wxPython - линии, нарисованные в контексте устройства, исчезают при изменении фокуса

1

Я написал это маленькое приложение, которое рисует линии между двумя точками, выбранными пользователем, и работает, но как я могу сохранить линии, которые я рисую, исчезая всякий раз, когда окно сворачивается или закрывается другим открытым окном?

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()
Теги:
wxpython

2 ответа

0

Ваша проблема в том, что вы рисуете только, когда пользователь нажимает. Изменение размера/стирание (когда другое окно покрывает ваши) проблемы связаны с тем, что ваше окно не поддерживает "буфер", который он может перерисовать.

Здесь я изменил ваш образец, кажется, работает нормально.

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()
0

Вы должны структурировать свою программу по-разному в среде графического интерфейса. Как правило, вы поддерживаете структуру данных, называемую вашей моделью. В вашем случае у вас уже есть один, self.points. Затем вы рисуете только окно в ответ на событие рисования. Система окон будет посылать вам события рисования, когда окно нуждается в рисовании, в том числе когда оно отображается первым, когда оно максимизировано, и когда оно открывается из-под другого окна.

В вашей программе вы привязываете событие LeftDown к функции, которая изменяет self.points и делает это недействительным, что обычно приводит к тому, что система оконной обработки отправляет вам события рисования. Вы привязываете событие Paint к функции, которая рисует окно.

  • 0
    Что вы подразумеваете под "делает недействительным окно"?
  • 1
    В оконном графическом интерфейсе оконная система отслеживает, какие части окон правильно окрашены, а какие нет. Когда ваша базовая модель изменяется, вы не рисуете прямо в окне. Вместо этого вы сообщаете оконной системе, что вы больше не правильно рисуете. Это называется «аннулирование окна». Затем он отправляет вам события рисования, чтобы перекрасить его.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню