Wie? -- > Objekt per drag and drop verschieben

Fragen zu Tkinter.
Antworten
dd42
User
Beiträge: 16
Registriert: Mittwoch 30. April 2008, 21:15

Hi! :D

Dieses Programm erzeugt eine Raute mit einem Textfeld drin:

Code: Alles auswählen

from Tkinter import *

class Raute(Canvas):
	def __init__(self, x, y):
		self.x, self.y = x, y
		self.form = c.create_polygon(0+self.x,50+self.y,100+self.x,0+self.y,200+self.x,50+self.y,100+self.x,100+self.y,width=3,outline="black",activeoutline="green",fill="white")
		self.inhalt = c.create_window(self.x+90,self.y+50,window=Text(height=2, width=10))


master = Tk()
c = Canvas(master, width=1000, height=1000)
c.pack()
raute = Raute(100, 100)
master.mainloop()
:?: ... wie kann man die Rauten(bei mehreren Instanzen) per drag and drop auf der canvas verschieben?

:?: und wie bekomme ich überhaupt ein binding auf die klasse Raute? xD

Liebe Grüße, David
Zuletzt geändert von dd42 am Mittwoch 23. Juli 2008, 11:45, insgesamt 1-mal geändert.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo dd42

Hier ein Übungsbeispiel mit Einsatz genialer Tkinter-Canvas-Methoden:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# Scriptname: move_graphic_object_02.py (wuf 23.07.2008)

# Funktion: Verschieben von Canvas-Objekten mit der Maus bei
#           Gebrauch der 'Drag and Drop' Philosophie

import Tkinter as tk

def mouse_button1(mouse,object):
    """Maus fasst das Grafik-Objekt"""

    cv.drag_drop_flag = True

    #~~ Hebt das selektierte Objekt über die anderen
    cv.tag_raise(object,None)

    #~~ Drag-Koordinaten
    cv.mouse_x  = mouse.x
    cv.mouse_y  = mouse.y
    print cv.mouse_x,cv.mouse_y

def mouse_release1():
    """Maus lässt Grafik-Objekt fallen"""

    cv.drag_drop_flag = False

def mouse_move(mouse,object):
    """Maus bewegt sich über das Grafik-Objekt"""

    if cv.drag_drop_flag == True:
        #~~ Ermittle den Koordinaten-Offset
        xoff = mouse.x - cv.mouse_x
        yoff = mouse.y - cv.mouse_y

        #~~ Verschiebe das Grafik Objekt
        cv.move(object,xoff,yoff)

        #~~ Aktuelle Koordinaten
        cv.mouse_x = mouse.x
        cv.mouse_y = mouse.y

def mouse_enter(event):
    """Mause bewegt sich ins grafische Objekt"""

    cv.temp_cursor = cv['cursor']
    cv['cursor'] = 'hand1'

def mouse_leave(event):
    """Mause bewegt sich aus dem grafische Objekt"""

    cv['cursor'] = cv.temp_cursor

def event_bindings(object):
    """Binde Mausereignisse an das Grafik-Objekt"""

    # Event für linke Maustaste
    cv.tag_bind(object,"<Button-1>", lambda e,obj=object:mouse_button1(e,obj))
    # Event für loslassen der linken Maustaste
    cv.tag_bind(object,"<ButtonRelease 1>", lambda e,obj=object:mouse_release1())
    # Event für Mausbewegung
    cv.tag_bind(object,"<Motion>", lambda e,obj=object:mouse_move(e,obj))
    # Maus bewegt sich ins Grafik-Objekt
    cv.tag_bind(object,"<Enter>", lambda e:mouse_enter(e))
    # Maus bewegt sich aus dem Grafik-Objekt
    cv.tag_bind(object,"<Leave>", lambda e:mouse_leave(e))

