views:

120

answers:

1

Greetings;

I'm having a bit of trouble correctly instantiating an Array of System.Drawing.Point instances, and then adding the Array of Points to a GDI+ GraphicsPath instance using IronPython in a WinForms application. The following code compiles or builds correctly under SharpDevelop 3.2 with IronPython 2.6:

import System.Drawing
import System.Drawing.Drawing2D 
import System.Windows.Forms

from System import Array 
from System.Drawing import Pen, Point
from System.Drawing.Drawing2D import GraphicsPath, CustomLineCap
from System.Windows.Forms import *

class MainForm(Form):
    def __init__(self):
        self.InitializeComponent()

    def InitializeComponent(self):
        self.SuspendLayout()
        # 
        # MainForm
        # 
        self.ClientSize = System.Drawing.Size(284, 264)
        self.Name = "MainForm"
        self.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
        self.Text = "GDI Lines"
        self.Paint += self.MainFormPaint
        self.ResumeLayout(False)

    def MainFormPaint(self, sender, e):
        graphicContext = e.Graphics
        bluePen = Pen(Color.Blue, 1)

        points = Array.CreateInstance(Point, 9)
        points[0] = Point(10, 10)
        points[1] = Point(15, 10)
        points[2] = Point(20, 15)
        points[3] = Point(20, 20)
        points[4] = Point(15, 25)
        points[5] = Point(10, 25)
        points[6] = Point(5, 20)
        points[7] = Point(5, 15)
        points[8] = Point(10, 10)

        graphicsPath = GraphicsPath()
        graphicsPath.AddLines(points)
        graphicContext.SmoothingMode = SmoothingMode.AntiAlias

        lineCap = CustomLineCap(nil, graphicsPath)
        lineCap.BaseInset = 0
        lineCap.WidthScale = 1
        lineCap.StrokeJoin = LineJoin.Miter

        bluePen.CustomStartCap = lineCap
        bluePen.CustomEndCap = lineCap

        graphicContext.DrawLine(bluePen, 50, 150, 200, 150)
        graphicContext.DrawLine(bluePen, 150, 50, 150, 200)

        lineCap.Dispose()
        graphicsPath.Dispose()
        bluePen.Dispose()

Based on the code above, I was expecting to see two perpendicualr blue lines drawn, with a small ellipse at the end of each line. Using the current scipting code above, the GDI+ runtime error red X is drawn. What am I missing or doing incorrectly? Also, is there a simpler or more concise way of instantiating an Array of System.Drawing.Point values?

Thank you in advance for your time and help...

A: 

In all fairness, I must say that I did not "Answer my own question" or resolve this issue on my own, but was able to receive outside help from both Matt Ward and Michael Foord. My sincerest thanks to both Matt and Michael for their time, help and patience, and I really appreciate them writing back with their corrections.

The main issue that kept the MainForm.py script from running was the omission on my part of importing the Color class from the System.Drawing namespace, and the SmoothingMode and LineJoin Enumerations from the System.Drawing.Drawing2D namespace. Although my script does not directly instantiate any of the additional enumerations or class, they still must be loaded and referenced from their respective assemblies by the .NET DLR to make them accessible and usable within my script. (Note: Again, thanks to Matt for pointing this out to me; if there are any errors in the explanation, they are mine and not Matt's.)

The original Array instantiation of the GDI+ Point instances was correct, but a more succinct approach is shown in the corrected script below. (Note: Again, my thanks to Michael for pointing out the Array instantiation alternative.)

The corrected and working MainForm.py script is as follows:

import System.Drawing
import System.Drawing.Drawing2D 
import System.Windows.Forms

from System import Array 
from System.Drawing import Pen, Point, Color
from System.Drawing.Drawing2D import GraphicsPath, CustomLineCap, SmoothingMode, LineJoin
from System.Windows.Forms import *

class MainForm(Form):
    def __init__(self):
        self.InitializeComponent()

    def InitializeComponent(self):
        self.SuspendLayout()
        # 
        # MainForm
        # 
        self.ClientSize = System.Drawing.Size(284, 264)
        self.Name = "MainForm"
        self.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
        self.Text = "GDI+ CustomLineCaps"
        self.Paint += self.MainFormPaint
        self.ResumeLayout(False)

    def MainFormPaint(self, sender, e):
        graphics = e.Graphics
        bluePen = Pen(Color.Blue, 1)

        points = Array[Point] \
        ((Point(10, 10), Point(15, 10), Point(20, 15), \
          Point(20, 20), Point(15, 25), Point(10, 25), \
          Point(5, 20),  Point(5, 15),  Point(10, 10)))

        graphicsPath = GraphicsPath()
        graphicsPath.AddLines(points)
        graphics.SmoothingMode = SmoothingMode.AntiAlias 

        lineCap = CustomLineCap(None, graphicsPath)
        lineCap.BaseInset = 0
        lineCap.WidthScale = 1
        lineCap.StrokeJoin = LineJoin.Miter 

        bluePen.CustomStartCap = lineCap
        bluePen.CustomEndCap = lineCap

        graphics.DrawLine(bluePen, 50, 150, 200, 150)
        graphics.DrawLine(bluePen, 150, 50, 150, 200)

        lineCap.Dispose()
        graphicsPath.Dispose()
        bluePen.Dispose()
ClockEndGooner