wxpython:打开关联菜单时,如何将TextCtrl中的插入符号移动到鼠标位置

wxpython:打开关联菜单时,如何将TextCtrl中的插入符号移动到鼠标位置,python,wxpython,caret,textctrl,Python,Wxpython,Caret,Textctrl,在wxpython中,TextCtrl上下文菜单的默认行为是插入符号移动到TextCtrl中右键单击的位置。当我覆盖EVT_上下文菜单事件并创建自己的菜单时,此行为将丢失。有没有一个简单的方法来改变这一点 我的目标是允许标记右键单击的句子或段落,但当前行为要求用户首先左键单击相关的句子/段落以移动插入符号,然后右键单击以选择要标记的内容 相关代码: self.textbox.Bind(wx.EVT_CONTEXT_MENU, self.textbox_context_menu) def tex

在wxpython中,TextCtrl上下文菜单的默认行为是插入符号移动到TextCtrl中右键单击的位置。当我覆盖EVT_上下文菜单事件并创建自己的菜单时,此行为将丢失。有没有一个简单的方法来改变这一点

我的目标是允许标记右键单击的句子或段落,但当前行为要求用户首先左键单击相关的句子/段落以移动插入符号,然后右键单击以选择要标记的内容

相关代码:

self.textbox.Bind(wx.EVT_CONTEXT_MENU, self.textbox_context_menu)

def textbox_context_menu(self, event):
    """ show context menu when right-clicking on text """
    menu = wx.Menu()

    menu.Append(self.mark_sentence_id, "mark sentence")
    menu.Append(self.mark_paragraph_id, "mark paragraph")

    self.PopupMenu(menu)
编辑:这里是一个可以执行的最低限度示例:

import wx
import wx.richtext as rt


class MCVE(wx.App):
    """ App """
    def OnInit(self):
        frame = Frame()
        frame.Show()
        return True


class Frame(wx.Frame):
    """ Frame """
    def __init__(self):
        style = wx.SYSTEM_MENU | wx.CAPTION | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.RESIZE_BORDER
        super(Frame, self).__init__(parent=None, title="LabelingTool", style=style, size=(800, 600))
        self.panel = Panel(parent=self)


