Skip to main content
 首页 » 编程设计

python之简单的 Tk 应用程序——单击按钮进行绘制

2025年05月04日12kenshinobiy

谁能告诉我为什么在单击 self.rec 按钮时我的“addLine”方法无法调用?

from tkinter import * 
from tkinter import ttk 
root = Tk() 
 
class Paint: 
    def __init__(self, parent): 
        self.parent = parent 
        self.whiteBoard = Canvas(self.parent) 
        self.whiteBoard.grid(column=0, row=0, sticky=(N,W,E,S)) 
        self.lastx = 0 
        self.lasty = 0 
        self.rec = self.whiteBoard.create_rectangle((10, 10, 30, 30), fill="red") 
        self.whiteBoard.tag_bind(self.rec, "<Button-1>", self.getClick) 
 
    def xy(self, event): 
        self.lastx, self.lasty = event.x, event.y 
        print (event.x, " is the x coordinate") 
        print (event.y, " is the y coordinate") 
 
    def addLine(self, event): 
        canvas.create_line((lastx, lasty, event.x, event.y)) 
        self.lastx, self.lasty = event.x, event.y 
 
    def getClick(self, event): 
        self.whiteBoard.bind("<Button-1>", self.xy) 
        self.whiteBoard.bind("B1-Motion>", self.addLine) 
 
white = Paint(root) 
 
root.mainloop() 

这都是尝试使用 Tkinter 制作 MS 绘图克隆的一部分。

请您参考如下方法:

首先,您要绑定(bind)到 B1-Motion> (注意缺少的 < )。但是,更重要的是,不要像那样进行绑定(bind)。它看起来像 getClick方法其实就是“选线工具”。然后,添加绑定(bind) <Button-1>和 <B1-Motion>到 Canvas 本身。调用回调时,您将根据所选工具执行操作。

这是遵循这个建议的粗略草图(带有 RECTANGLE 工具作为奖励):

import tkinter 
 
# TOOLS 
LINE, RECTANGLE = list(range(2)) 
 
class Paint: 
    def __init__(self, canvas): 
        self.canvas = canvas 
        self._tool, self._obj = None, None 
        self.lastx, self.lasty = None, None 
        self.canvas.bind('<Button-1>', self.update_xy) 
        self.canvas.bind('<B1-Motion>', self.draw) 
 
    def draw(self, event): 
        if self._tool is None or self._obj is None: 
            return 
        x, y = self.lastx, self.lasty 
        if self._tool in (LINE, RECTANGLE): 
            self.canvas.coords(self._obj, (x, y, event.x, event.y)) 
 
    def update_xy(self, event): 
        if self._tool is None: 
            return 
        x, y = event.x, event.y 
        if self._tool == LINE: 
            self._obj = self.canvas.create_line((x, y, x, y)) 
        elif self._tool == RECTANGLE: 
            self._obj = self.canvas.create_rectangle((x, y, x, y)) 
        self.lastx, self.lasty = x, y 
 
    def select_tool(self, tool): 
        print('Tool', tool) 
        self._tool = tool 
 
class Tool: 
    def __init__(self, whiteboard, parent=None): 
        self.whiteboard = whiteboard 
 
        frame = tkinter.Frame(parent) 
        self._curr_tool = None 
        for i, (text, t) in enumerate((('L', LINE), ('R', RECTANGLE))): 
            lbl = tkinter.Label(frame, text=text, width=2, relief='raised') 
            lbl._tool = t 
            lbl.bind('<Button-1>', self.update_tool) 
            lbl.pack(padx=6, pady=6*(i % 2)) 
        frame.pack(side='left', fill='y', expand=True, pady=6) 
 
    def update_tool(self, event): 
        lbl = event.widget 
        if self._curr_tool: 
            self._curr_tool['relief'] = 'raised' 
        lbl['relief'] = 'sunken' 
        self._curr_tool = lbl 
        self.whiteboard.select_tool(lbl._tool) 
 
 
root = tkinter.Tk() 
 
canvas = tkinter.Canvas(highlightbackground='black') 
whiteboard = Paint(canvas) 
tool = Tool(whiteboard) 
canvas.pack(fill='both', expand=True, padx=6, pady=6) 
 
root.mainloop()