【问题标题】:Tkinter get mouse coordinates on click and use them as variablesTkinter 在点击时获取鼠标坐标并将它们用作变量
【发布时间】:2017-02-28 03:22:18
【问题描述】:

我对 Python 完全陌生。因此,不要生我的气,因为我确信我缺少一些基本的东西。这是我的问题:

我正在尝试从图像中提取鼠标单击坐标并将这些坐标用作变量。

代码允许导入和图像,我想从中提取坐标。一些提示询问用户图表的大小和范围,之后我想通过分别单击 x 轴和 y 轴上的原点和终点来设置坐标网格。想法是利用这3组坐标,通过一些变换函数将它们变换为压力和温度坐标(见代码)。

# Determine the origin by clicking
# Probably with classes??
class Origin:
    def getorigin(eventorigin):
          eventorigin.x0 = eventorigin.x
          eventorigin.y0 = eventorigin.y
    #mouseclick event
    w.bind("<Button 1>",getorigin)
# What do I do here??
x0 = ...
y0 = ...

我真的不知道如何将通过单击获得的坐标分配给我以后可以在代码中使用的新变量。

我可以打印坐标,但由于它们是一个函数,它们是本地的并且在函数之外不能使用(据我所知)。所以,使用类的方法可能会更好,但我不知道该怎么做。

感谢任何帮助。

完整代码(改编):

from tkinter import *
from tkinter.filedialog import askopenfilename
from PIL import Image, ImageTk
import tkinter.simpledialog

root = Tk()

#setting up a tkinter canvas
w = Canvas(root, width=1000, height=1000)
w.pack()

#adding the image
File = askopenfilename(parent=root, initialdir="./",title='Select an image')
original = Image.open(File)
original = original.resize((1000,1000)) #resize image
img = ImageTk.PhotoImage(original)
w.create_image(0, 0, image=img, anchor="nw")

#ask for pressure and temperature extent
xmt = tkinter.simpledialog.askfloat("Temperature", "degrees in x-axis")
ymp = tkinter.simpledialog.askfloat("Pressure", "bars in y-axis")

#ask for real PT values at origin
xc = tkinter.simpledialog.askfloat("Temperature", "Temperature at origin")
yc = tkinter.simpledialog.askfloat("Pressure", "Pressure at origin")

#instruction on 3 point selection to define grid
tkinter.messagebox.showinfo("Instructions", "Click: \n" 
                                            "1) Origin \n"
                                            "2) Temperature end \n"
                                            "3) Pressure end")

# From here on I have no idea how to get it to work...

# Determine the origin by clicking
def getorigin(eventorigin):
    global x0,y0
    x0 = eventorigin.x
    y0 = eventorigin.y
    print(x0,y0)
#mouseclick event
w.bind("<Button 1>",getorigin)

# Determine the extent of the figure in the x direction (Temperature)
def getextentx(eventextentx):
    global xe
    xe = eventextentx.x
    print(xe)
#mouseclick event
w.bind("<Button 1>",getextentx)

# Determine the extent of the figure in the y direction (Pressure)
def getextenty(eventextenty):
    global ye
    ye = eventextenty.y
    print(ye)
#mouseclick event
w.bind("<Button 1>",getextenty)

#message to confirm that the grid is set up
tkinter.messagebox.showinfo("Grid", "Grid is set. You can start picking coordinates.")

#Coordinate transformation into Pressure-Temperature space
def printcoords(event):
    xmpx = xe-x0
    xm = xmt/xmpx
    ympx = ye-y0
    ym = -ymp/ympx

    #coordinate transformation
    newx = (event.x-x0)*(xm)+xc
    newy = (event.y-y0)*(ym)+yc

    #outputting x and y coords to console
    print (newx,newy)
#mouseclick event
w.bind("<Button 1>",printcoords)

root.mainloop()

