【问题标题】:Popup menu at the insertion point position in a wx.TextCtrlwx.TextCtrl中插入点位置的弹出菜单
【发布时间】:2014-11-11 12:21:44
【问题描述】:

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

目前,我可以创建一个自定义菜单,但这个菜单出现在鼠标光标位置,而原始菜单出现在文本光标位置当点击[Menu]键时。

【问题讨论】:

    标签: python contextmenu wxwidgets popupmenu wx.textctrl


    【解决方案1】:

    好的,

    可以以某种方式做到这一点这只能工作

    1. 当字体为等宽字体时(参见下面的代码),
    2. 当焦点行中没有制表符 ("\t") 时...

    简单地说:将文本光标 的位置转换为行/列坐标并将它们乘以字符大小。这给出了所需的弹出菜单位置。

    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() 考虑滚动条的位置

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      相关资源
      最近更新 更多