Python 如何通过tk/tcl启动小部件
我正在尝试制作一个GUI。我使用图像作为标记。 矩形表示操作区域,在那里我可以通过拖动标签来启动我的小部件或应用程序。怎么做 我制作了一个带有矩形的画布,并实现了拖放功能 我使用pack()实现了带有矩形的画布,并使用了拖放功能Python 如何通过tk/tcl启动小部件,python,user-interface,tkinter,Python,User Interface,Tkinter,我正在尝试制作一个GUI。我使用图像作为标记。 矩形表示操作区域,在那里我可以通过拖动标签来启动我的小部件或应用程序。怎么做 我制作了一个带有矩形的画布,并实现了拖放功能 我使用pack()实现了带有矩形的画布,并使用了拖放功能 import subprocess from tkinter import * class DragAndDrop: def __init__(self, boxes, apps, width=1920, height=1080, bg="white"):
import subprocess
from tkinter import *
class DragAndDrop:
def __init__(self, boxes, apps, width=1920, height=1080, bg="white"):
self.photos = []
self.__apps = {}
self.__boxes = set()
self.root = Tk()
self.canvas = Canvas(self.root, width=width, height=height, bg=bg)
self.canvas.pack()
for box in boxes:
self.__boxes.add(
self.canvas.create_rectangle(
box["x1"], box["y1"], box["x2"], box["y2"],
width=box["width"], fill=box["fill"]
)
)
for app in apps:
self.photos.append(PhotoImage(file=app["img"]))
self.__apps[(
self.canvas.create_image(app["x"], app["y"], image=self.photos[-1])
)] = app["cmd"]
self.__move = False
self.canvas.bind("<Button-1>", self.start_movement)
self.canvas.bind("<ButtonRelease-1>", self.stop_movement)
self.canvas.bind("<Motion>", self.movement)
def run(self):
self.root.mainloop()
def start_movement(self, event):
self.initi_x = self.canvas.canvasx(event.x)
self.initi_y = self.canvas.canvasy(event.y)
self.movingimage = self.canvas.find_closest(
self.initi_x, self.initi_y, halo=5
)
if self.movingimage[0] in self.__apps:
self.__move = True
def stop_movement(self, event):
self.__move = False
overlaps = self.canvas.find_overlapping(*self.canvas.bbox(self.movingimage))
if len(overlaps) > 1 and not self.movingimage[0] in self.__boxes and \
any(x in self.__boxes for x in overlaps):
subprocess.Popen(self.__apps[self.movingimage[0]])
def movement(self, event):
if self.__move:
end_x = self.canvas.canvasx(event.x)
end_y = self.canvas.canvasy(event.y)
deltax = end_x - self.initi_x
deltay = end_y - self.initi_y
self.initi_x = end_x
self.initi_y = end_y
self.canvas.move(self.movingimage, deltax, deltay)
if __name__ == "__main__":
boxes = (
{"x1": 618, "y1": 100, "x2": 693, "y2": 175, "width": 5, "fill": "white"},
{"x1": 693, "y1": 100, "x2": 768, "y2": 175, "width": 5, "fill": "white"},
{"x1": 618, "y1": 175, "x2": 693, "y2": 250, "width": 5, "fill": "green"},
{"x1": 693, "y1": 175, "x2": 768, "y2": 250, "width": 5, "fill": "green"},
{"x1": 618, "y1": 250, "x2": 693, "y2": 325, "width": 5, "fill": "blue"},
{"x1": 693, "y1": 250, "x2": 768, "y2": 325, "width": 5, "fill": "blue"},
{"x1": 618, "y1": 325, "x2": 693, "y2": 400, "width": 5, "fill": "yellow"},
{"x1": 693, "y1": 325, "x2": 768, "y2": 400, "width": 5, "fill": "yellow"},
{"x1": 543, "y1": 175, "x2": 618, "y2": 250, "width": 5, "fill": "dark orange"},
{"x1": 468, "y1": 175, "x2": 543, "y2": 250, "width": 5, "fill": "dark orange"},
{"x1": 768, "y1": 175, "x2": 843, "y2": 250, "width": 5, "fill": "red"},
{"x1": 843, "y1": 175, "x2": 918, "y2": 250, "width": 5, "fill": "red"},
)
apps = (
{"x": 125, "y": 125, "img": "chrome.png", "cmd": r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"},
{"x": 125, "y": 225, "img": "firefox.png", "cmd": r"C:\Program Files\Mozilla Firefox\firefox.exe"},
{"x": 125, "y": 325, "img": "np++.png", "cmd": r"C:\Program Files\Notepad++\notepad++.exe"},
{"x": 125, "y": 425, "img": "word.png", "cmd": r"C:\Program Files\Microsoft Office\root\Office16\WINWORD.exe"},
{"x": 200, "y": 125, "img": "excel.png", "cmd": r"C:\Program Files\Microsoft Office\root\Office16\EXCEL.EXE"},
{"x": 200, "y": 225, "img": "ppt.png", "cmd": r"C:\Program Files\Microsoft Office\root\Office16\POWERPNT.EXE"},
{"x": 200, "y": 325, "img": "outlook.png", "cmd": r"C:\Program Files\Microsoft Office\root\Office16\OUTLOOK.EXE"},
{"x": 200, "y": 425, "img": "access.png", "cmd": r"C:\Program Files\Microsoft Office\root\Office16\MSACCESS.EXE"},
{"x": 50, "y": 125, "img": "onenote.png", "cmd": r"C:\Program Files\Microsoft Office\root\Office16\ONENOTE.EXE"},
{"x": 50, "y": 225, "img": "pub.png", "cmd": r"C:\Program Files\Microsoft Office\root\Office16\MSPUB.EXE"},
{"x": 50, "y": 325, "img": "vlc.png", "cmd": r"C:\Program Files\VideoLAN\VLC\vlc.exe"},
{"x": 50, "y": 425, "img": "ccl.png", "cmd": r"C:\Program Files\CCleaner\CCleaner64.exe"},
)
dnd = DragAndDrop(boxes, apps)
dnd.run()
导入子流程
从tkinter进口*
类别DragAndDrop:
def u uu init uuuuu(self,box,app,宽度=1920,高度=1080,bg=“white”):
self.photos=[]
self.\uuu apps={}
self.\uuuu box=set()
self.root=Tk()
self.canvas=canvas(self.root,width=width,height=height,bg=bg)
self.canvas.pack()
对于盒子中的盒子:
self.\u box.add(
self.canvas.create_矩形(
方框[“x1”]、方框[“y1”]、方框[“x2”]、方框[“y2”],
宽度=方框[“宽度”],填充=方框[“填充”]
)
)
对于应用中的应用:
self.photos.append(PhotoImage(file=app[“img”]))
self.\u应用程序[(
self.canvas.create_image(应用程序[“x”],应用程序[“y”],image=self.photos[-1])
)]=应用程序[“cmd”]
self.\uu move=False
self.canvas.bind(“,self.start\u移动)
self.canvas.bind(“,self.stop\u移动)
self.canvas.bind(“,self.movement)
def运行(自):
self.root.mainloop()
def start_移动(自身、事件):
self.initi_x=self.canvas.canvasx(event.x)
self.initi_y=self.canvas.canvasy(event.y)
self.movingimage=self.canvas.find_(
self.initi_x,self.initi_y,光晕=5
)
如果self.\u应用程序中的self.movingimage[0]:
self.\uu move=True
def停止_移动(自身、事件):
self.\uu move=False
重叠=self.canvas.find_重叠(*self.canvas.bbox(self.movingimage))
如果len(重叠)>1而不是self.movingimage[0]在self.\u框和\
任何(重叠中x的自框中的x):
subprocess.Popen(self.\u应用程序[self.movingimage[0]]
def移动(自身、事件):
如果自行移动:
end_x=self.canvas.canvasx(event.x)
end_y=self.canvas.canvasy(event.y)
deltax=end_x-self.initi_x
deltay=end_y-self.initi_y
self.initi_x=end_x
self.initi_y=end_y
self.canvas.move(self.movingimage、deltax、deltay)
如果名称=“\uuuuu main\uuuuuuuu”:
方框=(
{“x1”:618,“y1”:100,“x2”:693,“y2”:175,“宽度”:5,“填充”:“白色”},
{“x1”:693,“y1”:100,“x2”:768,“y2”:175,“宽度”:5,“填充”:“白色”},
{“x1”:618,“y1”:175,“x2”:693,“y2”:250,“宽度”:5,“填充”:“绿色”},
{“x1”:693,“y1”:175,“x2”:768,“y2”:250,“宽度”:5,“填充”:“绿色”},
{“x1”:618,“y1”:250,“x2”:693,“y2”:325,“宽度”:5,“填充”:“蓝色”},
{“x1”:693,“y1”:250,“x2”:768,“y2”:325,“宽度”:5,“填充”:“蓝色”},
{“x1”:618,“y1”:325,“x2”:693,“y2”:400,“宽度”:5,“填充”:“黄色”},
{“x1”:693,“y1”:325,“x2”:768,“y2”:400,“宽度”:5,“填充”:“黄色”},
{“x1”:543,“y1”:175,“x2”:618,“y2”:250,“宽度”:5,“填充”:“深橙色”},
{“x1”:468,“y1”:175,“x2”:543,“y2”:250,“宽度”:5,“填充”:“深橙色”},
{“x1”:768,“y1”:175,“x2”:843,“y2”:250,“宽度”:5,“填充”:“红色”},
{“x1”:843,“y1”:175,“x2”:918,“y2”:250,“宽度”:5,“填充”:“红色”},
)
应用程序=(
{“x”:125,“y”:125,“img”:“chrome.png”,“cmd”:r“C:\ProgramFiles(x86)\Google\chrome\Application\chrome.exe”},
{“x”:125,“y”:225,“img”:“firefox.png”,“cmd”:r“C:\Program Files\Mozilla firefox\firefox.exe”},
{“x”:125,“y”:325,“img”:“np++.png”,“cmd”:r“C:\Program Files\Notepad++\Notepad++.exe”},
{“x”:125,“y”:425,“img”:“word.png”,“cmd”:r“C:\Program Files\Microsoft Office\root\Office16\WINWORD.exe”},
{“x”:200,“y”:125,“img”:“excel.png”,“cmd”:r“C:\Program Files\Microsoft Office\root\Office16\excel.EXE”},
{“x”:200,“y”:225,“img”:“ppt.png”,“cmd”:r“C:\Program Files\Microsoft Office\root\Office16\POWERPNT.EXE”},
{“x”:200,“y”:325,“img”:“outlook.png”,“cmd”:r“C:\Program Files\Microsoft Office\root\Office16\outlook.EXE”},
{“x”:200,“y”:425,“img”:“access.png”,“cmd”:r“C:\Program Files\Microsoft Office\root\Office16\MSACCESS.EXE”},
{“x”:50,“y”:125,“img”:“onenote.png”,“cmd”:r“C:\Program Files\Microsoft Office\root\Office16\onenote.EXE”},
{“x”:50,“y”:225,“img”:“pub.png”,“cmd”:r“C:\Program Files\Microsoft Office\root\Office16\MSPUB.EXE”},
{“x”:50,“y”:325,“img”:“vlc.png”,“cmd”:r“C:\Program Files\VideoLAN\vlc\vlc.exe”},
{“x”:50,“y”:425,“img”:“ccl.png”,“cmd”:r“C:\Program Files\CCleaner\CCleaner64.exe”},
)
dnd=DragAndDrop(盒子、应用程序)
dnd.run()
首先,这是一个非常酷的项目,欢迎参加
重构 在继续添加新逻辑之前,花时间清理当前代码是值得的 列表和循环 现在,将变量命名为
image0
,image1
<代码>图像12非常僵硬且不可缩放。如果您需要添加另一个框或应用程序图标,那么您基本上需要重写所有代码以适应更改。至于可伸缩性,如果您想要50、100或1000个应用程序呢?那将需要大量的打字
这就是为什么发明了许多类似阵列的结构。这个想法是一个单一的容器,可以将类似的物品放入其中。您可以浏览列表并对列表中的每一项执行操作。我不打算详细介绍列表和循环,但它们是任何编程任务的基本工具,因此学习如何使用它们对于作为一名编码人员取得进步是非常必要的
作为即时代码中的一个具体示例,使用一个变量images=[]
,代替image1
<代码>图像12。在大括号内,添加图像数据,然后使用images[n]
访问其中的一个,其中n
是要处理的图像的索引。你可以把它们绕成一圈
for image in images:
# do something with this image
{
"x": 125,
"y": 125,
"img": "np++.png",
"cmd": r"C:\Program Files (x86)\Notepad++\notepad++.exe"
}
def stop_movement(self, event):
self.__move = False
overlaps = self.canvas.find_overlapping(*self.canvas.bbox(self.movingimage))
if len(overlaps) > 1 and not self.movingimage[0] in self.__boxes and \
any(x in self.__boxes for x in overlaps):
subprocess.call(self.__apps[self.movingimage[0]])
import subprocess
from tkinter import *
class DragAndDrop:
def __init__(self, boxes, apps, width=1920, height=1080, bg="white"):
self.photos = []
self.__apps = {}
self.__boxes = set()
self.root = Tk()
self.canvas = Canvas(self.root, width=width, height=height, bg=bg)
self.canvas.pack()
for box in boxes:
self.__boxes.add(
self.canvas.create_rectangle(
box["x1"], box["y1"], box["x2"], box["y2"],
width=box["width"], fill=box["fill"]
)
)
for app in apps:
self.photos.append(PhotoImage(file=app["img"]))
self.__apps[(
self.canvas.create_image(app["x"], app["y"], image=self.photos[-1])
)] = {"cmd": app["cmd"], "running": False, "proc": None}
self.__move = False
self.canvas.bind("<Button-1>", self.start_movement)
self.canvas.bind("<ButtonRelease-1>", self.stop_movement)
self.canvas.bind("<Motion>", self.movement)
def run(self):
self.root.mainloop()
def start_movement(self, event):
self.initi_x = self.canvas.canvasx(event.x)
self.initi_y = self.canvas.canvasy(event.y)
self.movingimage = self.canvas.find_closest(
self.initi_x, self.initi_y, halo=5
)
if self.movingimage[0] in self.__apps:
self.__move = True
def stop_movement(self, event):
self.__move = False
overlaps = self.canvas.find_overlapping(*self.canvas.bbox(self.movingimage))
app = self.movingimage[0]
if len(overlaps) > 1 and app not in self.__boxes and not self.__apps[app]["running"] \
and any(x in self.__boxes for x in overlaps):
self.__apps[app]["proc"] = subprocess.Popen(self.__apps[app]["cmd"])
self.__apps[app]["running"] = True
elif app not in self.__boxes and self.__apps[app]["running"] \
and not any(x in self.__boxes for x in overlaps):
self.__apps[app]["proc"].kill()
self.__apps[app]["running"] = False
def movement(self, event):
if self.__move:
end_x = self.canvas.canvasx(event.x)
end_y = self.canvas.canvasy(event.y)
deltax = end_x - self.initi_x
deltay = end_y - self.initi_y
self.initi_x = end_x
self.initi_y = end_y
self.canvas.move(self.movingimage, deltax, deltay)
if __name__ == "__main__":
boxes = (
{"x1": 618, "y1": 100, "x2": 693, "y2": 175, "width": 5, "fill": "white"},
{"x1": 693, "y1": 100, "x2": 768, "y2": 175, "width": 5, "fill": "white"},
{"x1": 618, "y1": 175, "x2": 693, "y2": 250, "width": 5, "fill": "green"},
{"x1": 693, "y1": 175, "x2": 768, "y2": 250, "width": 5, "fill": "green"},
{"x1": 618, "y1": 250, "x2": 693, "y2": 325, "width": 5, "fill": "blue"},
{"x1": 693, "y1": 250, "x2": 768, "y2": 325, "width": 5, "fill": "blue"},
{"x1": 618, "y1": 325, "x2": 693, "y2": 400, "width": 5, "fill": "yellow"},
{"x1": 693, "y1": 325, "x2": 768, "y2": 400, "width": 5, "fill": "yellow"},
{"x1": 543, "y1": 175, "x2": 618, "y2": 250, "width": 5, "fill": "dark orange"},
{"x1": 468, "y1": 175, "x2": 543, "y2": 250, "width": 5, "fill": "dark orange"},
{"x1": 768, "y1": 175, "x2": 843, "y2": 250, "width": 5, "fill": "red"},
{"x1": 843, "y1": 175, "x2": 918, "y2": 250, "width": 5, "fill": "red"},
)
apps = (
{"x": 125, "y": 125, "img": "np++.png", "cmd": r"C:\Program Files (x86)\Notepad++\notepad++.exe"},
{"x": 125, "y": 225, "img": "vim.png", "cmd": r"C:\Program Files (x86)\Vim\vim74\vim.exe"},
)
dnd = DragAndDrop(boxes, apps)
dnd.run()