弹出菜单位于wx.TextCtrl中的插入点位置

时间:2014-11-11 12:21:45

标签: python contextmenu wxwidgets popupmenu wx.textctrl

有人知道如何使用wxPython在TextCtrl对象中创建自定义上下文菜单吗?

目前,我可以创建一个自定义菜单,但是这个菜单出现在鼠标光标位置enter image description here,当原始菜单出现在文本光标位置enter image description here时按下[Menu]键enter image description here

1 个答案:

答案 0 :(得分:1)

好,

可以某种方式来做这个技巧这只适用于

  1. 当字体是等宽字体时(参见下面的代码),
  2. 当焦点线中没有制表符(“\ t”)时......
  3. 简单地说:将文本光标enter image description here的位置放入行/列坐标中,然后将它们乘以字符大小。这将提供所需的弹出菜单位置。

    import wx
    
    # Test context menu that should be displayed at the insertion point position 
    # in the TextCtrl object
    class CustomMenu(wx.Menu):
    
        def __init__(self):
            wx.Menu.__init__(self)
    
            # Add some items in the menu
            self.AppendItem(wx.MenuItem(self, wx.NewId(), 'This should be at the'))
            self.AppendItem(wx.MenuItem(self, wx.NewId(), 'insertion point'))
            self.AppendItem(wx.MenuItem(self, wx.NewId(), 'position...'))
    
    # Text area from which to open the custom context menu
    class TestTextCtrl(wx.TextCtrl):
    
        def __init__(self, parent):
            wx.TextCtrl.__init__(self, parent, style=wx.TE_MULTILINE)
    
            self.parent = parent
    
            # Set a monospaced font
            font = wx.Font(12, wx.MODERN, wx.NORMAL, wx.NORMAL)
            self.SetFont(font)
    
            # Get the character size (width and height)
            self.pixelSize = font.GetPixelSize()
    
            # Display some text
            self.SetValue("[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n"
                          "[Ctrl] key = custom popup menu \n"
                          "[Menu] key = original context menu \n")
    
            # Activate the [Ctrl] key stroke detection (1/2)
            self.Bind(wx.EVT_KEY_DOWN, self.OnKeyStroke)
    
        def OnKeyStroke(self, event):
    
            # Activate the [Ctrl] key stroke detection (2/2)
            if event.GetUnicodeKey() == wx.WXK_CONTROL:
    
                #######################################
                ##### Here is the interesting code ####
                #######################################
    
                # Get the scroll position in pixels
                scrollPosition = [
                    self.GetScrollPos(wx.HORIZONTAL),
                    self.GetScrollPos(wx.VERTICAL),
                    ]
    
                # Get the text cursor position in the text area (int)
                insertionPointPosition = self.GetInsertionPoint()
    
                # Convert it into a row/column position (2D tuple)
                insertionPointRowColumnPosition = self.PositionToXY(insertionPointPosition)
    
                # Calculate the popup menu position in pixels
                insertionPointPositionInPixels = []
                for i in range(2):
                    insertionPointPositionInPixels.append(
                #       (  row/column position    +   offset   ) * size of character - position of scroll in pixels)
                        (insertionPointRowColumnPosition[i] + i) * self.pixelSize[i] - scrollPosition[i]
                    )
    
                # Convert the position into a wx.Point object
                popupMenuPoint = wx.Point(
                    insertionPointPositionInPixels[0],
                    insertionPointPositionInPixels[1]
                )
    
                # Display the context menu at the given position
                self.PopupMenu(CustomMenu(), popupMenuPoint)
    
                ### We did it ! :) ###
    
                #######################################
                #######################################
                #######################################
    
            else:
                event.Skip()
    
    # Test frame
    class TestFrame(wx.Frame):
    
        def __init__(self):
            wx.Frame.__init__(self, None)
    
            # Create a text area
            TestTextCtrl(self)
    
            # Display the window
            self.Show(True)
    
    
    if __name__ == "__main__":
    
        # Create an application
        application = wx.App(False)
    
        # Create a frame
        TestFrame()
    
        # Launch the application
        application.MainLoop()
    

    更新#1 - >从font.GetPixelSize()

    获取的字符大小

    更新#2 - >使用self.GetScrollPos()

    在帐户下截取滚动条的位置