【问题标题】:Why do I get a small window when I close a dialog in wxPython?为什么在 wxPython 中关闭对话框时会出现一个小窗口?
【发布时间】:2023-03-23 15:28:01
【问题描述】:

我有一个wx.Frame,它调用了一个wx.Dialog

现在,它们都相应地工作并且很好地打开。问题是,当他们这样做时,他们还会打开一个位于我框架左上角的小“窗口”,然后我无法用鼠标自动调整框架大小。关闭dialog 无效,因为那个小窗口仍然存在。

在我的wx.Frame 中,我有以下事件调用:

def OnTerminalSettings(self, event):
    """Open Terminal settings dialog"""
    dlg = TerminalSettingsDialog(self, wx.ID_ANY, "", settings=TerminalPanel(self).settings)
    dlg.ShowModal()
    dlg.Destroy()

TerminalSettingsDialog wx.Dialog 看起来像这样:

class TerminalSettingsDialog(wx.Dialog):
    """Simple dialog with common terminal settings."""

    def __init__(self, *args, **kwds):
        self.settings = kwds['settings']
        del kwds['settings']
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
        wx.Dialog.__init__(self, *args, **kwds)
        self.checkbox_echo = wx.CheckBox(self, wx.ID_ANY, "Local Echo")
        self.checkbox_unprintable = wx.CheckBox(self, wx.ID_ANY, "Show unprintable characters")
        self.radio_box_newline = wx.RadioBox(self, wx.ID_ANY, "Newline Handling", choices=["CR only", "LF only", "CR+LF"], majorDimension=0, style=wx.RA_SPECIFY_ROWS)
        self.button_ok = wx.Button(self, wx.ID_ANY, "OK")
        self.button_cancel = wx.Button(self, wx.ID_ANY, "Cancel")

        self.__set_properties()
        self.__do_layout()

        self.__attach_events()
        self.checkbox_echo.SetValue(self.settings.echo)
        self.checkbox_unprintable.SetValue(self.settings.unprintable)
        self.radio_box_newline.SetSelection(self.settings.newline)

    def __set_properties(self):
        self.SetTitle("Terminal Settings")
        self.radio_box_newline.SetSelection(0)
        self.button_ok.SetDefault()

    def __do_layout(self):
        sizer_2 = wx.BoxSizer(wx.VERTICAL)
        sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_4 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, "Input/Output"), wx.VERTICAL)
        sizer_4.Add(self.checkbox_echo, 0, wx.ALL, 4)
        sizer_4.Add(self.checkbox_unprintable, 0, wx.ALL, 4)
        sizer_4.Add(self.radio_box_newline, 0, 0, 0)
        sizer_2.Add(sizer_4, 0, wx.EXPAND, 0)
        sizer_3.Add(self.button_ok, 0, 0, 0)
        sizer_3.Add(self.button_cancel, 0, 0, 0)
        sizer_2.Add(sizer_3, 0, wx.ALL|wx.ALIGN_RIGHT, 4)
        self.SetAutoLayout(1)
        self.SetSizer(sizer_2)
        sizer_2.Fit(self)
        sizer_2.SetSizeHints(self)
        self.Layout()

    def __attach_events(self):
        self.Bind(wx.EVT_BUTTON, self.OnOK, id = self.button_ok.GetId())
        self.Bind(wx.EVT_BUTTON, self.OnCancel, id = self.button_cancel.GetId())

    def OnOK(self, events):
        """Update data with new values and close dialog."""
        self.settings.echo = self.checkbox_echo.GetValue()
        self.settings.unprintable = self.checkbox_unprintable.GetValue()
        self.settings.newline = self.radio_box_newline.GetSelection()
        self.EndModal(wx.ID_OK)

    def OnCancel(self, events):
        """Do not update data, but rather close dialog."""
        self.EndModal(wx.ID_CANCEL)

我不知道这是否重要,但框架包含一个顶部 wx.Panel,而顶部又包含另外两个 wx.Panels。我希望能够在其中一个这样的面板中拥有一个终端。

我从PySerial examples 获得了终端的代码,所以我猜他们工作得很好。

谁能帮帮我?

附录

这是TerminalPanel里面的代码:

class TerminalPanel(wx.Panel):
    def __init__(self, *args, **kwds):
        self.serial = serial.Serial()
        self.serial.timeout = 0.5    #make sure that the alive event can be checked from time to time
        self.settings = TerminalSetup()  #Placeholder for the settings
        self.thread = None
        self.alive = threading.Event()

        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Panel.__init__(self, *args, **kwds)
        TextPanel.text_ctrl_output = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE)

        self.__do_layout()
        # self.OnPortSettings(None)  #Call setup dialog on startup, opens port
        if not self.alive.isSet():
            self.Close()


    def StartThread(self):
        """Start the receiver thread."""
        self.thread = threading.Thread(target=self.ComPortThread)
        self.thread.setDaemon(1)
        self.alive.set()
        self.thread.start()


    def StopThread(self):
        """Stop the receiver thread, wait until it's finished."""
        if self.thread is not None:
            self.alive.clear()  #Clear alive event for thread
            self.thread.join()  #Wait until thread has finished
            self.thread = None  #Set flag as empty


    def __do_layout(self):
        """Set general layout """
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_1.Add(self.text_ctrl_output, 1, wx.EXPAND, 0)
        self.SetAutoLayout(1)
        self.SetSizer(sizer_1)
        self.Layout()

【问题讨论】:

    标签: wxpython panels


    【解决方案1】:
    dlg = TerminalSettingsDialog(self, wx.ID_ANY, "", settings=TerminalPanel(self).settings)
    

    每次创建对话框的实例时,此语句都会创建 TerminalPanel 的新实例,它是 self 的子代。那是你的额外窗口。如果你已经有一个 TerminalPanel 的实例,那么你可能应该从中获取设置对象,而不是创建一个新对象。

    【讨论】:

    • 非常有意义。我怎么做? (对不起,我是新手)--我附上TerminalPanel的代码
    • 假设TerminalPanel的初始实例是在框架中创建的,您应该在创建时保存对它的引用。像self.termPanel = TerminalPanel(self) 和稍后的OnTerminalSettings 你可以像这样使用它dlg = TerminalSettingsDialog(self, wx.ID_ANY, "", settings=self.termPanel.settings)
    • 谢谢@RobinDunn。实例TerminalPanel 是在另一个名为TopPanelwx.Dialog 类中创建的,而不是MainWindow wx.Frame。我如何考虑到这一点来相应地设置它?
    • 我想我明白了...settings=self.top_panel.terminal_panel.settings
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多