Frame... x,y zentrieren

Fragen zu Tkinter.
Antworten
Alexci
User
Beiträge: 44
Registriert: Dienstag 18. April 2006, 23:08

Hallo,

Man kann mit event.x und event.y lesen wo sich der Mauscursor in einem Frame befindet. Kann man aber auch befehlen, dass der Mauscursor auf die X,Y koordinaten in einem Frame gehet und dies auch Zentriert?

Oder, z.b., die koordidaten der oberen linken Ecke in einem Frame sind (0,0). Gibt es ein Befehl mit dem Mann zu den koordidaten X,Y gehen kann so dass sie sich in der oberen linken Ecke befinden?

Es geht eigentlich darum, dass ich einen grossen Frame habe (width=7200, height=3600) auf dem ich mich bewegem moechte, aber nicht mit einem Scrollbar sondern mit einen Mausclick. Wenn man irgendwo clickt, soll der Frame auf dieser stelle Zentriert werden (wie z.b. beim maps.google.com).


Hier ist ein teil des Codes:

Code: Alles auswählen

from Tkinter import *

root = Tk()

root.maxsize(980,700)
root.minsize(980,700)

#right_frame
right_frame = Canvas(root, background="gray50", borderwidth=5, relief=RIDGE, width=150)
right_frame.pack(side=RIGHT, fill=Y, expand=YES)  

right_frame.create_text(20, 15, text='R.A.:', fill='white')
right_frame.create_text(20, 30, text='DEC:', fill='white')

def callback(event):
    print "mousecursor at", event.x, event.y

def callback2(event):
    #########################################
    #WENN MAN AUF DEM FRAME CLICKT, SOLLTEN DIE               #
    #(event.x, event.y) KOORDIDATEN DER CENTER VON DEM     #
    #FRAME SEIN... DER FRAME MUSS ZENTRIERT WERDEN          #
    #########################################
    

# left_frame
left_frame = Canvas(root, relief=RIDGE, width=7200, height=3600, background='black') 

left_frame.bind("<Motion>", callback)
left_frame.bind("<Button-1>",callback2)
left_frame.create_text(700, 650, text='test', fill='white')

left_frame.pack(side=LEFT,fill=BOTH, expand=YES)  


root.mainloop()

Mit freundlichen Gruessen,
Aleksandar
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Zum Verständnis sollte dies genügen:

Code: Alles auswählen

from Tkinter import * 

def callback(event):
    global xoffset, yoffset
    print event.x, event.y
    x = swidth * xoffset + event.x - cwidth / 2
    y = sheight * yoffset + event.y - cheight / 2
    xoffset = min(max(x / swidth, 0.0), 1.0)
    yoffset = min(max(y / sheight, 0.0), 1.0)
    left_frame.xview(MOVETO, xoffset)
    left_frame.yview(MOVETO, yoffset)

root = Tk() 

root.maxsize(980,700) 
root.minsize(980,700) 

right_frame = Canvas(root, background="gray50", borderwidth=5, relief=RIDGE,
                     width=150) 
right_frame.pack(side=RIGHT, fill=Y, expand=YES)  
right_frame.create_text(20, 15, text='R.A.:', fill='white') 
right_frame.create_text(20, 30, text='DEC:', fill='white') 

cwidth = 800
cheight = 680
swidth = 7200
sheight = 3600
xoffset = 0.0
yoffset = 0.0
frame1 = Frame(root)
frame2 = Frame(frame1)
xscrollbar = Scrollbar(frame1, orient=HORIZONTAL)
yscrollbar = Scrollbar(frame2, orient=VERTICAL)
left_frame = Canvas(frame2, relief=RIDGE, width=cwidth, height=cheight,
                    background='black', scrollregion=(0, 0, swidth, sheight),
                    xscrollcommand=xscrollbar.set,
                    yscrollcommand=yscrollbar.set) 
xscrollbar.config(command=left_frame.xview)
yscrollbar.config(command=left_frame.yview)
left_frame.bind("<Button-1>", callback) 
left_frame.create_text(700, 650, text='test', fill='white') 

left_frame.pack(side=LEFT, fill=BOTH, expand=YES)  
yscrollbar.pack(side=RIGHT, fill=Y)
frame2.pack()
xscrollbar.pack(fill=X)
frame1.pack()

root.mainloop() 
Sinnvollerweise sollte dies natürlich in eine Klasse verpackt werden. Globale Variablen entfallen dann automatisch.

MfG
HWK
Alexci
User
Beiträge: 44
Registriert: Dienstag 18. April 2006, 23:08

WOW!

Vielen Dank! Es ist so wie ich es mir vorgestellt habe!

Gruess,
Aleksandar
Alexci
User
Beiträge: 44
Registriert: Dienstag 18. April 2006, 23:08

Nur noch ein kleines problem... event.x ist gleich event.x_root.
Warum? D.h. die linke obere Ecke hat immer koordinaten 0,0.
Wie kann man das loesen?

Danke!

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

Ich weiß nicht genau, was du meinst.
Willst du die Koordinaten relativ zum Desktop statt zum Client, dann z.B. so:

Code: Alles auswählen

x = event.x + left_frame.winfo_rootx()
y = event.y + left_frame.winfo_rooty()
Willst du die Koordinaten im gesamten Scrollbereich, dann liefern das ja bereits die Zeilen:

Code: Alles auswählen

x = swidth * xoffset + event.x
y = sheight * yoffset + event.y
Die Ergänzungen - cwidth / 2 bzw. - cheight / 2 dienen lediglich dazu, daß der angeclickte Punkt nicht in der linken, oberen Ecke, sondern in der Mitte landet.

MfG
HWK
Alexci
User
Beiträge: 44
Registriert: Dienstag 18. April 2006, 23:08

Hi,

versuchen Sie ganz unten rechts zu scrollen... auf die koordinaten (7200,3600)... wenn man dorthin klickt bekommt man die koordinaten (800,680) stadt (7200,3600).
...

Code: Alles auswählen

print event.x, event.y

Danke!

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

Du hast recht. Beim Scrollen verändern sich natürlich xoffset und yoffset. Diese müssen also aktuell abgefragt werden, z.B. so:

Code: Alles auswählen

def callback(event):
    global xoffset, yoffset
    xoffset = xscrollbar.get()[0]
    yoffset = yscrollbar.get()[0]
    x = swidth * xoffset + event.x - cwidth / 2
    y = sheight * yoffset + event.y - cheight / 2
    xoffset = min(max(x / swidth, 0.0), 1.0)
    yoffset = min(max(y / sheight, 0.0), 1.0)
    left_frame.xview(MOVETO, xoffset)
    left_frame.yview(MOVETO, yoffset)
Mfg
HWK
Alexci
User
Beiträge: 44
Registriert: Dienstag 18. April 2006, 23:08

Ja, jetzt funktioniert es. Und die aktualen koordinaten von dem Mauscursor sind dann:

Code: Alles auswählen

print xoffset*swidth+event.x, yoffset*sheight+event.y

Vielen Dank fuer ihre Hilfe.


Aleksandar
Antworten