【问题标题】:python tkinter - track and save mousecklicks to build canvas itemspython tkinter - 跟踪和保存鼠标点击以构建画布项目
【发布时间】:2018-07-02 20:48:41
【问题描述】:

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

  • 当我按下 button1 时,变量“状态”变为 0,并且每次点击画布都会产生一个圆圈
  • 当我按下 button2 时,变量“state”变为 1。当我单击的项目是一个圆圈时,我的变量“selected”从 None 变为 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)

【问题讨论】:

    标签: python events tkinter tkinter-canvas


    【解决方案1】:

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

    make_circle:

    单击该按钮可选择“绘制圆圈”操作,并清除可能已被选中的圆圈。
    当此操作处于活动状态时,单击画布会绘制一个蓝色圆圈。

    加入_圈子:

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

    您需要跟踪要执行的操作:绘制一个新圆圈,或选择两个圆圈加入。您还需要跟踪已选择的圈子数量。
    然后,在成功绘制圆圈之间的线后,您需要清除所选内容。

    我选择使用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()
    

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

    【讨论】:

      猜你喜欢
      • 2018-07-09
      • 1970-01-01
      • 2013-04-27
      • 2011-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多