[英]Moving line with Object Tkinter
I am currently working on a netwoking project and I want to make it so I can create multiple nodes and add connections between them. 我目前正在从事一个netwoking项目,我想使其成为一个项目,以便我可以创建多个节点并在它们之间添加连接。 I have got this all completed but now I am stuck on trying to make the lines move with the objects when I move the object. 我已经完成了所有这些工作,但是现在我不得不尝试在移动对象时使线条随对象一起移动。 I have created dictionaries for each object that I create and these are all stored within a list. 我为创建的每个对象创建了词典,这些词典都存储在列表中。 The dicitonary stores the item, the amount of connectors the item has, and then the connectors that it has linked to it. 字典存储该项目,该项目具有的连接器的数量,然后存储与其链接的连接器。
How can I make it so the lines move with the objects when I move them? 当移动对象时,如何使其与对象一起移动?
Here is my library code: 这是我的图书馆代码:
#-------------------------------------------------------------------------------
# Name: module1
# Purpose:
#
# Author: ahilton
#
# Created: 18/12/2014
# Copyright: (c) ahilton 2014
# Licence: <your licence>
#-------------------------------------------------------------------------------
#used for validation
#will make sure that the program will run on different versions of python
try:
# Python2
from Tkinter import *
except ImportError:
# Python3
from tkinter import *
#imports pre-defined libraries that are installed in tkinter
import random
#______________________________________________________________________________________________________________________________________________________________________
#creates a variable used for a count
count = 1
IPvar = 256
f = 0
ConnectCount = 1
a = 0
temp = 0
temp2 = 0
itemsconnectors = []
itemlist = []
LinkedItems = []
#______________________________________________________________________________________________________________________________________________________________________
class Window:
#______________________________________________________________________________________________________________________________________________________________________
def __init__(self, window, colour = 'White', width = 1440, height = 720):
#window variables
self.colour = colour
self.screenwidth = width
self.screenheight = height
#create the panes
self.MainCanvas = Canvas(window, background = self.colour, width = self.screenwidth, height = self.screenheight)
self.MainCanvas.pack()
#This dictionary is used to keep track of an item being dragged
self._drag_data = {"x": 0, "y": 0, "item": None}
#This dictionary is used to keep track of an item having it's state changed
self._state_change = {"item": None, "tag": "PCchange1", "colour": "Black"}
#This dictionary is used to keep track of the items being connected
self._connector = {"connector": None, "item": None, "item2": None, "x": 0, "y": 0, "x2": 0, "y2": 0, "tag": "False"}
self._object_data = []
#Add bindings for clicking, dragging and releasing over any object with the "PCdrag" tag
self.MainCanvas.tag_bind("PCdrag", "<ButtonPress-1>", self.OnButtonPress)
self.MainCanvas.tag_bind("PCdrag", "<ButtonRelease-1>", self.OnButtonRelease)
self.MainCanvas.tag_bind("PCdrag", "<B1-Motion>", self.OnMotion)
self.MainCanvas.tag_bind("ColourSwitch", "<ButtonPress-3>", self.ColourChange)
#self.MainCanvas.tag_bind("ColourSwitch", "<ButtonRelease-3>", self.ColourChangeRelease)
#self.MainCanvas.tag_bind("PCchange", "<B3-Motion>", self.ColourChange)
self.MainCanvas.tag_bind("text", "<Return>", self.OnEnter)
#______________________________________________________________________________________________________________________________________________________________________
def OnEnter(self, event):
print 'hi'
#______________________________________________________________________________________________________________________________________________________________________
def ChangeClick(self):
#This will change the binding of the mouse while the connector process is active
self.MainCanvas.tag_bind("PCdrag", "<ButtonPress-1>", self.LocateObject)
self.MainCanvas.tag_bind("PCdrag", "<ButtonRelease-1>", self.LocateObject2)
self.MainCanvas.tag_bind("PCdrag", "<B1-Motion>", self.Ignore)
#this is a temporary function to get rid of the OnMotion function which is usually called when the item is dragged
def Ignore(self, event):
a = 1
#print "Ignore"
#______________________________________________________________________________________________________________________________________________________________________
#This is used to draw the computer on the canvas, notice the tag that has been added as an attribute
def CreateComputer(self, x_start, y_start, color, tag):
#count = count + 1
#self._state_change["count"] = self._state_change["count"] + 1
#Creates a list of tags that are going to be added on to each computer object
#The second tag is defined elsewhere in the program as it changes depending on the state of the computer
#tag = ["PCdrag", self._state_change["count"], self._state_change["tag"], "ColourSwitch", self._connector["tag"]]
if temp <= temp2:
self._object_data.append(dict(item=count, CoCount=0))
#creates the object and takes properties from the DragItem class
self.MainCanvas.create_rectangle(x_start-40, y_start-25, x_start+40, y_start+25, outline=color, fill=color, tags = ("PCdrag", self._state_change["tag"], "ColourSwitch", self._connector["tag"], tag))
itemlist.append(self._state_change)
#print itemlist
#______________________________________________________________________________________________________________________________________________________________________
#This is used to draw text on top of the object on the canvas
def CreateText(self, x_start, y_start, Node, tag):
global count
global f
global IPvar
global temp
global temp2
IP = "192.168.0."
if f == 0:
temp2 = Node - 1
#IPvar = (IPvar - Node) + 1
#temp = IPvar
temp = 1
f = 1
else:
f = 1
if temp <= temp2:
self.MainCanvas.create_text(x_start, y_start, text = (IP, temp), fill = 'white', tag = ('PCdrag','text', tag))
count = count + 1
temp = temp + 1
else:
print 'fail'
#______________________________________________________________________________________________________________________________________________________________________
#this function will be called before the line is created. it sets all the variables for the line
def CreateLine(self):
global ConnectCount
#sets the four variables that will determine the coords of the line
xstart = self._connector["x"]
ystart = self._connector["y"]
xend = self._connector["x2"]
yend = self._connector["y2"]
#this will reset the _connector dictionary
self._connector["x"] = 0
self._connector["y"] = 0
self._connector["x2"] = 0
self._connector["y2"] = 0
#this will set the tag bindings back to their original ones to allow you to drag the item again
self.MainCanvas.tag_bind("PCdrag", "<ButtonPress-1>", self.OnButtonPress)
self.MainCanvas.tag_bind("PCdrag", "<ButtonRelease-1>", self.OnButtonRelease)
self.MainCanvas.tag_bind("PCdrag", "<B1-Motion>", self.OnMotion)
#print self._object_data
#tag = ["Linedrag", self._connector("item"), self._connector("item2")]
#this will create the line and put it on the main canvas
self.MainCanvas.create_line(xstart, ystart, xend , yend, tags = ("Linedrag", ConnectCount), width = 5, smooth = 1)
self.MainCanvas.tag_raise("PCdrag")
ConnectCount = ConnectCount + 1
#______________________________________________________________________________________________________________________________________________________________________
def LocateObject(self, event):
global ConnectCount
#sets the key "item" in the _connector dictionary to be equal to the object closest to the mouse
#sets the key "x" and the key "y" to be equal to the x and y coords of the object
self._connector["item"] = self.MainCanvas.find_closest(event.x, event.y)[0]
if self._connector["item"] % 2 == 0:
temp = self._connector["item"] / 2
for d in range(len(self._object_data)):
if self._object_data[d]["item"] == temp:
self._object_data[d]["CoCount"] = self._object_data[d]["CoCount"] + 1
self._object_data[d]["Connect" + str(self._object_data[d]["CoCount"])] = ConnectCount
self._connector["item"] = self._connector["item"] - 1
else:
self._connector["item"] = self._connector["item"] + 1
temp = self._connector["item"] / 2
for d in range(len(self._object_data)):
if self._object_data[d]["item"] == temp:
self._object_data[d]["CoCount"] = self._object_data[d]["CoCount"] + 1
self._object_data[d]["Connect" + str(self._object_data[d]["CoCount"])] = ConnectCount
self._connector["item"] = self._connector["item"] - 1
#print self._object_data, 'test1'
self._connector["x"] = self.MainCanvas.coords(self._connector["item"])[0] + 40
self._connector["y"] = self.MainCanvas.coords(self._connector["item"])[1] + 25
#______________________________________________________________________________________________________________________________________________________________________
def LocateObject2(self, event):
global ConnectCount
#sets the key "item" in the _connector dictionary to be equal to the object closest to the mouse
#sets the key "x2" and the key "y2" to be equal to the x and y coords of the object
#self._connector["connector"] = self.MainCanvas.find_closest(event.x, event.y)
self._connector["item2"] = self.MainCanvas.find_closest(event.x, event.y)[0]
if self._connector["item2"] % 2 == 0:
temp = self._connector["item2"] / 2
for d in range(len(self._object_data)):
if self._object_data[d]["item"] == temp:
self._object_data[d]["CoCount"] = self._object_data[d]["CoCount"] + 1
self._object_data[d]["Connect" + str(self._object_data[d]["CoCount"])] = ConnectCount
self._connector["item2"] = self._connector["item2"] - 1
else:
self._connector["item2"] = self._connector["item2"] + 1
temp = self._connector["item2"] / 2
for d in range(len(self._object_data)):
if self._object_data[d]["item"] == temp:
self._object_data[d]["CoCount"] = self._object_data[d]["CoCount"] + 1
self._object_data[d]["Connect" + str(self._object_data[d]["CoCount"])] = ConnectCount
self._connector["item2"] = self._connector["item2"] - 1
#print self._object_data, 'test2'
self._connector["x2"] = self.MainCanvas.coords(self._connector["item2"])[2] - 40
self._connector["y2"] = self.MainCanvas.coords(self._connector["item2"])[3] - 25
#an if statement to check whether the items are the same or if there is no item selected
if self._connector["item"] != self._connector["item2"]:
self._connector["tag"] = "True"
#sets the tags of the objects again to compensate for the tag change in the if statements previously
#tag = ["PCdrag", self._state_change["count"], self._state_change["tag"], "ColourSwitch", self._connector["tag"]]
#tag = ["PCdrag", self._state_change["tag"], "ColourSwitch", self._connector["tag"]]
#configures the items to change the tags of the items accordingly
#self.MainCanvas.itemconfig(self._connector["item"], tags = tag)
#self.MainCanvas.itemconfig(self._connector["item2"], tags = tag)
self.CreateLine()
self._connector["item"] = None
self._connector["connector"] = None
self._connector["item2"] = None
self._connector["x"] = 0
self._connector["y"] = 0
self._connector["x2"] = 0
self._connector["y2"] = 0
elif self._connector["item"] and self._connector["item2"] == 0:
self.Fail()
else:
self.Fail()
#______________________________________________________________________________________________________________________________________________________________________
#function that is called if the connector cannot be made
def Fail(self):
print 'Fail'
self._connector = {"connector": None, "item": None, "item2": None, "x": 0, "y": 0, "x2": 0, "y2": 0, "tag": "False"}
#this will set the tag bindings back to their original ones to allow you to drag the item again
self.MainCanvas.tag_bind("PCdrag", "<ButtonPress-1>", self.OnButtonPress)
self.MainCanvas.tag_bind("PCdrag", "<ButtonRelease-1>", self.OnButtonRelease)
self.MainCanvas.tag_bind("PCdrag", "<B1-Motion>", self.OnMotion)
#______________________________________________________________________________________________________________________________________________________________________
#This uses the find_closest method to get store the x and y positions of the nearest item into the dictionary
def OnButtonPress(self, event):
global itemsconnectors
global a
def Search(a):
for d in range(len(self._object_data)):
print 'hi1'
print self._object_data
if a in self._object_data[d]:
print 'hi'
## def Search():
## for d in range(len(a)):
## if 15 in a[d]["CoCount"]:
## print 'hi'
## else:
## print 'fail'
p = 0
item = self.MainCanvas.find_closest(event.x, event.y)[0]
tags = self.MainCanvas.gettags(item)
for tag in tags:
if tag.startswith("circle-"):
break
self._drag_data["item"] = tag
'''Begin drag of an object'''
# record the item and its location
#self._drag_data["item"] = self.MainCanvas.find_closest(event.x, event.y)[0]
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y
if item % 2 == 0:
item = item / 2
#runs for loop for the amount of nodes on screen
for d in range(len(self._object_data)):
#checks to find the current items dictionary
if self._object_data[d]["item"] == item:
#checks if the item has a connector
if self._object_data[d]["CoCount"] > 0:
#sets the amount of connectors the object has
connectors = len(self._object_data[d]) - 2
#runs a loop for the amount of connectors it has
for i in range(connectors):
#sets a to be equal to the current connector in the loop
a = self._object_data[d]["Connect" + str(i + 1)]
#prints the coords of the current connector
print self.MainCanvas.coords(len(itemlist) + a)
#appends that connector to a list
itemsconnectors.append(a)
print itemsconnectors
#runs loop for the amount of nodes on screen
for o in range(len(self._object_data)):
#LinkedItems.append(Search(self._object_data[d], a))
#checks if each node is connected to current connector
LinkedItems.append(Search(a))
else:
print 'No Connectors'
#print LinkedItems
#print itemlist
#print list(self.MainCanvas.gettags(self.MainCanvas.find_closest(event.x, event.y)))
#______________________________________________________________________________________________________________________________________________________________________
#This clears the dictionary once the mouse button has been released
def OnButtonRelease(self, event):
'''End drag of an object'''
# reset the drag information
self._drag_data["item"] = None
self._drag_data["x"] = 0
self._drag_data["y"] = 0
#______________________________________________________________________________________________________________________________________________________________________
def OnMotion(self, event):
b = len(self._object_data) + a
'''Handle dragging of an object'''
# compute how much this object has moved
delta_x = event.x - self._drag_data["x"]
delta_y = event.y - self._drag_data["y"]
# move the object the appropriate amount
self.MainCanvas.move(self._drag_data["item"], delta_x, delta_y)
#self.MainCanvas.coords(b, 10, 10 ,100 ,100)
# record the new position
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y
#______________________________________________________________________________________________________________________________________________________________________
def Delete_Object(self):
global IPvar
temp = IPvar
#deletes all the objects on the canvas
self.MainCanvas.delete('all')
#This dictionary is used to keep track of an item being dragged
self._drag_data = {"x": 0, "y": 0, "item": None}
#This dictionary is used to keep track of an item having it's state changed
self._state_change = {"item": None, "tag": "PCchange1", "colour": "Black"}
#This dictionary is used to keep track of the items being connected
self._connector = {"connector": None, "item": None, "item2": None, "x": 0, "y": 0, "x2": 0, "y2": 0, "tag": "False"}
self._data_store = {"item": None, "tag": self._state_change["tag"]}
#______________________________________________________________________________________________________________________________________________________________________
def ColourChange(self, event):
#sets the key "item" in the _state_change dictionaryto be equal to the object closest to the mouse
self._state_change["item"] = self.MainCanvas.find_closest(event.x, event.y)[0]
#a set of if statements to check what the current object colour is and change it depending on its colour
if self._state_change["colour"] == "Black":
self._state_change["colour"] = "Red"
#changes the tag of the object to reflect what colour it is
#this will then be used to set the PC to be either a sender, receiver or a router
self._state_change["tag"] = "PCchange2"
elif self._state_change["colour"] == "Red":
self._state_change["colour"] = "Blue"
self._state_change["tag"] = "PCchange3"
elif self._state_change["colour"] == "Blue":
self._state_change["colour"] = "Black"
self._state_change["tag"] = "PCchange1"
#an else for error checking. incase none of the if statements work
else:
print "Error"
#sets the tags of the objects again to compensate for the tag change in the if statements previously
#tag = ["PCdrag", self._state_change["count"], self._state_change["tag"], "ColourSwitch", self._connector["tag"]]
#tag = ["PCdrag", self._state_change["tag"], "ColourSwitch", self._connector["tag"]]
#configures the items to change the colour and the tags of the items accordingly
self.MainCanvas.itemconfig(self._state_change["item"], fill = self._state_change["colour"])
#print self.MainCanvas.gettags(self.MainCanvas.find_closest(event.x, event.y))
#______________________________________________________________________________________________________________________________________________________________________
class DragItem:
#Constructor
#Initiates when the class is called
#all the arguements are passed through
#the aruements have pre-set values that can be over written incase the program doesnt get passed anything
def __init__(self, window, width=100, height=100, colour="black", x_start=0, y_start=0, node = 5):
#window variables
self.window = window
tag = "circle-%d" % id(self)
#calls a method to create the computer object
self.circle = self.window.CreateComputer(x_start, y_start, colour, tag)
self.circle_text = self.window.CreateText(x_start, y_start, node, tag)
class Connector:
#Constructor
#Initiates when the class is called
#all the arguements are passed through
#the aruements have pre-set values that can be over written incase the program doesnt get passed anything
def __init__(self, window):
#window variables
self.window = window
self.window.ChangeClick()
You can use the canvas.coords()
method to redefine the points of the line ( http://effbot.org/tkinterbook/canvas.htm ). 您可以使用canvas.coords()
方法重新定义线的点( http://effbot.org/tkinterbook/canvas.htm )。
Assuming that line
is the id
or the tag
of the line that you want to move, canvas.coords(line)
will return the coordinates of the line. 假设该line
是您要移动的行的id
或tag
, canvas.coords(line)
将返回该行的坐标。 If it is a straight line, this will give you two points pt1
and pt2
representing the origin and the end of the line. 如果它是一条直线,这将为您提供两个点pt1
和pt2
代表该线的起点和终点。 One of these two points will be the start of your new line after you move the object. 这两个点之一将是您移动对象后新行的开始。
Then, you move the object. 然后,您移动对象。 When releasing the mouse button, a function will be called. 释放鼠标按钮时,将调用一个功能。 The first argument of that function is event
and contains the coordinates of the mouse, when you released the mouse button. 该函数的第一个参数是event
,包含释放鼠标按钮时鼠标的坐标。 These coordinates ( event.x
and event.y
) will be the end of your new line. 这些坐标( event.x
和event.y
)将在新行的结尾。
With this, you should have all the coordinates (the origin and end) of your new line and all you need to do is call canvas.coords(line, new_coords)
to move the line to its new position. 这样,您应该拥有新行的所有坐标(原点和终点),而您需要做的就是调用canvas.coords(line, new_coords)
将线移动到新位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.