在Linux中,wx.PopupWindow在从wx.Dialog弹出时没有接收到任何鼠标事件?

0 投票
1 回答
686 浏览
提问于 2025-04-17 12:06


大家好。

我有一个小的Python图形界面程序,是基于wxPython 2.8.x做的。
这个程序创建了一个wx.Dialog窗口,并通过调用ShowModal()来显示这个对话框。
在某些情况下,这个wx.Dialog会显示一个包含wx.ListCtrl的wx.PopupWindow。
wx.PopupWindow显示得很正常,但问题来了。
wx.ListCtrl和它的父窗口wx.PopupWindow都无法接收到任何鼠标事件,
这导致用户在进行任何鼠标操作时,wx.ListCtrl和wx.PopupWindow都没有反应。

如果通过调用Show()来打开wx.Dialog,
上述情况就不会发生,wx.PopupWindow和wx.ListCtrl都能正常工作。

不过,在Windows版本的wxPython 2.8.x中,即使我们通过ShowModal()来显示wx.Dialog,
也不会出现上述情况,这种问题只在Linux上出现。

有没有什么建议?

谢谢。
这是我的源代码。
可能有点长,但测试上述情况很简单(只需复制粘贴)。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import wx



class TestPopupWindow(wx.PopupWindow): # modify here to change different Widget
    def __init__(self, *args, **kwargs):
        super(TestPopupWindow, self).__init__(*args, **kwargs)
        self.SetSize((200, 200))

        self.testButton = wx.Button(self, label='Test')

        self.testButton.Bind(wx.EVT_BUTTON, self.__onEvtButton, self.testButton)

        self.Show()

    def __onEvtButton(self, event):
        event.Skip()
        print 'PopupWindow: test button pushed!'
        self.Hide()


class TestDialog(wx.Dialog):
    def __init__(self, *args, **kwargs):
        wx.Dialog.__init__(self, *args, **kwargs)

        panel = wx.Panel(self)
        panel.SetAutoLayout(True)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Fit(panel)
        sizer.SetSizeHints(panel)
        panel.SetSizer(sizer)

        for i in xrange(2):
            ctrl = wx.TextCtrl(panel)
            sizer.Add(ctrl, 0, wx.ADJUST_MINSIZE|wx.EXPAND, 0)
        for i in xrange(2):
            ctrl = wx.ComboBox(panel)
            sizer.Add(ctrl, 0, wx.ADJUST_MINSIZE|wx.EXPAND, 0)

        self.openPopupWindowButton = wx.Button(panel, label='Open PopupWindow')
        sizer.Add(self.openPopupWindowButton, 0, 0, 0)

        standardDialogButtonSizer = wx.StdDialogButtonSizer()
        self.standardDialogButtonSizerOK = wx.Button(panel, wx.ID_OK)
        standardDialogButtonSizer.AddButton(self.standardDialogButtonSizerOK)
        self.standardDialogButtonSizerCancel = wx.Button(panel, wx.ID_CANCEL)
        standardDialogButtonSizer.AddButton(self.standardDialogButtonSizerCancel)
        standardDialogButtonSizer.Realize()
        sizer.Add(standardDialogButtonSizer, 0, wx.EXPAND, 0)

        panel.Layout()

        # event binding
        self.openPopupWindowButton.Bind(wx.EVT_BUTTON, self.__onEvtButtonOpenPopupWindow, self.openPopupWindowButton)

        self.popupWindow = None

    # event handler
    def __onEvtButtonOpenPopupWindow(self, event):
        event.Skip()

        if self.popupWindow is not None:
            self.popupWindow.Close()
        self.popupWindow = TestPopupWindow(self)



class TestFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        panel = wx.Panel(self)
        panel.SetAutoLayout(True)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Fit(panel)
        sizer.SetSizeHints(panel)
        panel.SetSizer(sizer)

        self.openButton = wx.Button(panel, label='Open Dialog')
        sizer.Add(self.openButton, 0, 0, 0)

        self.openPopupWindowButton = wx.Button(panel, label='Open PopupWindow')
        sizer.Add(self.openPopupWindowButton, 0, 0, 0)

        panel.Layout()

        # event binding
        self.openButton.Bind(wx.EVT_BUTTON, self.__onEvtButtonOpen, self.openButton)
        self.openPopupWindowButton.Bind(wx.EVT_BUTTON, self.__onEvtButtonOpenPopupWindow, self.openPopupWindowButton)

        self.Show()

        self.popupWindow = None

    # event handler
    def __onEvtButtonOpenPopupWindow(self, event):
        event.Skip()

        if self.popupWindow is not None:
            self.popupWindow.Close()
        self.popupWindow = TestPopupWindow(self)

    def __onEvtButtonOpen(self, event):
        event.Skip()
        dialog = TestDialog(self, title='TestDialog')
        result = dialog.ShowModal()
        if result == wx.ID_OK:
            print >>sys.stderr, 'OK!'
        else:
            print >>sys.stderr, 'Cancel!'



def main(argv=sys.argv[:]):
    app = wx.PySimpleApp()
    frame = TestFrame(None, title='TestFrame', style=wx.TAB_TRAVERSAL|wx.DEFAULT_FRAME_STYLE)
    app.SetTopWindow(frame)
    app.MainLoop()
    return 0



if __name__ == '__main__':
    sys.exit(main())

1 个回答

0

与其使用弹出窗口,不如直接显示第二个 wx.Dialog 对话框。或者可以打开一个新的窗口。弹出窗口在处理像 ListCtrl 这样的复杂控件时可能会有点奇怪。

撰写回答