Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PythonTkinter-跟踪并保存mousecklicks以构建画布项_Python_Events_Tkinter_Tkinter Canvas - Fatal编程技术网

PythonTkinter-跟踪并保存mousecklicks以构建画布项

PythonTkinter-跟踪并保存mousecklicks以构建画布项,python,events,tkinter,tkinter-canvas,Python,Events,Tkinter,Tkinter Canvas,我在画布上编程了这样一个方法: 当我按下button1时,变量“state”变为0,每次单击画布都会产生一个圆圈 当我按下按钮2时,变量“状态”变为1。当我单击的项目是一个圆时,我的变量“selected”从None变为1,我还保存了鼠标单击的坐标 我的问题:我该如何编写代码,python应该等待第二次单击,然后看看它是否也是另一个圆圈?如果是的话,我怎样才能在他们之间划清界限呢 def newKnotornewEdge(event): if self.state

我在画布上编程了这样一个方法:

  • 当我按下button1时,变量“state”变为0,每次单击画布都会产生一个圆圈
  • 当我按下按钮2时,变量“状态”变为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)
def newKnotornewEdge(事件):
如果self.state==0:
self.canvas.create_oval(event.x-25,event.y-25,event.x+25,event.y+25,fill=“蓝色”)
self.canvas.create_文本(event.x,event.y,text=“A”,fill=“white”)
elif self.state==1:
如果self.canvas.itemcget(self.canvas.find_重叠(event.x,event.y,event.x,event.y),“fill”)=“blue”:
自我选择=1
开始x=事件x
start_y=event.y
其他:
self.selected=无
如果self.selected==1且#第二个鼠标单击也是一个圆:
#画一条连接这些圆圈的线
self.canvas.bind(“,newKnotornewEdge)

以下画布截图显示了该应用程序的8个圆圈;其中2个和4个用线连接;红色圆圈已被选中(这是红色所表示的),并准备在下一次单击时连接到另一个圆圈;一个圆未连接且未选定

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

加入你的圈子: 单击后,将激活“加入圆圈”操作,并清除可能已选择的圆圈。
第一次点击画布上的一个圆圈,选择这个颜色变为红色的圆圈;第二次单击画布上的圆将选择第二个圆,用一条线连接两个圆,将颜色重置为蓝色,并清除所选内容。
单击画布的空白部分不会产生任何效果

您需要跟踪要执行的操作:绘制一个新的圆,或选择两个要连接的圆。您还需要跟踪选择了多少个圆。
然后,在成功绘制圆之间的直线后,需要清除所选内容

我选择使用python的“functions as a first class object”功能来避免混乱的状态记帐:通过单击相关按钮选择要执行的操作,然后在画布上单击将与此操作相关

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

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()
将tkinter作为tk导入
类命令按钮(tk.Frame):
定义初始(自我,主):
self.master=master
super().\uuuu init\uuuuuu(self.master)
self.make\u circle\u btn=tk.按钮(根,text='make\u circle',command=make\u circle)
self.make_circle_btn.pack()
self.join\u circles\u btn=tk.按钮(root,text='join\u circles',command=select\u circles)
self.join\u circles\u btn.pack()
self.pack()
类CircleApp(tk.Frame):
定义初始(自我,主):
self.master=master
super().\uuuu init\uuuuuu(self.master)
self.canvas=tk.canvas(根,宽度=600,高度=600,bg='cyan')
self.canvas.pack(expand=True,fill=tk.BOTH)
self.pack()
def make_circle():
_清除所选内容()
打印('cmd make_circle selected')
c_app.canvas.bind(“”,_make_circle)
def_make_circle(事件):
c_app.canvas.create_oval(event.x-25,event.y-25,event.x+25,event.y+25,fill=“blue”)
def select_circles():
_清除所选内容()
打印('cmd join_circles selected')
c_app.canvas.bind(“”,_select_circles)
定义选择圆(事件):
打印(f'select circle{event}')
x、 y=事件.x,事件.y
选择=c_应用程序画布。查找重叠(x,y,x,y)
如果所选内容不是None且len(所选圆圈)<2:
所选圆。附加(选择)
c_app.canvas.itemconfigure(选择,fill='red')
如果len(选定的_圆)==2:
如果全部(选定的圆圈):
_加入你的圈子()
_清除所选内容()
def_join_circles():
坐标=[]
对于选定圆圈中的项目:
x、 y=查找中心(项目)
打印(x,y)
坐标。追加(x)
坐标。追加(y)
c_应用程序。画布。创建_线(坐标)
定义清除选项()
全局选定圆
对于选定圆圈中的项目:
c_app.canvas.itemconfigure(item,fill='blue')
选定的_圆=[]
def查找中心(项目):
x0,y0,x1,y1=c_app.canvas.bbox(项目)
返回(x0+x1)/2,(y0+y1)/2
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
选定的_圆=[]
root=tk.tk()
命令\帧=命令按钮(根)
c_app=CircleApp(根)
root.mainloop()
更好的版本将使用类来封装所选项目;这里我使用了一个集合作为全局变量。它还可以正确处理重叠圆的选择