【问题标题】:Drawing with cairo in wxpython在 wxpython 中使用 cairo 绘图
【发布时间】:2014-05-14 17:31:26
【问题描述】:

我对 python 相当陌生,正在尝试使用 cairo 和 wxpython 编写一个简单的程序。我习惯于将 cairo 与 gtk 和 C 一起使用,但我发现自己很困惑。

我用以下代码为自己构建了一个简单的用户界面:

import wx

class Frame(wx.Frame):

    def __init__(self, *args, **kwargs):
        super(Frame, self).__init__(*args, **kwargs) 
        self.InitUI()

    def InitUI(self):
        #----------------------------------------------------
        # Build menu bar and submenus   
        menubar = wx.MenuBar()
        # file menu containing quit menu item
        fileMenu = wx.Menu() 
        quit_item = wx.MenuItem(fileMenu, wx.ID_EXIT, '&Quit\tCtrl+W')
        fileMenu.AppendItem(quit_item)
        self.Bind(wx.EVT_MENU, self.OnQuit, quit_item)
        menubar.Append(fileMenu, '&File')      

        # help menu containing about menu item
        helpMenu = wx.Menu() 
        about_item = wx.MenuItem(helpMenu, wx.ID_ABOUT, '&About\tCtrl+A')
        helpMenu.AppendItem(about_item)
        self.Bind(wx.EVT_MENU, self.OnAboutBox, about_item)
        menubar.Append(helpMenu, '&Help')     

        self.SetMenuBar(menubar)

        #----------------------------------------------------
        # Build window layout

        panel = wx.Panel(self)        
        #panel.SetBackgroundColour('yellow')
        vbox = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(vbox)        

        midPan = wx.Panel(panel)
        #midPan.SetBackgroundColour('blue')
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        vbox.Add(midPan, 1, wx.EXPAND | wx.ALL, 12)
        midPan.SetSizer(hbox)      

        smallPan = wx.Panel(panel)
        #smallPan.SetBackgroundColour('red')
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        vbox.Add(smallPan, 0, wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT|wx.BOTTOM, 12)
        smallPan.SetSizer(hbox2)   

        #----------------------------------------------------
        # Place buttons in correct box corresponding with panel

        close_button = wx.Button(smallPan, wx.ID_CLOSE)
        self.Bind(wx.EVT_BUTTON, self.OnQuit, close_button)

        hbox2.Add(close_button)
        #----------------------------------------------------
        # Set window properties

        self.SetSize((1600, 1200))
        self.SetTitle('PROGRAM NAME')
        self.Centre()

    def OnQuit(self, e):
        self.Close()

def main():
    ex = wx.App()
    f = Frame(None)
    f.Show(True)  
    ex.MainLoop()  

if __name__ == '__main__':
    main()

我希望能够在名为 midPan 的面板中绘图。如何添加 OnDraw 函数并链接信号处理程序?

非常感谢您的帮助。

【问题讨论】:

  • 这是你的SSCCE吗?
  • 代码工作正常,只需设置一个窗口。 AboutDialog 无关紧要。我的问题是弄清楚如何添加 OnPaint 函数以在 gui 上绘图,并让它出现在我的 midPan 区域中。我注释掉了面板的颜色以帮助我查看布局。

标签: python wxpython cairo pycairo


【解决方案1】:

如果您习惯于过程式编程,那么您会感到困惑 是自然的。 Python 是一种 OOP 语言,并且在 OOP 中进行编码 语言完全不同。我已经清理并更新了 提供的例子。用作绘图区域的面板 绘制三个彩色矩形。您没有提供 OnAboutBox() 方法的实现,因此,我有 注释掉该行。