class Panel(wx.Panel):
    """ Panel """
    def __init__(self, parent):
        super(Panel, self).__init__(parent)
        # textbox
        hboxsizer = wx.BoxSizer(wx.HORIZONTAL)
        text = "Lorem Ipsum\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean eget enim vitae elit convallis ultrices. Sed vestibulum in metus id tempus. Phasellus tincidunt risus elit, id sagittis erat placerat quis. Donec ac porta tortor, non varius purus. Suspendisse euismod auctor maximus. Suspendisse nec orci vel dui posuere ultrices. Vivamus dictum vel enim nec interdum. Nunc tincidunt nulla sed facilisis suscipit. Nunc eget nisi ut turpis venenatis faucibus.\n\nInteger mauris nulla, malesuada quis lacus vitae, condimentum tincidunt dui. Aliquam non nisi aliquam, vulputate dolor ut, fringilla ligula. Nulla vitae tellus sit amet nulla ultrices pellentesque eu vitae lectus. Aliquam fringilla mauris tortor, et maximus lorem bibendum quis. Nam in magna gravida, accumsan libero accumsan, feugiat nisl. Donec tincidunt, tortor ut aliquam convallis, urna odio imperdiet ligula, dignissim vulputate ligula diam sit amet tortor. Ut a eros risus.\n\nCras et erat sodales, tempus nulla a, vulputate metus. Maecenas lacinia, nulla ac congue pharetra, lorem nibh pharetra metus, eu porttitor turpis leo ut lectus. Proin luctus rutrum mi id pharetra. Suspendisse aliquet id est nec efficitur. Maecenas dolor dui, vulputate et pulvinar at, venenatis id lorem. Praesent vel nisi ultrices massa rhoncus vestibulum. Nunc imperdiet consectetur pharetra. In cursus nec massa nec finibus. Aliquam et ligula bibendum, sodales mauris a, efficitur sapien. Ut mattis et ipsum eget sodales. Vestibulum maximus libero id ipsum placerat interdum at luctus risus. In finibus accumsan nunc, vitae posuere est interdum quis. Vivamus sed neque metus. Etiam fringilla efficitur lacus, vel aliquam purus lobortis vitae. Donec ut placerat orci. Etiam efficitur efficitur eleifend.\n\nAenean in imperdiet nisl. Donec dapibus neque tincidunt, fringilla velit vel, vestibulum velit. Sed at lorem id tortor accumsan interdum eu ut orci. Aenean convallis aliquet libero eu congue. In dapibus posuere massa, quis finibus neque volutpat et. Integer non massa tristique, gravida justo id, accumsan nibh. Ut ac nisl purus. Integer vestibulum sem in ante pellentesque, ac interdum augue faucibus.\n\nInteger bibendum eros vitae aliquam venenatis. Integer feugiat orci eu metus placerat, ut dictum leo posuere. Vivamus eget ligula vitae ante porttitor cursus. Nulla consectetur enim eu nisi aliquam mollis. Aliquam elementum consequat mauris, dignissim tempus libero sodales eu. In ultrices ullamcorper nulla, vel aliquet est vestibulum non. Nullam nec est ante. Phasellus eleifend lacinia nulla nec ultricies."
        self.textbox = rt.RichTextCtrl(parent=self, value=text, style=wx.TE_MULTILINE | wx.TE_READONLY)
        self.textbox.Bind(wx.EVT_CONTEXT_MENU, self.textbox_context_menu)
        hboxsizer.Add(self.textbox, proportion=1, flag=wx.EXPAND)
        self.SetSizerAndFit(hboxsizer)
        # event handling
        self.tag_sentence_id = 100
        self.tag_paragraph_id = 200
        self.Bind(wx.EVT_MENU, self.menu_event)

    def textbox_context_menu(self, event):
        """ show context menu when right-clicking on text """
        menu = wx.Menu()
        menu.Append(self.tag_sentence_id, "tag sentence")
        menu.Append(self.tag_paragraph_id, "tag paragraph")
        self.PopupMenu(menu)

    def menu_event(self, event):
        """ handle context menu events """
        event_id = event.GetId()
        self.tag(event_id)

    def tag(self, event_id):
        # get caret position
        caret_position = self.textbox.GetCaretPosition()+1
        # tag by event
        if event_id == self.tag_paragraph_id:
            paragraph = self.find_paragraph(caret_position)
            start = self.textbox.GetValue().find(paragraph)
            end = start + len(paragraph)
            self.apply_tag((start, end))
        elif event_id == self.tag_sentence_id:
            sentence = self.find_sentence(caret_position)
            start = self.textbox.GetValue().find(sentence.strip())
            end = start + len(sentence.strip())
            self.apply_tag((start, end))

    def apply_tag(self, position):
        self.textbox.SetStyle(position[0], position[1], wx.TextAttr(colText=wx.WHITE, colBack=wx.BLACK))

    def find_paragraph(self, caret_position):
        paragraphs = self.textbox.GetValue().split("\n\n")
        for paragraph in paragraphs:
            paragraph = paragraph.strip()
            start = self.textbox.GetValue().find(paragraph)
            end = start + len(paragraph)
            if start < caret_position < end:
                return paragraph

    def find_sentence(self, caret_position):
        sentences = self.find_paragraph(caret_position).split(".")
        for sentence in sentences:
            sentence = sentence.strip()
            start = self.textbox.GetValue().find(sentence)
            end = start + len(sentence)
            # append dot if applicable
            if self.textbox.GetValue()[end] == ".":
                sentence += "."
            if start < caret_position < end:
                return sentence


if __name__ == "__main__":
    app = MCVE()
    app.MainLoop()
