Wie? -- > Objekt per drag and drop verschieben

Fragen zu Tkinter.
Antworten
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