python tkinter-跟踪并保存mousecklicks以构建画布项目

时间:2018-07-02 20:48:42

标签: python events tkinter tkinter-canvas

我在画布上编写了这样的方法:

  • 当我按下button1时,变量“状态”变为0,并且每次在画布上单击都会产生一个圆圈
  • 当我按下button2时,变量“状态”更改为1。当我单击的项目是一个圆圈时,变量“选定”从“无”更改为1,并且我还保存了鼠标单击的坐标

我的问题:我该如何编码,该python应该等待第二次点击,看看它是否又是另一个圆圈?如果是这样,我如何在它们之间划一条线?

     def newKnotornewEdge(event):
        if self.state == 0:
            self.canvas.create_oval(event.x-25,event.y-25,event.x+25, event.y+25, fill="blue")
            self.canvas.create_text(event.x, event.y, text="A", fill="white")
        elif self.state == 1:
            if self.canvas.itemcget(self.canvas.find_overlapping(event.x, event.y, event.x, event.y), "fill") == "blue":
                self.selected = 1
                start_x = event.x
                start_y = event.y

            else:
                self.selected = None

            if self.selected == 1 and #second mouseclick is a circle too:
                #draw line that connects those circels

    self.canvas.bind("<Button -1>", newKnotornewEdge)

1 个答案:

答案 0 :(得分:0)

以下画布截图显示了绘制了8个圆圈的应用程序;其中的2和4用线连接;红色的圆圈已被选中(这是红色表示的颜色),并准备在下一次单击时加入另一个圆圈;一个圈子没有加入也没有被选中。

make_circle:

单击按钮选择“绘制圆圈”操作,并清除可能已经选择的圆圈。
启用此操作后,在画布上单击会绘制一个蓝色圆圈。

join_circles:

单击后,它会激活“加入圈子”操作并清除可能已经选择的圈子。
第一次单击画布上的圆圈时,将选择该圆圈,其颜色将变为红色;第二次单击画布上的一个圆会选择第二个圆,并用一条线将两个圆连接起来,将颜色重置为蓝色,然后清除所选内容。
单击画布的空白部分没有任何作用。

enter image description here

您将需要跟踪要执行的操作:画一个新圆,或选择两个圆加入。您还需要跟踪选择了多少个圈子。
然后,在圆之间成功画出一条线之后,您将需要清除选择。

我选择使用python的“作为一类对象的功能”功能来避免混乱的状态记帐:通过单击相关按钮选择要执行的动作,然后在画布上单击将与此动作相关

以下代码在画布上执行此操作,并打印选择的操作以及在控制台中执行的操作:

import tkinter as tk


class CommandButtons(tk.Frame):
    def __init__(self, master):
        self.master = master
        super().__init__(self.master)
        self.make_circle_btn = tk.Button(root, text='make_circle', command=make_circle)
        self.make_circle_btn.pack()
        self.join_circles_btn = tk.Button(root, text='join_circles', command=select_circles)
        self.join_circles_btn.pack()
        self.pack()


class CircleApp(tk.Frame):
    def __init__(self, master):
        self.master = master
        super().__init__(self.master)
        self.canvas = tk.Canvas(root, width=600, height=600, bg='cyan')
        self.canvas.pack(expand=True, fill=tk.BOTH)
        self.pack()


def make_circle():
    _purge_selection()
    print('cmd make_circle selected')
    c_app.canvas.bind('<Button-1>', _make_circle)


def _make_circle(event):
    c_app.canvas.create_oval(event.x - 25, event.y - 25, event.x + 25, event.y + 25, fill="blue")


def select_circles():
    _purge_selection()
    print('cmd join_circles selected')
    c_app.canvas.bind('<Button-1>', _select_circles)


def _select_circles(event):
    print(f'select circle {event}')
    x, y = event.x, event.y
    selection = c_app.canvas.find_overlapping(x, y, x, y)
    if selection is not None and len(selected_circles) < 2:
        selected_circles.append(selection)
        c_app.canvas.itemconfigure(selection, fill='red')
    if len(selected_circles) == 2:
        if all(selected_circles):
            _join_circles()
        _purge_selection()


def _join_circles():
    coordinates = []
    for item in selected_circles:
        x, y = find_center(item)
        print(x, y)
        coordinates.append(x)
        coordinates.append(y)
    c_app.canvas.create_line(coordinates)


def _purge_selection():
    global selected_circles
    for item in selected_circles:
        c_app.canvas.itemconfigure(item, fill='blue')
    selected_circles = []


def find_center(item):
    x0, y0, x1, y1 = c_app.canvas.bbox(item)
    return (x0 + x1) / 2, (y0 + y1) / 2


if __name__ == '__main__':
    selected_circles = []

    root = tk.Tk()
    command_frame = CommandButtons(root)
    c_app = CircleApp(root)

    root.mainloop()

更好的版本将使用一个类来封装所选项目;在这里,我使用集合作为全局变量。它还可以正确处理重叠的圆选择。