1

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

目前,我可以创建一个自定义菜单,但这个菜单出现在鼠标光标位置,而当点击 [Menu] 键在此处输入图像描述时,原来的菜单出现在文本光标位置。在此处输入图像描述在此处输入图像描述

4

1 回答 1

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()

于 2014-11-14T13:40:02.567 回答