【问题讨论】:

    标签: python tkinter click coordinates mouse


    【解决方案1】:

    如果我在之前的评论中所说的是你想要做的,因为 tkinter 不会暂停程序以等待鼠标单击事件,你将不得不这样做:每次鼠标按钮时它都会重新绑定它被点击

    from tkinter import *
    from tkinter.filedialog import askopenfilename
    from PIL import Image, ImageTk
    import tkinter.simpledialog
    
    root = Tk()
    
    #setting up a tkinter canvas
    w = Canvas(root, width=1000, height=1000)
    w.pack()
    
    #adding the image
    File = askopenfilename(parent=root, initialdir="./",title='Select an image')
    original = Image.open(File)
    original = original.resize((1000,1000)) #resize image
    img = ImageTk.PhotoImage(original)
    w.create_image(0, 0, image=img, anchor="nw")
    
    #ask for pressure and temperature extent
    xmt = tkinter.simpledialog.askfloat("Temperature", "degrees in x-axis")
    ymp = tkinter.simpledialog.askfloat("Pressure", "bars in y-axis")
    
    #ask for real PT values at origin
    xc = tkinter.simpledialog.askfloat("Temperature", "Temperature at origin")
    yc = tkinter.simpledialog.askfloat("Pressure", "Pressure at origin")
    
    #instruction on 3 point selection to define grid
    tkinter.messagebox.showinfo("Instructions", "Click: \n" 
                                                "1) Origin \n"
                                                "2) Temperature end \n"
                                                "3) Pressure end")
    
    # From here on I have no idea how to get it to work...
    
    # Determine the origin by clicking
    def getorigin(eventorigin):
        global x0,y0
        x0 = eventorigin.x
        y0 = eventorigin.y
        print(x0,y0)
        w.bind("<Button 1>",getextentx)
    #mouseclick event
    w.bind("<Button 1>",getorigin)
    
    # Determine the extent of the figure in the x direction (Temperature)
    def getextentx(eventextentx):
        global xe
        xe = eventextentx.x
        print(xe)
        w.bind("<Button 1>",getextenty)
    
    # Determine the extent of the figure in the y direction (Pressure)
    def getextenty(eventextenty):
        global ye
        ye = eventextenty.y
        print(ye)
        tkinter.messagebox.showinfo("Grid", "Grid is set. You can start picking coordinates.")
        w.bind("<Button 1>",printcoords)
    
    #Coordinate transformation into Pressure-Temperature space
    def printcoords(event):
        xmpx = xe-x0
        xm = xmt/xmpx
        ympx = ye-y0
        ym = -ymp/ympx
    
        #coordinate transformation
        newx = (event.x-x0)*(xm)+xc
        newy = (event.y-y0)*(ym)+yc
    
        #outputting x and y coords to console
        print (newx,newy)
    
    root.mainloop()
    

    【讨论】:

    • 哇,这似乎符合我的要求(我可能需要调整我的转换,但程序在其他方面很好!)我现在正在做一些其他的事情,但稍后会测试和评论。谢谢!
    • 一切正常。谢谢! (只需将ympx=ye-y0 更改为ympx=y0-ye 即可翻转坐标系(但这与问题无关,哈哈)。
    【解决方案2】:

    最简单的方法是设置 x, y 为 global,class 与否无关紧要。 我没有看到您的完整代码,因为我无法在手机上打开 zip 文件。所以这就是我可以帮助你的例子

    import tkinter as tk
    def getorigin(eventorigin):
          global x,y
          x = eventorigin.x
          y = eventorigin.y
          print(x,y)
    
    root = tk.Tk()
    root.bind("<Button 1>",getorigin)
    

    【讨论】:

    • 我修改了代码。这件作品本身似乎有效,但在完整代码的上下文中却没有。如果我最后尝试print(x,y),则会显示错误消息NameError: name 'x' is not defined。难道我需要某种if 语句或循环,以便能够一个接一个地保存 3 个坐标?
    • Here是完整代码的改编版
    • @Lele 你介意将你修改后的代码复制并粘贴到你在编辑下的问题中。我正在使用手机,因此无法查看 .py 文件
    • @Lele 你只能使用 w.bind 绑定一次“
    • 您是否要让程序等待用户按下某些东西?然后继续等待用户再次按下别的东西?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 2020-06-11
    • 2021-01-05
    • 1970-01-01
    • 2016-04-14
    相关资源
    最近更新 更多