#*** MODUL-TEST: CANVAS-OBJECT-MOVE WITH MOUSE ***
if __name__ == '__main__':

    root = tk.Tk()
    root.title("Drag&Drop Canvas-Object-Move")

    #~~ Erzeugt Canvasfläche für die Aufnahme von Canvas-Objekten
    cv = tk.Canvas(root,height=430,width=450,bd=0,relief='raised',bg='khaki2')
    cv.pack()

    #~~ Folgende Variablen werden dem cv.objekt angehängt
    cv.drag_drop_flag = False
    cv.mouse_x = None
    cv.mouse_y = None

    #~~~Eckkoordinaten für das Objekt gefüllter Kreis
    x0 = 50
    y0 = 50
    x1 = 200
    y1 = 200

    #~~ Zeichnet ein gefüllter Kreis
    object = cv.create_oval(x0,y0,x1,y1,fill='green',outline='darkgreen')
    event_bindings(object)

    #~~~Eckkoordinaten für das Objekt gefülltes Rechteck
    x0 = 150
    y0 = 150
    x1 = 300
    y1 = 300

    #~~ Zeichne ein gefülltes Rechteck
    object = cv.create_rectangle(x0,y0,x1,y1,fill='steelblue3',outline='darkblue')
    event_bindings(object)

    x0 = 100
    x1 = 100
    #~~ Start-Koordinaten für eine Raute
    object = cv.create_polygon(0+x0,50+y0,100+x0,0+y0,
                200+x0,50+y0,100+x0,100+y0,width=3,outline="black",
                activeoutline="green",fill="white")
    event_bindings(object)

    root.mainloop()
Gruss wuf :wink:
Take it easy Mates!
dd42
User
Beiträge: 16
Registriert: Mittwoch 30. April 2008, 21:15

Wow, Danke! :)

Aber ich will eigentlich form und inhalt gleichzeitig per drag and drop bewegen...
wie kann man alle Attribute, der Instanz von Raute per DnD verschieben :?:

Code: Alles auswählen

class Raute():
    def __init__(self, x, y):
        self.x, self.y = x, y
        self.form = c.create_polygon(0+self.x,50+self.y,100+self.x,0+self.y,200+self.x,50+self.y,100+self.x,100+self.y,width=3,outline="black",activeoutline="green",fill="white")
        self.inhalt = c.create_window(self.x+90,self.y+50,window=Text(height=2, width=10))
skypa
User
Beiträge: 97
Registriert: Freitag 5. Januar 2007, 03:13

http://www.python-forum.de/topic-9208,1 ... h&start=15

Schau da mal rein, da ist ne DnD Funktion enthalten, ähnlich zu dem was du suchst.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo dd42

Kannst du dies einmal ausprobieren. Vieleicht hat 'skypa' noch eine bessere Variante. Hatte leider keine Zeit seinen Code zu analysieren:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# Scriptname: move_graphic_object_03.py (wuf 23.07.2008)

# Funktion: Verschieben von Canvas-Objekten mit der Maus bei
#           Gebrauch der 'Drag and Drop' Philosophie

import Tkinter as tk

def mouse_button1(mouse,object):
    """Maus fasst das Grafik-Objekt"""

    cv.drag_drop_flag = True

    tags = cv.gettags(object)
    if tags != ():
        object = tags[0]

    #~~ Hebt das selektierte Objekt über die anderen
    cv.tag_raise(object,None)

    #~~ Drag-Koordinaten
    cv.mouse_x  = mouse.x
    cv.mouse_y  = mouse.y
    print cv.mouse_x,cv.mouse_y

def mouse_release1():
    """Maus lässt Grafik-Objekt fallen"""

    cv.drag_drop_flag = False

def mouse_move(mouse,object):
    """Maus bewegt sich über das Grafik-Objekt"""

    tags = cv.gettags(object)
    if tags != ():
        object = tags[0]

    if cv.drag_drop_flag == True:
        #~~ Ermittle den Koordinaten-Offset
        xoff = mouse.x - cv.mouse_x
        yoff = mouse.y - cv.mouse_y

        #~~ Verschiebe das Grafik Objekt
        cv.move(object,xoff,yoff)

        #~~ Aktuelle Koordinaten
        cv.mouse_x = mouse.x
        cv.mouse_y = mouse.y

def mouse_enter(event):
    """Mause bewegt sich ins grafische Objekt"""

    cv.temp_cursor = cv['cursor']
    cv['cursor'] = 'hand1'

def mouse_leave(event):
    """Mause bewegt sich aus dem grafische Objekt"""

    cv['cursor'] = cv.temp_cursor

def event_bindings(object):
    """Binde Mausereignisse an das Grafik-Objekt"""

    # Event für linke Maustaste
    cv.tag_bind(object,"<Button-1>", lambda e,obj=object:mouse_button1(e,obj))
    # Event für loslassen der linken Maustaste
    cv.tag_bind(object,"<ButtonRelease 1>", lambda e,obj=object:mouse_release1())
    # Event für Mausbewegung
    cv.tag_bind(object,"<Motion>", lambda e,obj=object:mouse_move(e,obj))
    # Maus bewegt sich ins Grafik-Objekt
    cv.tag_bind(object,"<Enter>", lambda e:mouse_enter(e))
    # Maus bewegt sich aus dem Grafik-Objekt
    cv.tag_bind(object,"<Leave>", lambda e:mouse_leave(e))

