上点击鼠标绘制矩形[Python的](Draw rectangle on mouse click [

2019-09-23 23:18发布

def xaxis(event):
   x1, y1 = (event.x - 1), (event.y - 1)

def yaxis(event):
   x2, y2 = (event.x + 1), (event.y + 1)

def create(event):
   w.create_rectangle(x1,y1,x2,y2,fill='Black')

w = Canvas(root, width=canvas_width, height=canvas_height)
w.config(cursor='cross')
w.pack(expand=YES, fill=BOTH)
w.bind("<Button-1>", xaxis)
w.bind("<ButtonRelease-1>", yaxis)
w.bind("<ButtonRelease-1>", create)

外壳说

例外的Tkinter回调回溯(最近通话最后一个):
文件“/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py”,线1410,在调用返回self.func(*参数)文件“/用户/狮子座/桌面/ draw.py” 22行,在创建w.create_rectangle(X1,Y1,X2,Y2,填补= '黑')NameError:不定义的全局名称 'X1'

它认为建立功能不能够得到的其他功能的坐标...

我就是这么做的,因为我以后需要的坐标!

我希望你能帮助我.. ;-)谢谢!

Answer 1:

解决“全球名‘X1’没有定义”的问题

调试时一个好的经验法则是假设错误消息说的是实话。 在这种情况下,它是说,没有名为“X1”的全局变量。 所以,问自己“为什么?”。 无论你是不是创造一个“X1”变量在所有的,或者你以这样的方式创造它,它不是全球性的。

在你的情况,当你定义X1,Y1,X2和Y2,你正在创建它们作为局部变量。 这是创建变量时,Python的默认行为。 最简单的办法是将它们申报为全球:

def xaxis(event):
   global x1, y1
   x1, y1 = (event.x - 1), (event.y - 1)

def yaxis(event):
    global x2, y2
    x2, y2 = (event.x + 1), (event.y + 1)

一个不相关的第二个问题

你有你如何做你的绑定在你的代码的另一个问题。 考虑下面的代码片段:

w.bind("<ButtonRelease-1>", yaxis)
w.bind("<ButtonRelease-1>", create)

你是不是创建两个绑定,要创建一个,然后用另一个覆盖它。 你不需要两个绑定,但是。 您可以在创建函数中调用你y轴的功能。

使用面向对象的方法

然而,全局变量通常不是一个问题的最佳解决方案。 如果您切换到使用面向对象的方法,那么你可以将坐标存储为一个对象的属性。 下面是一个完整,工作示例:

import Tkinter as tk

class ExampleApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.x = self.y = 0
        self.canvas = tk.Canvas(self, width=400, height=400, cursor="cross")
        self.canvas.pack(side="top", fill="both", expand=True)
        self.canvas.bind("<ButtonPress-1>", self.on_button_press)
        self.canvas.bind("<ButtonRelease-1>", self.on_button_release)

    def on_button_press(self, event):
        self.x = event.x
        self.y = event.y

    def on_button_release(self, event):
        x0,y0 = (self.x, self.y)
        x1,y1 = (event.x, event.y)

        self.canvas.create_rectangle(x0,y0,x1,y1, fill="black")

if __name__ == "__main__":
    app = ExampleApp()
    app.mainloop()

作为绘制拖动鼠标

如果你想为你拖动光标以绘制矩形,你可以改变程序来创建按钮按矩形。 如果你要么给对象的唯一标签或保存画布ID ,您可以设置鼠标移动事件来调整使用当前矩形的坐标COORDS画布对象的方法。 我会离开,作为一个练习留给读者,因为它不直接关系到被问的问题。



Answer 2:

您只设置x1在各自的职责等局部(如xaxis ),所以它们不能用于create 。 所以他们返回了预期的效果,你可以重写这些:

def xaxis(event):
   return (event.x - 1), (event.y - 1) # x1, y1

def yaxis(event):
   return (event.x + 1), (event.y + 1) # x2, y2

def create(event):
   x1, y1 = xaxis(event)
   x2, y2 = yaxis(event)
   w.create_rectangle(x1,y1,x2,y2,fill='Black')


Answer 3:

You are storing results of x1, x2 ... in local variables. These values are lost when you exit the event handler function. You must use global vars or a dedicated object for managing event handlers. I would prefer the 2nd solution.

Another issue is that you have two functions bound with Button-Release1. My solution is not to bound yaxis and to call it from create. A cleaner approach can be found :)

See example below. It should work:

from Tkinter import *

root=Tk()

class Handler:

    def __init__(self, w):
        self.w = w
        w.bind("<Button-1>", self.xaxis)
        #w.bind("<ButtonRelease-1>", self.yaxis)
        w.bind("<ButtonRelease-1>", self.create)


    def xaxis(self, event):
        self.x1, self.y1 = (event.x - 1), (event.y - 1)

    def yaxis(self, event):
        self.x2, self.y2 = (event.x + 1), (event.y + 1)

    def create(self, event):
        self.yaxis(event)
        self.w.create_rectangle(self.x1,self.y1,self.x2,self.y2,fill='Black')

w = Canvas(root, width=200, height=200)
w.config(cursor='cross')
w.pack(expand=YES, fill=BOTH)

Handler(w)


root.mainloop()


文章来源: Draw rectangle on mouse click [Python]