wxWidgets / Phoenix

wxPython's Project Phoenix. A new implementation of wxPython, better, stronger, faster than he was before.
http://wxpython.org/
2.29k stars 515 forks source link

Unable to draw dashed lines after wxPython 4.0.7 #2011

Open jwdj opened 2 years ago

jwdj commented 2 years ago

Operating system: Windows 10 wxPython version & source: wxPython-4.1.1-cp38-cp38-win32 (installed using pip install -U wxPython) Python version & source: Python 3.8.10 (using installer) Description of the problem: Unable to draw dashed lines after wxPython 4.0.7 TypeError: GraphicsRenderer.CreatePen(): argument 1 has unexpected type 'Pen' According to the documentation GraphicsRenderer.CreatePen should accept a wx.Pen but it only accepts wx.GraphicsPen That would not be such an issue if wx.GraphicsPenInfo would provide a way to specify Dashes just like wx.Pen. Example below does work when using: pip install wxPython==4.0.7.post2 See here for actual usage.

Code Example (click to expand) ```python #!/usr/bin/env python3 import wx WX4 = wx.version().startswith('4') WX41 = WX4 and not wx.version().startswith('4.0') if WX4: wx_colour = wx.Colour else: wx_colour = wx.NamedColour class Frame(wx.Frame): def __init__(self, title): wx.Frame.__init__(self, None, title=title, size=(350,200)) linecap = 'butt' svg_stroke = 'black' line_width = 1 dasharray = (5,5) self.renderer = wx.GraphicsRenderer.GetDefaultRenderer() if WX41 and not dasharray: # GraphicsPenInfo does not have Dashes wxpen = wx.GraphicsPenInfo(wx_colour(svg_stroke)).Width(line_width) if linecap == 'butt': wxpen.Cap(wx.CAP_BUTT) elif linecap == 'round': wxpen.Cap(wx.CAP_ROUND) else: raise Exception('linecap %s not supported yet' % linecap) wxpen.Join(wx.JOIN_MITER) else: wxpen = wx.Pen(wx_colour(svg_stroke), line_width) if linecap == 'butt': wxpen.SetCap(wx.CAP_BUTT) elif linecap == 'round': wxpen.SetCap(wx.CAP_ROUND) else: raise Exception('linecap %s not supported yet' % linecap) if dasharray: wxpen.SetDashes(list(dasharray)) wxpen.SetStyle(wx.USER_DASH) wxpen.SetJoin(wx.JOIN_MITER) self.pen = self.renderer.CreatePen(wxpen) self.Bind(wx.EVT_PAINT, self.OnPaint) def OnPaint(self, evt): dc = wx.PaintDC(self) gc = wx.GraphicsContext.Create(dc) # make a path that contains a circle and some lines gc.SetPen(self.pen) path = gc.CreatePath() path.AddCircle(50.0, 50.0, 50.0) path.MoveToPoint(0.0, 50.0) path.AddLineToPoint(100.0, 50.0) path.MoveToPoint(50.0, 0.0) path.AddLineToPoint(50.0, 100.0) path.CloseSubpath() path.AddRectangle(25.0, 25.0, 50.0, 50.0) gc.StrokePath(path) app = wx.App(redirect=False) top = Frame("Dashed line") top.Show() app.MainLoop() ```
swt2c commented 2 years ago

Your example doesn't work for me even on wxPython 4.0.7:

(wxpy_407_env) throttle:~ stalbert$ python3 Phoenix/issue_2011.py 
Traceback (most recent call last):
  File "Phoenix/issue_2011.py", line 60, in <module>
    top = Frame("Dashed line")
  File "Phoenix/issue_2011.py", line 41, in __init__
    self.pen = self.renderer.CreatePen(wxpen)
TypeError: GraphicsRenderer.CreatePen(): argument 1 has unexpected type 'Pen'
swt2c commented 2 years ago

I can see why the new stuff doesn't work, but I would think your existing way to do it on 4.0.7 should still work - I just need to understand what that was, because your example doesn't work on 4.0.7.

jwdj commented 2 years ago

Hello swt2c. Thank you for looking into this issue. I have checked the attached example on another Windows-pc just to be sure, but the example does work on Windows with wxPython 4.0.7.post2. Maybe wxPython 4.0.7 was already broken on other platforms. At least I am happy that you get the same error as I did. It used to work this way.