#*** MODUL-TEST: CANVAS-OBJECT-MOVE WITH MOUSE ***
if __name__ == '__main__':

    root = tk.Tk()
    root.title("Drag&Drop Canvas-Object-Move")

    #~~ Erzeugt Canvasfläche für die Aufnahme von Canvas-Objekten
    cv = tk.Canvas(root,height=430,width=450,bd=0,relief='raised',bg='khaki2')
    cv.pack()

    #~~ Folgende Variablen werden dem cv.objekt angehängt
    cv.drag_drop_flag = False
    cv.mouse_x = None
    cv.mouse_y = None

    x0 = 100
    y0 = 100
    #~~ Start-Koordinaten für eine Raute
    raute = cv.create_polygon(0+x0,50+y0,100+x0,0+y0,
                200+x0,50+y0,100+x0,100+y0,width=3,outline="black",
                activeoutline="green",fill="white")
    event_bindings(raute)

    inhalt = cv.create_window(x0+90,y0+50,window=tk.Text(height=2, width=10))

    cv.addtag_withtag('form',raute)
    cv.addtag_withtag('form',inhalt)


    root.mainloop()
Gruss wuf :wink:
Take it easy Mates!
dd42
User
Beiträge: 16
Registriert: Mittwoch 30. April 2008, 21:15

Tausend Dank für eure Antworten =) :D

Ich werd jetzt mal schaun ob ich mit diesem code weiterkomme ;)
sonst meld ich mich wieder in diesem Thread oder schick euch ne PM

mfg. David
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Du solltest Dir auch einmal Tkdnd.py unter Python24\lib\lib-tk oder ähnlichem Pfad ansehen.
MfG
HWK
dd42
User
Beiträge: 16
Registriert: Mittwoch 30. April 2008, 21:15

ok ich bin bissal weitergekommen aber jetz steck ich :roll:

Das Programm kann zur Zeit:
- Mit der Klasse lassen sich Rauten mit Textfeldern drin erstellen
- Diese Rauten lassen sich per drag and drop verschieben und die Textfelder wandern mit
- der Text in den Textfeldern ist zentriert

so weit funktioniert alles gut

Ziele(bitte helft mir bei den ersten zwei, für 3 und 4 vllt habt ihr ja eine Idee :-P):
1- wenn die anzahl der Zeichen von Textfeld 8 zeichen überschreitet soll eine weitere Zeile eingefügt werden
2- wenn man dann zwei Zeilen hat, Zeichen löscht und daher wieder unter 8 zeichen kommt wird wieder auf ein einzeiliges Textfeld gewechselt
(3-) sobald das Textfeld zu viele Zeichen beinhaltet alsdass sie in zwei zeilen bei standardgröße der Raute untergebracht werden könnten soll die Raute vergrößert werden und das noch immer zweizeilige Textfeld mit mehr Zeichen verlängert werden
((4-)) zwischen den Rauten soll man linien ziehen können indem man mit der rechten maustaste auf die erste Raute1 dann auf die zweite Raute2 drückt und als folge eine Linie zwischen Raute1 und Raute2 erzeugt

.....XDD
hier der derzeitige Code:

Code: Alles auswählen

#!/usr/bin/env python 
# -*- coding: UTF-8 -*- 

# Scriptname: visualpython.py (David Dürnwirth 23.07.2008) 

# Funktion: Graphische Erstellung von Flussdiagrammen
#           und deren Umwandlung in Code 

import Tkinter as tk 

def mouse_button1(mouse,object): 
    """Maus fasst das Grafik-Objekt""" 

    cv.drag_drop_flag = True 

    tags = cv.gettags(object) 
    if tags != (): 
        object = tags[0] 

    #~~ Hebt das selektierte Objekt über die anderen 
    cv.tag_raise(object,None) 

    #~~ Drag-Koordinaten 
    cv.mouse_x  = mouse.x 
    cv.mouse_y  = mouse.y 

def mouse_release1(): 
    """Maus lässt Grafik-Objekt fallen""" 

    cv.drag_drop_flag = False 

