wxPython - 改变焦点时通过设备上下文绘制的线条消失

2 投票
2 回答
1242 浏览
提问于 2025-04-15 18:13

我写了一个小程序,可以在用户选择的两个点之间画线,程序运行得很好。但是我想知道,怎么才能让我画的线在窗口被最小化或者被其他窗口遮住时不消失呢?

class SimpleDraw(wx.Frame):
  def __init__(self, parent, id, title, size=(640, 480)):
    self.points = []
    wx.Frame.__init__(self, parent, id, title, size)

    self.Bind(wx.EVT_LEFT_DOWN, self.DrawDot)

    self.SetBackgroundColour("WHITE")
    self.Centre()
    self.Show(True)

  def DrawDot(self, event):
    self.points.append(event.GetPosition())
    if len(self.points) == 2:
        dc = wx.ClientDC(self)
        dc.SetPen(wx.Pen("#000000", 10, wx.SOLID))
        x1, y1 = self.points[0]
        x2, y2 = self.points[1]
        dc.DrawLine(x1, y1, x2, y2)
        # reset the list to empty
        self.points = []

if __name__ == "__main__":
  app = wx.App()
  SimpleDraw(None, -1, "Title Here!")
  app.MainLoop()

2 个回答

0

在图形用户界面(GUI)环境中,你需要以不同的方式来组织你的程序。通常,你会维护一个叫做“模型”的数据结构。在你的情况下,你已经有了一个初步的模型,self.points。然后,你只在窗口需要绘制的时候进行绘图,这种情况被称为“绘制事件”。窗口系统会在窗口需要绘制的时候发送给你这些绘制事件,比如窗口第一次显示时、窗口被最大化时,或者当窗口从其他窗口下面显示出来时。

在你的程序中,你需要把“鼠标左键按下”这个事件绑定到一个函数上,这个函数会修改self.points并让窗口失效,这样通常会导致窗口系统发送给你绘制事件。你还需要把“绘制”事件绑定到一个函数上,这个函数负责在窗口上进行绘图。

1

你的问题在于你在用户点击的时候才进行绘图。当其他窗口覆盖你的窗口时,出现的调整大小或擦除的问题,是因为你的窗口没有保持一个“缓冲区”,这样它就无法重新绘制。

在这里,我对你的示例做了一些修改,似乎运行得不错。

import wx

class SimpleDraw(wx.Frame):
    def __init__(self, parent, id, title, size=(640, 480)):
        self.points = []
        wx.Frame.__init__(self, parent, id, title, size)

        self.Bind(wx.EVT_LEFT_DOWN, self.DrawDot)
        self.Bind(wx.EVT_PAINT, self.Paint)

        self.SetBackgroundColour("WHITE")
        self.Centre()
        self.Show(True)
        self.buffer = wx.EmptyBitmap(640, 480)  # draw to this
        dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
        dc.Clear()  # black window otherwise


    def DrawDot(self, event):
        self.points.append(event.GetPosition())
        if len(self.points) == 2:
            dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
            dc.Clear()
            dc.SetPen(wx.Pen("#000000", 10, wx.SOLID))
            x1, y1 = self.points[0]
            x2, y2 = self.points[1]
            dc.DrawLine(x1, y1, x2, y2)
            # reset the list to empty
            self.points = []


    def Paint(self, event):
        wx.BufferedPaintDC(self, self.buffer)


if __name__ == "__main__":
    app = wx.App(0)
    SimpleDraw(None, -1, "Title Here!")
    app.MainLoop()

撰写回答