使用不同的事件绑定为同一鼠标位置获取不同的tkinter坐标

时间:2018-12-31 18:00:30

标签: python tkinter coordinates

我正在开发一个tkinter应用程序,该应用程序使您可以在地图上单击并拖动,并使用滚轮进行放大和缩小。 UI在主地图下方还有一个较宽的部分,这导致应用程序比地图的Canvas对象还要宽。

但是,对于单击和拖动事件和滚轮事件的位置,我得到了不同的坐标:就像我期望的那样,前者是画布内的坐标,而后者的x坐标增加了由底部较宽的对象添加的填充量。

这是一个最小的工作示例(使用所有动作,而不仅仅是单击并拖动):

#!/usr/bin/env python3
import tkinter as tk


class MainCanvas(tk.Canvas):
    def __init__(self, tk_parent):
        super().__init__(tk_parent, height=200, width=200, bg="green")
        self.pack()
        self.bind("<Motion>",     self.print_move)
        self.bind("<MouseWheel>", self.print_scroll)  # For Mac
        self.bind("<Button-4>",   self.print_scroll)  # For Linux
        self.bind("<Button-5>",   self.print_scroll)  # For Linux

    def print_coords(self, name, event):
        print("{}: x: ({}, {}), y: ({}, {})".format(
            name,
            event.x, int(self.canvasx(event.x)),
            event.y, int(self.canvasy(event.y))))

    def print_move(self, event):
        self.print_coords("moving", event)

    def print_scroll(self, event):
        self.print_coords("scroll", event)


class Bottom(tk.Canvas):
    def __init__(self, tk_parent):
        super().__init__(tk_parent, height=5, width=500, bg="red")
        self.pack()


class GUI(tk.Frame):
    def __init__(self, tk_parent):
        super().__init__(tk_parent)
        self.pack()
        self.main = MainCanvas(self)
        self.bottom = Bottom(self)


if __name__ == "__main__":
    root = tk.Tk()
    gui = GUI(root)

    # Make an easy way to exit
    for char in "wWqQ":
        root.bind("<Control-{}>".format(char), lambda _: root.destroy())

    root.mainloop()

和一些示例输出:

moving: x: (14, 14), y: (117, 117)
moving: x: (14, 14), y: (118, 118)
scroll: x: (164, 164), y: (118, 118)
scroll: x: (164, 164), y: (118, 118)
moving: x: (14, 14), y: (117, 117)
moving: x: (14, 14), y: (116, 116)
moving: x: (15, 15), y: (116, 116)
moving: x: (15, 15), y: (115, 115)
moving: x: (15, 15), y: (114, 114)
moving: x: (16, 16), y: (114, 114)
scroll: x: (166, 166), y: (114, 114)
scroll: x: (166, 166), y: (114, 114)
moving: x: (15, 15), y: (114, 114)
moving: x: (14, 14), y: (114, 114)
moving: x: (14, 14), y: (113, 113)
moving: x: (13, 13), y: (113, 113)
scroll: x: (163, 163), y: (113, 113)
scroll: x: (163, 163), y: (113, 113)
moving: x: (13, 13), y: (112, 112)
moving: x: (13, 13), y: (111, 111)
moving: x: (13, 13), y: (110, 110)

我希望对运动和滚动事件都具有相同的坐标系,但是如您所见,滚动事件向右移动了150个像素,这对应于左边的150个填充像素,这是由于底部的红色画布。使用.canvasx.canvasy函数将事件移到画布的坐标系中无济于事。

任何想法如何解决此问题?我不想从滚动事件坐标中减去恒定的150个像素,因为整个窗口是可调整大小的,因此填充量可能会更大。

我在Mac(Mojave)上使用Python 3.7.2和tkinter 8.6版,尽管我的应用程序在具有多个Python和tkinter版本的Ubuntu上具有相同的行为。 (免责声明:我尚未在Ubuntu上尝试过MWE,但我希望它能正常工作。)

预先感谢您的帮助!

0 个答案:

没有答案