Wxpython:在工具栏按钮下方定位一个菜单

5
在wx.ToolBar中,我有一个CheckLabelTool,当鼠标单击时,我希望菜单直接在其下面弹出。我试图获取工具的位置以便设置菜单的位置,但是我尝试过的所有方法(如GetEventObject、GetPosition等)都只给我返回了工具栏的位置,所以菜单从工具栏下弹出,但是离相关工具很远。你有什么建议吗?如果有更好的选择,我需要该工具具备切换和位图功能,但我并不固定于CheckLabelTool。
谢谢!
1个回答

6
请阅读wxpython.org上关于PopupMenu方法的部分:

“在指定的坐标相对于此窗口时弹出给定的菜单,并在用户关闭菜单后返回控制。如果选择了菜单项,则将生成相应的菜单事件并像往常一样进行处理。如果给出默认位置,则将使用鼠标光标的当前位置。”

您需要绑定到您的检查工具的EVT_MENU事件。一旦选中工具按钮,您可以弹出菜单。如果您不指定弹出窗口的位置,则会使用鼠标的当前位置,这正是您想要的。
如果您希望菜单在与鼠标无关的预定位置弹出,您可以获取工具栏的屏幕位置并添加偏移量。
让我们看看代码:
[编辑:为了展示如何计算工具栏上任意点的位置,我已经修改了代码,一旦你点击一个工具,就会计算并显示工具栏上各个点。菜单出现在所点击按钮的右下角。这对于我在Windows上有效。我很好奇它在其他平台上是否表现不佳。]
import wx

class ViewApp(wx.App):
    def OnInit(self):
        self.frame = ToolFrame(None, -1, "Test App")    
        self.frame.Show(True)
        return True        

class MyPopupMenu(wx.Menu):
    def __init__(self, parent):
        wx.Menu.__init__(self)

        self.parent = parent

        minimize = wx.MenuItem(self, wx.NewId(), 'Minimize')
        self.AppendItem(minimize)
        self.Bind(wx.EVT_MENU, self.OnMinimize, id=minimize.GetId())

    def OnMinimize(self, event):
        self.parent.Iconize()

class ToolFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(350, 250))

        self.toolbar = self.CreateToolBar()
        self.tool_id = wx.NewId()
        for i in range(3):
            tool_id = wx.NewId()
            self.toolbar.AddCheckLabelTool(tool_id, 'Tool', wx.EmptyBitmap(10,10))
            self.toolbar.Bind(wx.EVT_MENU, self.OnTool, id=tool_id)
        self.toolbar.Realize()
        self.Centre()
        self.Show()

    def OnTool(self, event):
        if event.IsChecked():
            # Get the position of the toolbar relative to
            # the frame. This will be the upper left corner of the first tool
            bar_pos = self.toolbar.GetScreenPosition()-self.GetScreenPosition()

            # This is the position of the tool along the tool bar (1st, 2nd, 3rd, etc...)
            tool_index = self.toolbar.GetToolPos(event.GetId())

            # Get the size of the tool
            tool_size = self.toolbar.GetToolSize()

            # This is the upper left corner of the clicked tool
            upper_left_pos = (bar_pos[0]+tool_size[0]*tool_index, bar_pos[1])

            # Menu position will be in the lower right corner
            lower_right_pos = (bar_pos[0]+tool_size[0]*(tool_index+1), bar_pos[1]+tool_size[1])

            # Show upper left corner of first tool in black
            dc = wx.WindowDC(self)
            dc.SetPen(wx.Pen("BLACK", 4))
            dc.DrawCircle(bar_pos[0], bar_pos[1], 4)        

            # Show upper left corner of this tool in blue
            dc.SetPen(wx.Pen("BLUE", 4))
            dc.DrawCircle(upper_left_pos[0], upper_left_pos[1], 4)        

            # Show lower right corner of this tool in green
            dc.SetPen(wx.Pen("GREEN", 4))
            dc.DrawCircle(lower_right_pos[0], lower_right_pos[1], 4)        

            # Correct for the position of the tool bar
            menu_pos = (lower_right_pos[0]-bar_pos[0],lower_right_pos[1]-bar_pos[1])

            # Pop up the menu
            self.PopupMenu(MyPopupMenu(self), menu_pos)

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

这段代码的部分来自这里


感谢您的回复。问题不在于如何打开菜单,而是当我无法获取工具栏中单个工具的位置(您答案中的“添加偏移量”部分)时如何定位它。我已经找到了这个特定问题的解决方法,但是将来,我仍然想知道如何获取工具栏中工具的位置(以像素为单位),或者是否可能。 - kkeogh
请查看编辑。现在它将向您显示所单击工具的左上角和右下角。菜单将出现在右下角。 - Mathieu
在Mint Linux上使用gnome运行良好。 - Alan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接