导入wx
将wx.richtext作为rt导入
MCVE类(wx.App):
“应用程序”
def OnInit(自身):
frame=frame()
frame.Show()
返回真值
类框架(wx.Frame):
“帧”
定义初始化(自):
style=wx.SYSTEM_菜单| wx.CAPTION | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.RESIZE_BORDER
super(Frame,self)。uuu init_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(父项=None,title=“LabelingTool
self.panel=panel(父级=self)
类面板(wx.Panel):
“面板”
定义初始化(自身,父级):
超级(面板,自我).\uuuu初始化\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
#文本框
hboxsizer=wx.BoxSizer(wx.HORIZONTAL)
文本=“Lorem Ipsum \n \n Lorem Ipsum door sit amet,奉献精英。埃尼安·埃吉特·埃尼姆·维塔特·埃利特·康瓦利斯·乌尔特里斯。内翻前庭。这是一个很好的例子。Donec ac porta tortor,非静脉曲张。尤伊斯莫·马克西姆斯悬浮体拍卖行。因特殊原因导致的紧急情况。这句话的意思是:“活下去。”。未经许可的设施未使用。如果你不喜欢威尼斯的屠宰场。\n\n如果你喜欢毛里斯·努拉(mauris nulla),那么你可以喝一杯调味酒。非尼西阿利夸姆,秃鹫多洛,流苏利古拉。你的生命告诉我们,你的生命就是你的生命。阿利奎姆·弗里利亚·莫里斯·托托,以及最大的奥勒姆·比本杜姆·奎斯。不,不,不,不,不,不,不,不。请不要吃苦头,不要吃苦头,不要吃苦头,不要吃苦头,不要吃苦头。这是一个厄洛斯之神。\n\n这是一个苏打水,一个空的温度,一个空的温度。梅塞纳斯·拉西尼亚(Maecenas lacinia)、纳拉·康格·法雷特拉(nulla ac congue pharetra)、洛雷姆·尼布·法雷特拉·梅特斯(lorem nibh pharetra metus)、欧盟港口(eu porttitor turpis leo ut lectus)。罗汉果原生质体。吊牌的有效性。梅塞纳斯·多洛尔酒后驾车,在维尼那提斯岛的一个城市。前庭后斜肌按摩术。法雷特拉帝国。在cursus nec massa nec finibus。Aliquam和ligula bibendum、sodales mauris a、efficitur sapien。我们的马蒂斯和伊普苏姆是苏打水。大前庭同侧前庭位于luctus risus的中间。在菲尼布斯·阿库姆桑·努克(finibus accumsan nunc)的作品中,波苏尔(vitae posuere)是一位伟大的艺术家。万岁。这是一种有效的治疗方法。油炸圈饼。Etiam efficitur efficitur eleifend.\n\n不适用于任何其他类型。请不要在前庭、前庭、前庭等处使用。在欧盟和奥奇之间的侵权行为中使用。埃尼安·康瓦利斯(Aenean convallis)是一位自由欧盟成员。在dapibus posuere massa中,finibus neque Volvepat和Integer non-massa tristique、孕妇justo id、accumsan nibh。乌特-尼斯拉-普卢斯。完整的前庭扫描电镜,在佩伦特斯克之前,在奥古斯·福西布斯(augue faucibus)之间进行扫描。\n\n比本杜姆·比本杜姆·埃罗斯·维塔·阿利奎姆·维内提斯(vitae aliquam venenatis)。整数封建主义者奥奇·欧·梅特斯·普莱斯特拉特(orci-eu-metus-placerat),这是利奥·波苏尔(leo posuere)的名言。活在门前的生命之舌。不可为任何人提供任何好处。莫里斯的元素,欧盟自由的尊严。在ultrices ullamcorper nulla中,前庭的水平是非。没有必要。无尾褐飞虱。”
self.textbox=rt.RichTextCtrl(父项=self,值=text,样式=wx.TE_多行| wx.TE_只读)
self.textbox.Bind(wx.EVT\u上下文菜单,self.textbox\u上下文菜单)
hboxsizer.Add(self.textbox,比例=1,标志=wx.EXPAND)
自动设置SizerAndIt(hboxsizer)
#事件处理
self.tag\u语句\u id=100
self.tag\u段落\u id=200
self.Bind(wx.EVT_菜单,self.MENU事件)
def文本框上下文菜单(自身、事件):
“”“右键单击文本时显示上下文菜单”“”
menu=wx.menu()
菜单.附加(self.tag\u语句\u id,“tag语句”)
菜单.附加(self.tag\u段落\u id,“tag段落”)
self.PopupMenu(菜单)
def菜单_事件(自身、事件):
“”“处理上下文菜单事件”“”
event_id=event.GetId()
self.tag(事件标识)
def标签(自身、事件标识):
#获得插入符号位置
插入符号位置=self.textbox.GetCaretPosition()+1
#按事件标记
如果event\u id==self.tag\u段落\u id:
段落=自我。查找段落(插入符号位置)
start=self.textbox.GetValue().find(段落)
结束=开始+长度(段落)
self.apply_标记((开始,结束))
elif事件\u id==self.tag\u语句\u id:
句子=自我。查找句子(插入符号位置)
start=self.textbox.GetValue().find(句子.strip())
end=start+len(句子.strip())
self.apply_标记((开始,结束))
def应用标签(自身、位置):
self.textbox.SetStyle(位置[0],位置[1],wx.texttr(colText=wx.WHITE,colBack=wx.BLACK))
def查找段落(自身、插入符号位置):
段落=self.textbox.GetValue().split(“\n\n”)
对于段落中的段落:
段落=段落.strip()
start=self.textbox.GetValue().find(段落)
结束=开始+长度(段落)
如果开始<插入符号位置<结束:
返回段
def find_语句
import wx
import wx.richtext as rt


class MCVE(wx.App):
    """ App """
    def OnInit(self):
        frame = Frame()
        frame.Show()
        return True


class Frame(wx.Frame):
    """ Frame """
    def __init__(self):
        style = wx.SYSTEM_MENU | wx.CAPTION | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.RESIZE_BORDER
        super(Frame, self).__init__(parent=None, title="LabelingTool", style=style, size=(800, 600))
        self.panel = Panel(parent=self)


class Panel(wx.Panel):
    """ Panel """
    def __init__(self, parent):
        super(Panel, self).__init__(parent)
        # textbox
        hboxsizer = wx.BoxSizer(wx.HORIZONTAL)
        text = "Lorem Ipsum\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean eget enim vitae elit convallis ultrices. Sed vestibulum in metus id tempus. Phasellus tincidunt risus elit, id sagittis erat placerat quis. Donec ac porta tortor, non varius purus. Suspendisse euismod auctor maximus. Suspendisse nec orci vel dui posuere ultrices. Vivamus dictum vel enim nec interdum. Nunc tincidunt nulla sed facilisis suscipit. Nunc eget nisi ut turpis venenatis faucibus.\n\nInteger mauris nulla, malesuada quis lacus vitae, condimentum tincidunt dui. Aliquam non nisi aliquam, vulputate dolor ut, fringilla ligula. Nulla vitae tellus sit amet nulla ultrices pellentesque eu vitae lectus. Aliquam fringilla mauris tortor, et maximus lorem bibendum quis. Nam in magna gravida, accumsan libero accumsan, feugiat nisl. Donec tincidunt, tortor ut aliquam convallis, urna odio imperdiet ligula, dignissim vulputate ligula diam sit amet tortor. Ut a eros risus.\n\nCras et erat sodales, tempus nulla a, vulputate metus. Maecenas lacinia, nulla ac congue pharetra, lorem nibh pharetra metus, eu porttitor turpis leo ut lectus. Proin luctus rutrum mi id pharetra. Suspendisse aliquet id est nec efficitur. Maecenas dolor dui, vulputate et pulvinar at, venenatis id lorem. Praesent vel nisi ultrices massa rhoncus vestibulum. Nunc imperdiet consectetur pharetra. In cursus nec massa nec finibus. Aliquam et ligula bibendum, sodales mauris a, efficitur sapien. Ut mattis et ipsum eget sodales. Vestibulum maximus libero id ipsum placerat interdum at luctus risus. In finibus accumsan nunc, vitae posuere est interdum quis. Vivamus sed neque metus. Etiam fringilla efficitur lacus, vel aliquam purus lobortis vitae. Donec ut placerat orci. Etiam efficitur efficitur eleifend.\n\nAenean in imperdiet nisl. Donec dapibus neque tincidunt, fringilla velit vel, vestibulum velit. Sed at lorem id tortor accumsan interdum eu ut orci. Aenean convallis aliquet libero eu congue. In dapibus posuere massa, quis finibus neque volutpat et. Integer non massa tristique, gravida justo id, accumsan nibh. Ut ac nisl purus. Integer vestibulum sem in ante pellentesque, ac interdum augue faucibus.\n\nInteger bibendum eros vitae aliquam venenatis. Integer feugiat orci eu metus placerat, ut dictum leo posuere. Vivamus eget ligula vitae ante porttitor cursus. Nulla consectetur enim eu nisi aliquam mollis. Aliquam elementum consequat mauris, dignissim tempus libero sodales eu. In ultrices ullamcorper nulla, vel aliquet est vestibulum non. Nullam nec est ante. Phasellus eleifend lacinia nulla nec ultricies."
        self.textbox = rt.RichTextCtrl(parent=self, value=text, style=wx.TE_MULTILINE | wx.TE_READONLY)
        
        # event handling
        self.tag_sentence_id = 100
        self.tag_paragraph_id = 200

        self.menu = wx.Menu()
        self.menu.Append(self.tag_sentence_id, "tag sentence")
        self.menu.Append(self.tag_paragraph_id, "tag paragraph")
        
        self.textbox.SetContextMenu(self.menu)
        
        hboxsizer.Add(self.textbox, proportion=1, flag=wx.EXPAND)
        self.SetSizerAndFit(hboxsizer)

        self.Bind(wx.EVT_MENU, self.menu_event)


    def menu_event(self, event):
        """ handle context menu events """
        event_id = event.GetId()
        self.tag(event_id)

    def tag(self, event_id):
        # get caret position
        caret_position = self.textbox.GetCaretPosition()+1
        # tag by event
        if event_id == self.tag_paragraph_id:
            paragraph = self.find_paragraph(caret_position)
            start = self.textbox.GetValue().find(paragraph)
            end = start + len(paragraph)
            self.apply_tag((start, end))
        elif event_id == self.tag_sentence_id:
            sentence = self.find_sentence(caret_position)
            start = self.textbox.GetValue().find(sentence.strip())
            end = start + len(sentence.strip())
            self.apply_tag((start, end))

    def apply_tag(self, position):
        self.textbox.SetStyle(position[0], position[1], wx.TextAttr(colText=wx.WHITE, colBack=wx.BLACK))

    def find_paragraph(self, caret_position):
        paragraphs = self.textbox.GetValue().split("\n\n")
        for paragraph in paragraphs:
            paragraph = paragraph.strip()
            start = self.textbox.GetValue().find(paragraph)
            end = start + len(paragraph)
            if start < caret_position < end:
                return paragraph

    def find_sentence(self, caret_position):
        sentences = self.find_paragraph(caret_position).split(".")
        for sentence in sentences:
            sentence = sentence.strip()
            start = self.textbox.GetValue().find(sentence)
            end = start + len(sentence)
            # append dot if applicable
            if self.textbox.GetValue()[end] == ".":
                sentence += "."
            if start < caret_position < end:
                return sentence


if __name__ == "__main__":
    app = MCVE()
    app.MainLoop()