#!/usr/bin/python import wx import wx.lib.wxcairo import cairo class DrawingArea(wx.Panel): def __init__ (self , *args , **kw): super(DrawingArea , self).__init__ (*args , **kw) self.SetDoubleBuffered(True) self.Bind(wx.EVT_PAINT, self.OnPaint) def OnPaint(self, e): dc = wx.PaintDC(self) cr = wx.lib.wxcairo.ContextFromDC(dc) self.DoDrawing(cr) def DoDrawing(self, cr): cr.set_source_rgb (0.2 , 0.23 , 0.9) cr.rectangle(10 , 15, 90, 60) cr.fill() cr.set_source_rgb(0.9 , 0.1 , 0.1) cr.rectangle(130 , 15, 90, 60) cr.fill() cr.set_source_rgb(0.4 , 0.9 , 0.4) cr.rectangle(250 , 15, 90, 60) cr.fill() class Frame(wx.Frame): def __init__(self, *args, **kwargs): super(Frame, self).__init__(*args, **kwargs) self.InitUI() def InitUI(self): #---------------------------------------------------- # Build menu bar and submenus menubar = wx.MenuBar() # file menu containing quit menu item fileMenu = wx.Menu() quit_item = wx.MenuItem(fileMenu, wx.ID_EXIT, '&Quit\tCtrl+W') fileMenu.AppendItem(quit_item) self.Bind(wx.EVT_MENU, self.OnQuit, quit_item) menubar.Append(fileMenu, '&File') # help menu containing about menu item helpMenu = wx.Menu() about_item = wx.MenuItem(helpMenu, wx.ID_ABOUT, '&About\tCtrl+A') helpMenu.AppendItem(about_item) #~ self.Bind(wx.EVT_MENU, self.OnAboutBox, about_item) menubar.Append(helpMenu, '&Help') self.SetMenuBar(menubar) #---------------------------------------------------- # Build window layout panel = wx.Panel(self) vbox = wx.BoxSizer(wx.VERTICAL) panel.SetSizer(vbox) midPan = DrawingArea(panel) vbox.Add(midPan, 1, wx.EXPAND | wx.ALL, 12) smallPan = wx.Panel(panel) hbox2 = wx.BoxSizer(wx.HORIZONTAL) vbox.Add(smallPan, 1, wx.EXPAND|wx.ALL, 12) smallPan.SetSizer(hbox2) #---------------------------------------------------- # Place buttons in correct box corresponding with panel close_button = wx.Button(smallPan, wx.ID_CLOSE) self.Bind(wx.EVT_BUTTON, self.OnQuit, close_button) hbox2.Add(close_button) #---------------------------------------------------- # Set window properties #~ self.SetSize((1600, 1200)) self.SetSize((400, 250)) #~ self.Maximize() self.SetTitle('PROGRAM NAME') self.Centre() def OnQuit(self, e): self.Close() def main(): ex = wx.App() f = Frame(None) f.Show(True) ex.MainLoop() if __name__ == '__main__': main()

为了进行绘图,我们创建了一个自定义类,该类将用作 绘图区。它继承自 wx.Panel 小部件。

class DrawingArea(wx.Panel):
    
    def __init__ (self , *args , **kw):
        super(DrawingArea , self).__init__ (*args , **kw)
        
        self.SetDoubleBuffered(True)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
...

这是我们用于绘图的自定义类。在构造函数中 我们将绘制事件绑定到OnPaint() 方法。

def OnPaint(self, e):
        
    dc = wx.PaintDC(self)
    cr = wx.lib.wxcairo.ContextFromDC(dc)
    self.DoDrawing(cr)  

在OnPaint() 方法中,我们创建了一个cairo 绘图 上下文并将实际绘图代码委托给DoDrawing() 方法。

midPan = DrawingArea(panel)
vbox.Add(midPan, 1, wx.EXPAND | wx.ALL, 12)

绘图区域被创建并添加到垂直框。

#~ self.SetSize((1600, 1200))
self.SetSize((400, 250))
#~ self.Maximize()

最后说明:如果您想最大化显示窗口,请调用Maximize() 方法。电脑屏幕有不同的尺寸。

【讨论】:

    【解决方案2】:

    如Very Simple Drawing 示例中所述,使用 wx.EVT_PAINT;

    将 OnPaint 绑定添加到您的 midPan:

        # (...)
        midPan = wx.Panel(panel)
        #midPan.SetBackgroundColour('blue')
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        vbox.Add(midPan, 1, wx.EXPAND | wx.ALL, 12)
        midPan.SetSizer(hbox)
        # binding here:
        midPan.Bind(wx.EVT_PAINT, self.OnPaint)
        # (...) rest of code
    

    并定义您的 OnPaint 代码:

       # (...)
       def OnQuit(self, e):
          self.Close()
    
       # your OnPaint():
       def OnPaint(self,event):
          dc = wx.PaintDC(event.GetEventObject())
          dc.Clear()
          # set up your pen
          dc.SetPen(wx.Pen("BLACK", 4))
          # draw whatever you like
          dc.DrawLine(0, 0, 50, 50)
    
       # (...) rest of code
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多