def mouse_move(mouse,object): 
    """Maus bewegt sich über das Grafik-Objekt""" 

    tags = cv.gettags(object) 
    if tags != (): 
        object = tags[0] 

    if cv.drag_drop_flag == True: 
        #~~ Ermittle den Koordinaten-Offset 
        xoff = mouse.x - cv.mouse_x 
        yoff = mouse.y - cv.mouse_y 

        #~~ Verschiebe das Grafik Objekt 
        cv.move(object,xoff,yoff) 

        #~~ Aktuelle Koordinaten 
        cv.mouse_x = mouse.x 
        cv.mouse_y = mouse.y 

def mouse_enter(event): 
    """Mause bewegt sich ins grafische Objekt""" 

    cv.temp_cursor = cv['cursor'] 
    cv['cursor'] = 'hand1' 

def mouse_leave(event): 
    """Mause bewegt sich aus dem grafische Objekt""" 

    cv['cursor'] = cv.temp_cursor 

def event_bindings(object): 
    """Binde Mausereignisse an das Grafik-Objekt""" 

    # Event für linke Maustaste 
    cv.tag_bind(object,"<Button-1>", lambda e,obj=object:mouse_button1(e,obj)) 
    # Event für loslassen der linken Maustaste 
    cv.tag_bind(object,"<ButtonRelease 1>", lambda e,obj=object:mouse_release1()) 
    # Event für Mausbewegung 
    cv.tag_bind(object,"<Motion>", lambda e,obj=object:mouse_move(e,obj)) 
    # Maus bewegt sich ins Grafik-Objekt 
    cv.tag_bind(object,"<Enter>", lambda e:mouse_enter(e)) 
    # Maus bewegt sich aus dem Grafik-Objekt 
    cv.tag_bind(object,"<Leave>", lambda e:mouse_leave(e)) 

class Zaehler(object):
    Anzahl = 0
    def __init__(self):
        type(self).Anzahl += 1	
    
        
    def __del__(self):
        type(self).Anzahl -= 1
    

    def refreshRaute(self,zeilen,x,y,text=""):   ##### diese Funktion zeichnet Raute und zugehöriges Textfenster####
        self.raute = cv.create_polygon(0+x,50+y,100+x,0+y, 
                                       200+x,50+y,100+x,100+y,width=3,outline="black", 
                                       activeoutline="green",fill="white")
        if zeilen==1:       ###### Auf die Zeilenanzahl beziehen sich die Zeichen
            zeichen=15
        else:
            zeichen=30
        self.text = tk.Text(height=zeilen, width=zeichen,highlightcolor="white", font=("Arial", 16))
        self.text.insert(tk.END,text)
        self.text.tag_add("alles", "0.0", tk.END)
        self.text.tag_config("alles", justify=tk.CENTER)
        self.text.bind('<KeyRelease>', self.Keyrelease)
        self.inhalt = cv.create_window(x+100,y+50,window=self.text)
        self.identi = "tag" + str(Raute.Anzahl)
        cv.addtag_withtag(self.identi,self.raute)
        cv.addtag_withtag(self.identi,self.inhalt)
        event_bindings(self.raute)

class Raute(Zaehler):
    def __init__(self,x0,y0):
        Zaehler.__init__(self)
        self.x0 = x0
        self.y0 = y0
        self.refreshRaute(1,self.x0,self.y0)

    
    def Keyrelease(self, event):
        self.text.tag_add("alles", "0.0", tk.END)
        self.text.tag_config("alles", justify=tk.CENTER)
        self.unformatinhalt = str(self.text.get(0.0,tk.END))
        self.formatinhalt = self.unformatinhalt[:-1]
        self.leninhalt = len(self.formatinhalt)
        if self.leninhalt<=9:
            pass     ##########!!! Hier soll die Funktion sein die die Zeilenanzahl auf 1 setzt !!!!#######
                     ##########!!! und die Zeichenanzahl pro Zeile vergrößert !!!!!######
	        #self.refreshRaute(1,self.x0,self.y0,self.formatinhalt)
        elif self.leninhalt>9:
            pass     ##########!!! Hier soll die Funktion sein die die Zeilenanzahl auf 2 setzt!!!!#######
                     ##########!!! und die Zeichenanzahl pro Zeile verkleinert !!!!#######
        print "!" + self.formatinhalt + "?"
        print self.leninhalt
    
    def __del__(self):
        pass
    

#*** MODUL-TEST *** 
if __name__ == '__main__': 

    root = tk.Tk() 
    root.title("Drag&Drop Canvas-Object-Move") 

    # Erzeugt Canvasfläche für die Aufnahme von Canvas-Objekten 
    cv = tk.Canvas(root,height=1000,width=1200,bd=0,relief='raised',bg='white') 
    cv.pack() 

    # Folgende Variablen werden dem cv.objekt angehängt 
    cv.drag_drop_flag = False 
    cv.mouse_x = None 
    cv.mouse_y = None 


    raute = Raute(1000, 100)
    raute2 = Raute(200, 200)
    raute3 = Raute(1000, 100)
    print cv.find_closest(0,0)

    root.mainloop()
