简体   繁体   English

获取线鼠标在 tkinter 文本上

[英]Getting line mouse is on tkinter text

I am trying to make a sidebar for a tkinter Text widget that displays a red dot next to the line that the mouse hovers over.我正在尝试为 tkinter Text 小部件制作一个侧边栏,该小部件在鼠标悬停的行旁边显示一个红点。 Currently it is configured to go to the selected line but would be better if it tracked the mouse.目前它被配置为转到选定的行,但如果它跟踪鼠标会更好。 I know how to track the mouses y position with root.winfo_pointery() but don't know how the get the corresponding line for that.我知道如何使用root.winfo_pointery()跟踪鼠标的 y 位置,但不知道如何获得相应的行。 I also don't want it to display anything if it is out of the text widget's y area or if there is no line.如果它超出文本小部件的 y 区域或没有线条,我也不希望它显示任何内容。 How do I cross compare the y value of the pointer to text lines?如何交叉比较指针的 y 值与文本行?

Current code:当前代码:

from tkinter import *
class BreakpointBar(Canvas):
    def __init__(self, *args, **kwargs):
        #Initializes the canvas
        Canvas.__init__(self, *args, **kwargs, highlightthickness=0)
        self.textwidget = None
        self.ovals = []

    def attach(self, text_widget):
        #Attaches the canvas to the text widget
        self.textwidget = text_widget

    def redraw(self, *args):
        #Redraws the canvas
        """redraw line numbers"""
        # try:
        self.delete("all")
        self.unbind_all("<Enter>")
        self.unbind_all("<Leave>")
        self.ovals = []
        index = self.textwidget.index("insert")
        index_linenum = str(index).split(".")[0]


        i = self.textwidget.index("@0,0")
        print(self.winfo_pointerx())
        print(self.winfo_pointery())
        while True :
            dline= self.textwidget.dlineinfo(i)
            if dline is None: break
            y = dline[1]
            linenum = str(i).split(".")[0]
            if linenum == index_linenum:
                oval = self.create_oval(5, y, 15, y+10, fill="red", outline="red")
                self.tag_bind(oval, "<Enter>", lambda event: self.on_enter(event, oval))
                self.tag_bind(oval, "<Leave>", lambda event: self.on_exit(event, oval))
                self.tag_bind(oval, "<Button-1>", lambda event: self.on_press(event, oval))
                self.ovals.append(oval)
            i = self.textwidget.index("%s+1line" % i)
        # except:
        #     pass

    def on_enter(self, event, oval):
        self.itemconfig(oval, fill="dark red", outline="dark red")


    def on_exit(self, event, oval):
        self.itemconfig(oval, fill="red", outline="red")

    def on_press(self, event, oval):
        index_linenum = int(str(self.textwidget.index("insert")).split(".")[0])
        self.textwidget.insert("{}.end".format(index_linenum), "\nbreakpoint\n")
        self.textwidget.mark_set("insert", "{}.0".format(index_linenum+2))
        self.textwidget.see("insert")
root = Tk()
frame = Frame(root)
frame.pack(expand=True, fill=BOTH)
text=Text(frame)
text.pack(side=RIGHT, fill=BOTH, expand=True)
bb = BreakpointBar(frame, width=20)
bb.attach(text)
bb.pack(side=LEFT, fill=Y)
root.bind("<Button-1>", bb.redraw)
root.bind("<KeyRelease-Return>", bb.redraw)
root.mainloop()

You can get the index for character nearest to the mouse via an x,y coordinate using the format @x,y .您可以使用@x,y格式通过 x,y 坐标获取离鼠标最近的字符的索引。

For example, if you have a function bound to the <Motion> event, you can get the index under the cursor by doing something like this:例如,如果您有一个绑定到<Motion>事件的函数,您可以通过执行以下操作来获取光标下的索引:

def track_mouse(event):
    index = event.widget.index(f"@{event.x},{event.y}")
    ...

In the above example, index will be in the canonical form of a string in the format line.character .在上面的示例中, index将采用line.character格式的字符串的规范形式。

It's important to note that you must give coordinates that are relative to the upper-left corner of the text widget itself, not of the window or display as a whole.请务必注意,您必须提供相对于文本小部件本身的左上角的坐标,而不是相对于窗口或整个显示的坐标。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM