【问题标题】:How to convince the mouse right click popup menu to show near the mouse cursor position in wxPython?如何说服鼠标右键单击弹出菜单在wxPython中显示在鼠标光标位置附近?
【发布时间】:2021-02-17 10:48:02
【问题描述】:

我有一个使用 SplitterWindow 的 wx 框架(该框架还有主菜单、工具栏、状态栏——但这与这里无关)。一切都按预期工作,除了按钮上的鼠标右键单击弹出菜单,因为弹出菜单显示在屏幕上明显随机的位置 - 并且在将框架移动到第二个屏幕(监视器)时出现在“负”随机位置。 “显然”是指弹出菜单的位置似乎与实际的按钮(或框架)位置有些相关,但与某些因素相乘——主屏幕为正,第二个为负。

我只在 Windows 10 64bit / Python 3.9.0 64bit / wx '4.1.1 msw (phoenix) wxWidgets 3.1.5' 上运行代码。框架代码的第一行是通过 wxGlade 生成的,所以这可能与最初生成框架代码的特定方式有关。

我创建了一个精简的测试代码,如下所示,它在鼠标右键单击弹出菜单方面模仿真实代码的确切情况。在这个测试代码中,我将按钮放在了第二个窗格中,但它在任何窗格中的行为都相同。

我在其他简单的 wx 示例代码上尝试了相同的弹出菜单代码,但没有使用 SplitterWindow,并且弹出行为正常。我应该在下面的测试代码中更改或改进什么?

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import wx

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((400, 300))
        self.SetTitle("test frame")

        sizer_0 = wx.BoxSizer(wx.HORIZONTAL)
        self.window_1 = wx.SplitterWindow(self, wx.ID_ANY)
        self.window_1.SetMinimumPaneSize(20)
        sizer_0.Add(self.window_1, 1, wx.EXPAND, 0)

        self.pane_1 = wx.Panel(self.window_1, wx.ID_ANY)
        sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
        self.pane_2 = wx.Panel(self.window_1, wx.ID_ANY)
        sizer_2 = wx.BoxSizer(wx.HORIZONTAL)

        self.button = wx.Button(self.pane_2, wx.ID_ANY, "test button")
        sizer_2.Add(self.button, 0, 0, 0)

        self.pane_1.SetSizer(sizer_1)
        self.pane_2.SetSizer(sizer_2)
        self.window_1.SplitVertically(self.pane_1, self.pane_2)
        self.SetSizer(sizer_0)
        self.Layout()

        self.Bind(wx.EVT_CONTEXT_MENU, self.OnButtonContextMenu, self.button)

    def OnButtonContextMenu(self, event):
        self.PopupMenu(ButtonContext(self), event.GetPosition())

##

class ButtonContext(wx.Menu):
    def __init__(self, parent):
        super(ButtonContext, self).__init__()
        self.parent = parent
 
        button_popup = wx.MenuItem(self, wx.ID_ANY, 'test popup')
        self.Append(button_popup)
        self.Bind(wx.EVT_MENU, self.button_action, button_popup)
 
    def button_action(self, event):
        event.Skip()

##

class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

##

if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()

【问题讨论】:

  • 使用self.PopupMenu(ButtonContext(self)) 丢失event.GetPosition(),菜单将集中在按钮本身的parent 上。
  • 是的,这行得通。您可以将此作为答案,所以我可以接受:)谢谢。

标签: python wxpython


【解决方案1】:

这有点令人费解,但我认为您通过将event.GetPosition() 传递给class ButtonContext 来覆盖InvokingWindowwx.Menu 的位置。

简而言之,如果您删除该参数 event.GetPosition() 并使用 self.PopupMenu(ButtonContext(self)) 调用它,它将默认为父窗口,即按钮本身。
结果是它始终会关注您刚刚右键单击的按钮。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-22
    • 2014-11-23
    • 1970-01-01
    • 1970-01-01
    • 2012-03-15
    • 2011-08-27
    • 2019-06-14
    • 1970-01-01
    相关资源
    最近更新 更多