Bitte helft mir bei 1- und 2-
Liebe Grüße, David =)
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo dd42

Für den Fall-1 und Fall-2 kannst du einmals das folgende ausprobieren:

Code: Alles auswählen

        if self.leninhalt<=9:
            self.text.config(height=1)
#             pass     ##########!!! Hier soll die Funktion sein die die Zeilenanzahl auf 1 setzt !!!!#######
#                      ##########!!! und die Zeichenanzahl pro Zeile vergrößert !!!!!######
            #self.refreshRaute(1,self.x0,self.y0,self.formatinhalt)
        elif self.leninhalt>9:
            self.text.config(height=2)
#             pass     ##########!!! Hier soll die Funktion sein die die Zeilenanzahl auf 2 setzt!!!!#######
#                      ##########!!! und die Zeichenanzahl pro Zeile verkleinert !!!!#######
Gruss wuf :wink:
Take it easy Mates!
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo dd42

Zum Fall-3 habe ich das dir schon präsentierte Code-Schnipsel erweitert. Um ein Canvas-Grafik-Objekt zu vergrössern oder zu verkleinern bietet dir Tkinter die starke Methode 'scale' an. Versuche sie in deinen Code zu übernehmen:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# Scriptname: move_graphic_object_04.py (wuf 25.07.2008)

# Funktion: Verschieben von Canvas-Objekten mit der Maus bei
#           Gebrauch der 'Drag and Drop' Philosophie

import Tkinter as tk

def mouse_button1(mouse,object):
    """Maus fasst das Grafik-Objekt"""

    cv.drag_drop_flag = True

    tags = cv.gettags(object)
    if tags != ():
        object = tags[0]

    #~~ Hebt das selektierte Objekt über die anderen
    cv.tag_raise(object,None)

    #~~ Drag-Koordinaten
    cv.mouse_x  = mouse.x
    cv.mouse_y  = mouse.y
    print cv.mouse_x,cv.mouse_y

def mouse_release1():
    """Maus lässt Grafik-Objekt fallen"""

    cv.drag_drop_flag = False

def mouse_move(mouse,object):
    """Maus bewegt sich über das Grafik-Objekt"""

    tags = cv.gettags(object)
    if tags != ():
        object = tags[0]

    if cv.drag_drop_flag == True:
        #~~ Ermittle den Koordinaten-Offset
        xoff = mouse.x - cv.mouse_x
        yoff = mouse.y - cv.mouse_y

        #~~ Verschiebe das Grafik Objekt
        cv.move(object,xoff,yoff)

        #~~ Aktuelle Koordinaten
        cv.mouse_x = mouse.x
        cv.mouse_y = mouse.y

def mouse_enter(event):
    """Mause bewegt sich ins grafische Objekt"""

    cv.temp_cursor = cv['cursor']
    cv['cursor'] = 'hand1'

def mouse_leave(event):
    """Mause bewegt sich aus dem grafische Objekt"""

    cv['cursor'] = cv.temp_cursor

def event_bindings(object):
    """Binde Mausereignisse an das Grafik-Objekt"""

    # Event für linke Maustaste
    cv.tag_bind(object,"<Button-1>", lambda e,obj=object:mouse_button1(e,obj))
    # Event für loslassen der linken Maustaste
    cv.tag_bind(object,"<ButtonRelease 1>", lambda e,obj=object:mouse_release1())
    # Event für Mausbewegung
    cv.tag_bind(object,"<Motion>", lambda e,obj=object:mouse_move(e,obj))
    # Maus bewegt sich ins Grafik-Objekt
    cv.tag_bind(object,"<Enter>", lambda e:mouse_enter(e))
    # Maus bewegt sich aus dem Grafik-Objekt
    cv.tag_bind(object,"<Leave>", lambda e:mouse_leave(e))

def button_callback(function):
    """Eine Schaltfächhe wurde aktiviert"""

    print function

    if function == 'up':
        cv.move('raute',0,-5)
    elif function == 'down':
        cv.move('raute',0,5)
    elif function == 'left':
        cv.move('raute',-5,0)
    elif function == 'right':
        cv.move('raute',5,0)
    elif function == '+':
        cv.scale('raute', x0, y0, x_scale_up_fac, y_scale_up_fac)
    elif function == '-':
        cv.scale('raute', x0, y0, x_scale_down_fac, y_scale_down_fac)

#*** MODUL-TEST: CANVAS-OBJECT-MOVE WITH MOUSE ***
if __name__ == '__main__':

    root = tk.Tk()
    root.title("Drag&Drop Canvas-Object-Move")

    #~~ Erzeugt Canvasfläche für die Aufnahme von Canvas-Objekten
    cv = tk.Canvas(root,height=430,width=450,bd=0,relief='raised',bg='khaki2')
    cv.pack()

    #~~ Folgende Variablen werden dem cv.objekt angehängt
    cv.drag_drop_flag = False
    cv.mouse_x = None
    cv.mouse_y = None

    button_frame = tk.Frame(root,bd=1,highlightthickness=0)
    button_frame.pack(side='bottom',fill='x')

    buttons = ('up', 'down', 'left', 'right', '+','-')

    for button in buttons:
        button = tk.Button(button_frame, bd=1, text=button,
            highlightthickness=0,
            command=lambda function=button:button_callback(function))
        button.pack(side='left')

    x0 = 100
    y0 = 100
    #~~ Start-Koordinaten für eine Raute
    raute = cv.create_polygon(0+x0,50+y0,100+x0,0+y0,
                200+x0,50+y0,100+x0,100+y0,width=3,outline="black",
                activeoutline="green",fill="white")
    event_bindings(raute)

    inhalt = cv.create_window(x0+90,y0+50,window=tk.Text(height=2, width=10))

    cv.addtag_withtag('raute',raute)
    cv.addtag_withtag('raute',inhalt)

    x_scale_up_fac = y_scale_up_fac = 1.1
    x_scale_down_fac = y_scale_down_fac = 0.9

    root.mainloop()
Gruss wuf :wink:
Take it easy Mates!
dd42
User
Beiträge: 16
Registriert: Mittwoch 30. April 2008, 21:15

danke =) ich werd mal den code einbaun und schaun wie ich die Verbindungslinien implementieren kann

¡Hasta luego! :wink:
tommes
User
Beiträge: 3
Registriert: Samstag 26. Juli 2008, 14:43

Hallo David,

bin gerade zufällig über Deinen Post gestolpert. Ich habe letztens auch mit solchen Dingen wie "Verschieben von zusammengesetzten Objekten" und "Zeichnen von Verbindungslinien" herum experimentiert und daher auch die Codebeispiele in Deinem Thread mit großem Interesse gelesen.

Vielleicht ist ja bei meinen Sachen noch etwas hilfreiches dabei:

[wiki]User Group Köln/VortragUMLTkinter[/wiki]

Viele Grüße
Thomas
dd42
User
Beiträge: 16
Registriert: Mittwoch 30. April 2008, 21:15

tommes hat geschrieben: Vielleicht ist ja bei meinen Sachen noch etwas hilfreiches dabei:

[wiki]User Group Köln/VortragUMLTkinter[/wiki]
Hi Thomas! :)

danke für dein post dein Projekt ist meinem ziemlich ähnlich, ich werd davon sicher viel lernen

aja, dazu gleich mal eine frage *gg*

:?: Warum läuft drag and drop bei deinem programm so flüssig? (Zumindest im gegensatz zur [auch guten 8) ] drag and drop lösung von wuf)
:arrow: vllt wirkt das ja auch nur so weil bei beidem move() verwendet wurde ?? :?

bis bald, david :D
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Entry- bzw. Text-Widget in der Raute ist optisch ja alles andere als ein Leckerbissen. Praktisch dürfte es wohl auch so sein, dass man einmalig einen Text in eine Raute schreibt und diesen Text dann ggf. noch mal ändern muss, er aber nicht andauernd verändert wird.

Man könnte darum mal über folgendes nachdenken: Neu erstellte Raute ist zunächst leer. Bei Doppelklick öffnet sich ein zwei- oder mehrzeiliges Text-Widget in bzw. über der Raute - dass es ggf. über die Raute hinausreicht, macht nichts - s.u. Danach gibt man die gewünschten Informationen in das Eingabefeld ein und schließt die Eingabe mit einfachem Mausklick in die Raute (außerhalb des Eingabefeldes) ab.

Das Eingabefeld verschwindet, der Eingabetext wird mittels create_text in einen Text umgewandelt, der innerhalb der Raute platziert wird. Erneuter Doppelklick in der Raute aktiviert bei Änderungswunsch wieder das Eingabefeld.

Für die Größenanpassung des Textes an die Raute bzw. umgekehrt, könnte man z.B. so vorgehen, dass man eine Rautenstandardgröße verwendet und eine Mindestschriftgröße festlegt. Der in der Raute zu zeigende Text wird dann auf die "größtmögliche" Schrift eingestellt, so dass der Text noch in der Raute darstellbar ist. Muss dafür die Mindestschriftgröße unterschritten werden, wird die Raute entsprechend vergrößert, so dass in Mindestschriftgröße dargestellt werden kann.
tommes
User
Beiträge: 3
Registriert: Samstag 26. Juli 2008, 14:43

Hi David,
aja, dazu gleich mal eine frage *gg*

:?: Warum läuft drag and drop bei deinem programm so flüssig? (Zumindest im gegensatz zur [auch guten 8) ] drag and drop lösung von wuf)
:arrow: vllt wirkt das ja auch nur so weil bei beidem move() verwendet wurde ?? :?
Ehrlich gesagt, habe ich keine Ahnung. Von der Art der Programmierung der Move-Funktionialität gibt es aus meiner Sicht keinen Unterschied. Bei beiden Varianten werden Tags verwendet, um die kombinierten Objekte zu identifizieren. Ich habe auch einmal beide Programme nebeneinander getestet. Und da sieht das Bewegen der Objekte auch exakt gleich aus.

Vielleicht lässt Du einfach einmal probeweise das Text-Entry-Field weg? Möglicherweise kann er das in Deiner Umgebung ja nur holprig verschieben? :?: Ist aber nur so eine Idee.

Übrigens: Die Sache mit den lambda-Forms beim Binden der Ereignisse an die Objekte finde ich äußerst geschickt. Hat etwas gedauert, bis ich kapiert habe, wie es funktioniert. :lol:

Gruß
Thomas
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo dd42

Ich würde auch die Eingabephilosophie von 'numerix' anwenden. Eingebettete normale Tk-Widgets die mittels der create_window-Methode erstellt wurden lassen sich nicht so elegant bewegen wie echte Text-Grafikobjekte die mit der create_text-Methode erzeugt wurden. Ein weiterer Nachteil von eingebetteten Tk-Widgets (wie Entry,Text...usw.) ist, sie lassen sich nicht durch Canvas-Grafikobjekte (wie Polygons, Rechtecke, Linien,Texte usw.) abdecken!

Hier ein weiteres angepasstes Beispiel mit einemn Canvas-Textobjekt in der Raute. Die Performance-Zunahme für Bewegungsabläufe ist auffällig besser:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# Scriptname: move_graphic_object_05.py (wuf 27.07.2008)

# Funktion: Verschieben von Canvas-Objekten mit der Maus bei
#           Gebrauch der 'Drag and Drop' Philosophie

import Tkinter as tk

def mouse_button1(mouse,object):
    """Maus fasst das Grafik-Objekt"""

    cv.drag_drop_flag = True

    tags = cv.gettags(object)
    if tags != ():
        object = tags[0]

    #~~ Hebt das selektierte Objekt über die anderen
    cv.tag_raise(object,None)

    #~~ Drag-Koordinaten
    cv.mouse_x  = mouse.x
    cv.mouse_y  = mouse.y
    print cv.mouse_x,cv.mouse_y

def mouse_release1():
    """Maus lässt Grafik-Objekt fallen"""

    cv.drag_drop_flag = False

def mouse_move(mouse,object):
    """Maus bewegt sich über das Grafik-Objekt"""

    tags = cv.gettags(object)
    if tags != ():
        object = tags[0]

    if cv.drag_drop_flag == True:
        #~~ Ermittle den Koordinaten-Offset
        xoff = mouse.x - cv.mouse_x
        yoff = mouse.y - cv.mouse_y

        #~~ Verschiebe das Grafik Objekt
        cv.move(object,xoff,yoff)

        #~~ Aktuelle Koordinaten
        cv.mouse_x = mouse.x
        cv.mouse_y = mouse.y

def mouse_enter(event):
    """Mause bewegt sich ins grafische Objekt"""

    cv.temp_cursor = cv['cursor']
    cv['cursor'] = 'hand1'

def mouse_leave(event):
    """Mause bewegt sich aus dem grafische Objekt"""

    cv['cursor'] = cv.temp_cursor

def event_bindings(object):
    """Binde Mausereignisse an das Grafik-Objekt"""

    # Event für linke Maustaste
    cv.tag_bind(object,"<Button-1>", lambda e,obj=object:mouse_button1(e,obj))
    # Event für loslassen der linken Maustaste
    cv.tag_bind(object,"<ButtonRelease 1>", lambda e,obj=object:mouse_release1())
    # Event für Mausbewegung
    cv.tag_bind(object,"<Motion>", lambda e,obj=object:mouse_move(e,obj))
    # Maus bewegt sich ins Grafik-Objekt
    cv.tag_bind(object,"<Enter>", lambda e:mouse_enter(e))
    # Maus bewegt sich aus dem Grafik-Objekt
    cv.tag_bind(object,"<Leave>", lambda e:mouse_leave(e))

def button_callback(function):
    """Eine Schaltfächhe wurde aktiviert"""

    print function

    if function == 'up':
        cv.move('raute',0,-5)
    elif function == 'down':
        cv.move('raute',0,5)
    elif function == 'left':
        cv.move('raute',-5,0)
    elif function == 'right':
        cv.move('raute',5,0)
    elif function == '+':
        cv.scale('raute', x0, y0, x_scale_up_fac, y_scale_up_fac)
    elif function == '-':
        cv.scale('raute', x0, y0, x_scale_down_fac, y_scale_down_fac)

#*** MODUL-TEST: CANVAS-OBJECT-MOVE WITH MOUSE ***
if __name__ == '__main__':

    root = tk.Tk()
    root.title("Drag&Drop Canvas-Object-Move")

    #~~ Erzeugt Canvasfläche für die Aufnahme von Canvas-Objekten
    cv = tk.Canvas(root,height=430,width=450,bd=0,relief='raised',bg='khaki2')
    cv.pack()

    #~~ Folgende Variablen werden dem cv.objekt angehängt
    cv.drag_drop_flag = False
    cv.mouse_x = None
    cv.mouse_y = None

    button_frame = tk.Frame(root,bd=1,highlightthickness=0)
    button_frame.pack(side='bottom',fill='x')

    buttons = ('up', 'down', 'left', 'right', '+','-')

    for button in buttons:
        button = tk.Button(button_frame, bd=1, text=button,
            highlightthickness=0,
            command=lambda function=button:button_callback(function))
        button.pack(side='left')

    x0 = 100
    y0 = 100
    #~~ Start-Koordinaten für eine Raute
    raute = cv.create_polygon(0+x0,50+y0,100+x0,0+y0,
                200+x0,50+y0,100+x0,100+y0,width=3,outline="black",
                activeoutline="green",fill="white")
    event_bindings(raute)

#    inhalt = cv.create_window(x0+90,y0+50,window=tk.Text(height=2, width=10))
    inhalt = cv.create_text(100+x0, 50+y0, anchor='center', width=150,
        text="Python and Tkinter are good Companions!")

    cv.addtag_withtag('raute',raute)
    cv.addtag_withtag('raute',inhalt)

    x_scale_up_fac = y_scale_up_fac = 1.1
    x_scale_down_fac = y_scale_down_fac = 0.9

    root.mainloop()
Gruss wuf :wink:
Zuletzt geändert von wuf am Sonntag 27. Juli 2008, 18:51, insgesamt 1-mal geändert.
Take it easy Mates!
dd42
User
Beiträge: 16
Registriert: Mittwoch 30. April 2008, 21:15

bisher habe ich das programm nur auf mac getestet tkaqua baut ja auf carbon auf (und alle carbon programme... wie zb.: Photoshop, Flash oder M$ Office for Mac) laufen extrem langsam[im gegensatz zu cocoa]
durch carbon entsteht ein extremer performance verlust!

heute habe ich das ganze mal auf MIC®O$OFT Windows getestet ==> programm sehr performant :)

@ numerix: gute Idee, aber unpraktisch, und kaum verbesserte performance

das "stocken" auf mac liegt nicht an dem Text Widget, sondern an Carbon (in snow leopard wird Carbon vllt sogar ganz entfernt, ohne ersatz :x )

nachdem mir mac nicht so wichtig ist :twisted: werd ich so weiter machen mit dem "Window-Text-Widget" *gg*

¡hasta pronto!

edit: ich kenn mich mit der scale methode nicht aus :( wisst ihr was ich da falsch mach? [um den störenden Code, beim neuladen der Threads zu sparen hab ichs auf dpaste geladen] http://dpaste.com/67741/ Problem in Zeile 117

edit: kenn mich jetzt mit der scale methode aus ^^
Antworten