Ich weiß nicht, ob meine Frage eine dumme oder eine knifflige Frage ist.Tkinter Canvas: Scale auf bewegtes Objekt
Mit Tkinter und Canvas gelang es mir, eine Scroll/Zoom-Funktion zu implementieren, die perfekt funktioniert, dank dieser Post Move and zoom a tkinter canvas with mouse. Ich füge auch eine Bindung hinzu, um die Leinwandgröße zu ändern, wenn sich die Fenstergröße ohne Schwierigkeit ändert.
Mit coords
und after
, habe ich keine Probleme, object
um zu bewegen.
Das Problem kam, als ich versuchte, alles zu kombinieren.
- Verschieben und Scrollen: keine Probleme
- Scrollen und Zoomen: ok
- Zoomen, Verschieben und Scrollen: funktionieren nicht
Der Code unten die Mühe reproduzieren (python 2.7
, die Arbeit an Fenstern). Was ich sehen kann, liegt das Problem an der Skalierung, die möglicherweise durch die Änderung von coords
der Objekte verursacht wird, die die Größenänderung des Arbeitsbereichs verursachen, und dann die Skalierung deaktivieren? Wenn das der Fall ist, brauche ich Hilfe, um dieses Problem zu lösen. Wenn es nicht der Fall ist, brauche ich Hilfe, um das Problem zu finden ...
Durch Entfernen/Deaktivieren der Zeile self.master.after(50, self.Display)
, Verschieben nicht mehr auftreten.
import Tkinter as tk
import math
class Example:
def __init__ (self, master):
self.master = master
self.interval = 0
self.SizeX, self.SizeY = master.winfo_width(), master.winfo_height()
#Canvas Frame
self.SystemCanvasFrame = tk.Frame(master, bg='black')
self.SystemCanvasFrame.grid(row=0, column=0)
#Canvas
self.SystemCanvas = tk.Canvas(self.SystemCanvasFrame, width=int(self.SizeX*0.75)-20, height=self.SizeY-20, bg="black")
self.SystemCanvas.focus_set()
self.xsb = tk.Scrollbar(self.SystemCanvasFrame, orient="horizontal", command=self.SystemCanvas.xview)
self.ysb = tk.Scrollbar(self.SystemCanvasFrame, orient="vertical", command=self.SystemCanvas.yview)
self.SystemCanvas.configure(scrollregion=(-500,-500,500,500))
self.SystemCanvas.configure(yscrollcommand=self.ysb.set, xscrollcommand=self.xsb.set)
#add the canvas with scroll bar in grid format
self.xsb.grid(row=1, column=0, sticky="ew")
self.ysb.grid(row=0, column=1, sticky="ns")
self.SystemCanvas.grid(row=0, column=0, sticky="nsew")
# This is what enables using the mouse to slide the window:
self.SystemCanvas.bind("<ButtonPress-1>", self.move_start)
self.SystemCanvas.bind("<B1-Motion>", self.move_move)
#windows scroll
self.SystemCanvas.bind("<MouseWheel>",self.zoomer)
#resize the main window
self.master.bind('<Configure>', self.UpdateCanvasSize)
#Create Objects
self.Size = 5 #object Size
x0 = 0
y0 = 0
x1 = self.Size
y1 = self.Size
self.SystemCanvas.create_oval(x0,y0,x1,y1, fill='green', outline='green', width=3, tags='Green')
self.SystemCanvas.create_oval(x0,y0,x1,y1, fill='red', outline='red', width=3, tags='Red')
self.SystemCanvas.create_oval(x0,y0,x1,y1, fill='yellow', outline='yellow', width=1, tags='Yellow')
self.Display()
def Display(self):
self.interval += 0.5 #speed parameter
GreenPos = self.UpdatePosition(0.1*self.interval, (0,0), 50)
RedPos = self.UpdatePosition(0.02*self.interval+180, (0,0), 200)
YellowPos = self.UpdatePosition(0.3*self.interval, RedPos, 10)
self.MoveObject('Green', GreenPos)
self.MoveObject('Red', RedPos)
self.MoveObject('Yellow', YellowPos)
self.master.after(50, self.Display) #Disable to zoom
def MoveObject (self, Obj, pos): #only move object that are in the field of view
"""Move Obj to the given position (tuple - xy)"""
ID = self.SystemCanvas.find_withtag(Obj)
#Convert the Center of the object to the coo need for tk
x0 = pos[0] - self.Size/2.0 #radius of the circle
y0 = pos[1] - self.Size/2.0
x1 = pos[0] + self.Size/2.0
y1 = pos[1] + self.Size/2.0
self.SystemCanvas.coords(ID, x0,y0,x1,y1)
def UpdatePosition(self, angle, center, distance):
"""Calculate next object position around the Center at the Distance and speed determine by Angle (in Radian) - Center of the object"""
h = center[0]
k = center[1]
radius = distance
Rad = angle
x = h+radius*math.cos(Rad)
y = k+radius*math.sin(Rad)
return (x, y)
def UpdateCanvasSize(self, event):
"""Permit to resize the canvas to the window"""
self.SizeX, self.SizeY = self.master.winfo_width(), self.master.winfo_height()
self.SystemCanvas.config(width=int(self.SizeX*0.75)-20, height=self.SizeY-20)
def move_start(self, event):
"""Detect the beginning of the move"""
self.SystemCanvas.scan_mark(event.x, event.y)
self.SystemCanvas.focus_set() #security, set the focus on the Canvas
def move_move(self, event):
"""Detect the move of the mouse"""
self.SystemCanvas.scan_dragto(event.x, event.y, gain=1)
def zoomer(self,event):
"""Detect the zoom action by the mouse. Zoom on the mouse focus"""
true_x = self.SystemCanvas.canvasx(event.x)
true_y = self.SystemCanvas.canvasy(event.y)
if (event.delta > 0):
self.SystemCanvas.scale("all", true_x, true_y, 1.2, 1.2)
elif (event.delta < 0):
self.SystemCanvas.scale("all", true_x, true_y, 0.8, 0.8)
self.SystemCanvas.configure(scrollregion = self.SystemCanvas.bbox("all"))
if __name__ == '__main__':
root = tk.Tk()
root.geometry('1125x750')
app = Example(root)
root.mainloop()