2017-01-03 5 views
0

Ich erstelle eine GUI-Anwendung mit tkinter, und die App benötigt eine CAD-Schnittstelle für die Modellierung, daher habe ich das tkinter-Canvas-Widget dafür verwendet.Verhindern, dass gezoomte tkinter-Canvas-Objekte verschoben/Koordinaten geändert werden

Ich implementierte Methoden zum Verschieben und Zoomen der Zeichenfläche mit einer Maus basierend auf this thread. Das Problem, das ich habe, ist, dass das Zoomen der Leinwand die Koordinaten von Objekten verändert (manchmal ändern sich die Koordinaten von positiv zu negativ). Also, wenn ich ein Rechteck auf der Leinwand mit Hilfe von;

self.canvas.create_rectangle(0, 5, 75, 100, outline="black", fill="blue") self.canvas.create_text(100,125, anchor="nw", text="Click and drag to move the canvas\nScroll to zoom.")

Dann zoomen oder die Leinwand bewegen und zoomen, und ein weiteres Rechteck zeichnen verwendet;

self.canvas.create_rectangle(75, 5, 200, 100, outline="black", fill="red")

ich erwartet hatte, so etwas zu sehen;

Expected output image

Aber ich bekomme diese statt;

Actual output

Gibt es trotzdem, dies in tkinter zu beheben?

EDIT

Ich habe meinen Code mit Bryans Antwort aktualisiert. Ich konnte den Skalierungsfaktor im Attribut self.scale verfolgen, aber der Offset (verfolgt im self.offset Attribut) ist immer noch falsch. Ich bin nicht in der Lage, den kumulativen Offset vom wiederholten Zoomen zu berechnen. Neue Rechtecke skalieren richtig (Größe), aber der Offset/Ort ist immer noch ausgeschaltet.

Hier ist mein aktueller Code;

import Tkinter as tk 

class CAD(tk.Frame): 
    def __init__(self, root): 
     tk.Frame.__init__(self, root) 

     self.scale = 1 
     self.offset = [0, 0] 
     self.current_scale = [self.offset[0], self.offset[1], self.scale, self.scale] 

     self.canvas = tk.Canvas(self, width=400, height=350, background="bisque") 
     self.canvas.pack() 

     #Plot on the canvas 
     self.rect = self.canvas.create_rectangle(0, 5, 75, 100, outline="black", fill="blue") 
     self.canvas.create_text(100,125, anchor="nw", text=""" 
      Left click and drag to move the canvas 
      Scroll to zoom 
      Right click to draw rectangle""") 

     # Mouse bindings to the canvas 
     self.canvas.bind("<ButtonPress-1>", self.move_start) 
     self.canvas.bind("<B1-Motion>", self.move_move) 
     self.bind_all("<MouseWheel>", self.zoom) 
     self.canvas.bind("<ButtonPress-3>", self.draw) 

    # move 
    def move_start(self, event): 
     self.canvas.scan_mark(event.x, event.y) 
    def move_move(self, event): 
     self.canvas.scan_dragto(event.x, event.y, gain=1) 

    # zoom 
    def zoom(self, event): 
     true_x = self.canvas.canvasx(event.x) 
     true_y = self.canvas.canvasy(event.y) 
     if (event.delta > 0): 
      sc = 1.1 
     elif (event.delta < 0): 
      sc = 0.9 
     self.canvas.scale("all", true_x, true_y, sc, sc) 
     self.scale *= sc 

     self.offset = [sum(x) for x in zip(self.offset, [true_x, true_y])] 
     self.current_scale = [self.offset[0], self.offset[1], self.scale, self.scale] 

    def draw(self, event): 
     new_item = self.canvas.create_rectangle(75, 5, 200, 100, outline="black", fill="red") 
     self.canvas.scale(new_item, *self.current_scale) 


if __name__ == "__main__": 
    root = tk.Tk() 
    CAD(root).pack(fill="both", expand=True) 
    root.mainloop() 

END EDIT

Antwort

2

Ein Weg, um Ihr Problem zu erklären, ist dies:

  • I
  • ein Objekt habe ich eine Transformation auf das Objekt angewendet
  • ich erstellt neues Objekt ohne die Transformation
  • die Objekte nicht, wie ich erwarten
  • ausgerichtet

Um die Objekte erhalten Sie die Koordinaten aller neuen Elemente auf dem aktuellen Satz von Transformationen basiert zu transformieren ausrichten müssen.

Angenommen, Sie wissen, was der aktuelle Skalierungsfaktor ist, können Sie die Skalierung nur auf neue Elemente anwenden, die Sie erstellen.

Zum Beispiel der folgende Code ergibt ein Ergebnis, wie Sie in der Frage beschreiben, wo sich die beiden Rechtecke ausgerichtet sind, obwohl die zweite erstellt wurde, nachdem der erste skaliert wurde:

import tkinter as tk 

root = tk.Tk() 
canvas = tk.Canvas(root, width=400, height=400, background="bisque") 
canvas.pack(fill="both", expand=True) 

# start with one rectangle 
canvas.create_rectangle(0, 5, 75, 100, outline="black", fill="blue") 

# scale it, and save the scale 
current_scale = (0, 0, 1.5, 1.5) 
canvas.scale("all", *current_scale) 

# add a new item, and apply the same scale to it 
new_item = canvas.create_rectangle(75, 5, 200, 100, outline="black", fill="red") 
canvas.scale(new_item, *current_scale) 

root.mainloop() 
+0

Ich aktualisiert die Frage mit Ihrer Antwort und dem aktuellen Code, haben aber immer noch Probleme mit der Berechnung des kumulativen Offset. – Khristos

Verwandte Themen