Всплывающее меню в позиции точки вставки в wx.TextCtrl

Кто-нибудь знает, как создать пользовательское контекстное меню в объекте TextCtrl, используя wxPython?

На данный момент я мог бы создать собственное меню, но оно появляется в позиции курсора мыши , когда оригинал появляется в позиции курсора текста при нажатии клавиши [Меню] ,

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

Другие вопросы по тегам