bind und Mausklicks

Fragen zu Tkinter.
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

bind und Mausklicks

Beitragvon niko » Freitag 23. Januar 2004, 21:02

Mein Problem ist: Ich mache einen Abakus(von vielen als rechenbrett bezeichnet) und ich will, das wenn man auf eine perle(im programm als newp bezeichnet) klickt, die perle ein stückchen nach oben verschoben wird.theoretisch alles klar, jedoch praktisch wills nicht.es hakt an dem bind, das ich der bezüglichen perle zuordne.ich hoffe ihr helft mir weiter.
p.s.:das auskommentierte macht probleme.
niko

der code:

Code: Alles auswählen

from Tkinter import *
root = Tk()
root.title("Abakus")
cv = Canvas(root,height=450,width=650)
cv.pack()
perle = {}
usingIDLE = 0

r = 30
for x in range(10):
   for y in range(10):
                newp= "p"+str(x)+str(y)+" = cv.create_oval(32+"+str(x)+"*"+str(r)+"+"+str(x)+"*"+str(r)+", 32+"+str(y)+"*"+str(r)+", 32+("+str(x)+"+1)*"+str(r)+"+"+str(x)+"*"+str(r)+", 32+("+str(y)+"+1)*"+str(r)+",fill='green',outline='grey',)"
                print newp
                exec newp
                #newb="p"+str(x)+str(y)+".bind('<Button-1>',schieb("+str(x)+","+str(y)+"))"
                #print newb
                #exec newb
                cv.create_line(47+x*r+x*r, 2, 47+x*r+x*r, 332, width=3,)
      cv.create_text(47+x*r+x*r,352,text = "0")

quit = Button(root, text="Beenden", width=6, command=root.destroy)
quit.pack(side="right")

### Aktion:Kugel nach oben schieben.
def schieb(xc,yc):
   cv.coords(perle[(xc,yc)],32+xc*r+xc*r, 32+yc*r, 32+(xc+1)*r+xc*r, 32+(yc-1)*r)


root.focus_force()
if not usingIDLE:
   root.mainloop()
Es gibt diejenigen, die angeln, und diejenigen, die nur das Wasser trüben.
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

bitte

Beitragvon niko » Samstag 24. Januar 2004, 12:23

bitte bitte helft mir, das ist echt wichtig.Das Programm ist für meine Facharbeit und in einer Woche ist Abgabetermin.
:(
Ich wäre euch echt sehr dankbar.
niko
p.s.:wenn ihr aus der problembeschreibung nicht schlau werdet, dann schreibt bitte.
Benutzeravatar
oenone
User
Beiträge: 75
Registriert: Mittwoch 27. August 2003, 14:39
Wohnort: 49°17'28N, 8°15'57E
Kontaktdaten:

Re: bitte

Beitragvon oenone » Samstag 24. Januar 2004, 13:09

niko hat geschrieben:bitte bitte helft mir, das ist echt wichtig.Das Programm ist für meine Facharbeit und in einer Woche ist Abgabetermin.

tipp von mir:
fang naechstes mal frueher an und informiere dich genauer darueber was du machen willst.

aber hier zu fragen, wer deine hausaufgaben macht ist ein wenig realitaetsfern.

auf bald
oenone

ps: nimm es nicht zu persoehnlich.
if you don't remember something, it never happened.
if you aren't remembered, you never existed.
i don't quite understand what love is like... but if there was someone who liked me, i'd be happy.
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

Beitragvon niko » Samstag 24. Januar 2004, 13:39

hi oenone,
also es ist ja nicht so, dass ich nicht früh genug angefangen hab.ich hab schon im Oktober angefangen.Ich musste erst Python lernen und hab sämtiche Bücher durchgearbeitet.Der theoretische Teil der Facharbeit ist ja auch längst gemacht.
Es soll ja keiner für mich die Hausaufgaben machen, aber wenn ich einfach nicht weiterkomme und in keiner einzigen Dokumentation steht etwas darüber, was soll ich dann machen?Es soll ja keiner das Programm für mich schreiben. Es geht lediglich um ein kleines Problem, das mich aber daran hindert weiterzuprogrammieren. Ic hoffe ich habe das klargestellt.
p.s.:ich versteh deine sicht und nehme es nicht zu persönlich.
mfg
niko
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Samstag 24. Januar 2004, 13:56

Hi niko,

ich wollte gerade das script testen, aber leider kommt da gleich eine Fehlermeldung:

Code: Alles auswählen

fritz@seneca:~/Python/Beispiele$ python abakus.py
  File "abakus.py", line 33
    cv.create_text(47+x*r+x*r,352,text = "0")
                                            ^
IndentationError: unindent does not match any outer indentation level

also ich hab jetzt echt keine Lust Deine Einrückungen zu bearbeiten. Bring erstmal Deinen Code in Ordnung dann sehen wir weiter.


Gruß

Dookie

P.S.: Bei Python hat es sich eingebürgert, daß Einrückungen aus 4 Spaces bestehen. keine Tabs und eine Zeile hat nicht mehr als 79 Zeichen.
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

ok

Beitragvon niko » Samstag 24. Januar 2004, 15:18

Danke dookie, dass du dich überhaupt der sache angenommen hast.
also es ist folgendermaßen:
erst hatte ich es so, dass ich alle perlen in einem dictionary hatte.ich habe also jeder perle einen namen zugewiesen, z.B. perle(0,1) usw... Jedoch glaube ich nicht,dass ein dictionary hier richtig ist. Denn jetzt muss ich ja jedem perle(x,y) bei einem mausklick auf perle(x,y) die Funktion "schieb" zuweisen. Und genau da hängts. Also habe ich mir gedacht ich mache es folgendermaßen:

newp= "p"+str(x)+str(y)+" = cv.create_oval(32+"+str(x)+"*"+str(r)+"+"+str(x)+"*"+str(r)+", 32+"+str(y)+"*"+str(r)+", 32+("+str(x)+"+1)*"+str(r)+"+"+str(x)+"*"+str(r)+", 32+("+str(y)+"+1)*"+str(r)+")"

exec newp

das ergebnis ist das gleiche wie beim dictionary; es läuft zwar, aber es ist zum einen viel länger als 79 Zeichen und zum anderen weiß ich auch hier nicht, wie ich "schieb" anbinden soll.

also ist es wohl ein grundlegendes Problem.

ich habe alles nochmal verbessert(alle Zeilen weniger als 79 Zeichen, keine Tabs usw. und ich hoffe es läuft jetzt bei dir dookie.

das ist die dictionary-Variante, die sollte 100% laufen:

Code: Alles auswählen

from Tkinter import *
root = Tk()
root.title("Abakus")
cv = Canvas(root,height=450,width=650)
cv.pack()
perle = {}
usingIDLE = 0

r = 30   # Durchmesser der Perle
s = 32   # Nur um in Zeile 14 nicht über 79 Zeichen zu kommen
for x in range(10):
   for y in range(10):
      q = x*r  # Nur um in Zeile 14 nicht über 79 Zeichen zu kommen
      perle[(x,y)]=cv.create_oval(s+q+q,s+y*r,s+(x+1)*r+q,s+(y+1)*r)
      cv.create_line(47+x*r+x*r,2,47+x*r+x*r,332,width=3)
      cv.create_text(47+x*r+x*r,352,text = "0")
      
### Aktion:Kugel nach oben schieben.
def schieb(xc,yc):
   cv.coords(perle[(xc,yc)],32+xc*r+xc*r,32+yc*r,32+(xc+1)*r+xc*r,32+(yc-1)*r)
#perle[(x,y)].bind("<Button-1>", lambda:schieb(x,y))
quit = Button(root, text="Beenden", width=6, command=root.destroy)
quit.pack(side="right")

root.focus_force()
if not usingIDLE:
   root.mainloop()



Mfg
Niko
Es gibt diejenigen, die angeln, und diejenigen, die nur das Wasser trüben.
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Samstag 24. Januar 2004, 15:55

Hi niko,

das schaut schon besser aus.
Über die Fehlermeldung bin ich dann auch schnell auf das Problem gestossen.
[b]create_oval(..) vom Canvaswidget gibt nur eine ID(Integer) auf das Oval zurück. Dem kannst Du natürlich keine Action zuweisen. Du musst also an das Canvaswidget die action mittels Bind zuweisen und in dieser anhand der Mausposition die Perle bestimmen die verschoben werden soll.


Gruß

Dookie
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Beitragvon Voges » Samstag 24. Januar 2004, 18:24

Hallo!
Dookie hat geschrieben:Dem kannst Du natürlich keine Action zuweisen. Du musst also an das Canvaswidget die action mittels Bind zuweisen und in dieser anhand der Mausposition die Perle bestimmen die verschoben werden soll.
Ganz so aufwändig ist das nicht. Man kann mit der Canvas-Methode tag_bind() den Canvas-Items auch direkt Events zuweisen.
Jan
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

vielen dank!

Beitragvon niko » Samstag 24. Januar 2004, 18:33

Vielen Dank Dookie und Voges.
Also ich habe nach dem letzten Posting auch so ungefähr die Idee gehabt wie Dookie es vorgeschlagen hat.
Aber das was Voges sagt sollte,wenn es geht,leichter sein.

Meinst du, wenn die Perle z.B. perle(2,1) ist, dann kann ich ihr einfach mittels
perle(2,1)_bind()
das zuweisen oder wie sieht das konkret aus, wenn die Funktion für's Verschieben schieb() ist?

so etwa?

perle(2,1)_bind("<Button1>", schieb)

Auf jeden Fall vielen Dank an euch beide.
Mfg
Niko
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Samstag 24. Januar 2004, 19:16

wenn dann müsste das
canvas.tag_bind(perle(2,1),"<Button1>", schieb) heissen

Dookie
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

tja..

Beitragvon niko » Sonntag 25. Januar 2004, 17:19

also ich bin enttäuscht das sagen zu müssen, aber es geht immer noch nicht. ich hab das mit tag_bind in allen Variationen ausprobiert. doch nichts zu machen. ich werde wohl doch die kompliziertere lösung machen müssen. oder weiß jemand weiter?
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Re: tja..

Beitragvon Voges » Sonntag 25. Januar 2004, 17:41

Hallo!
niko hat geschrieben:also ich bin enttäuscht das sagen zu müssen, aber es geht immer noch nicht.
Was geht nicht? Konkrete Infos brauchen wir schon. Egal, das Folgende sollte in etwa das tun, was Du wohl wolltest:

Code: Alles auswählen

from Tkinter import *
root = Tk()
root.title("Abakus")
cv = Canvas(root,height=450,width=650)
cv.pack()
perle = {}
usingIDLE = 0

### Aktion:Kugel nach oben schieben.
def schieb(xc,yc):
   cv.coords(perle[(xc,yc)],32+xc*r+xc*r,32+yc*r,32+(xc+1)*r+xc*r,32+(yc-1)*r)

r = 30   # Durchmesser der Perle
s = 32   # Nur um in Zeile 14 nicht über 79 Zeichen zu kommen
for x in range(10):
    for y in range(10):
        q = x*r  # Nur um in Zeile 14 nicht über 79 Zeichen zu kommen
        perle[(x,y)]=cv.create_oval(s+q+q,s+y*r,s+(x+1)*r+q,s+(y+1)*r,fill='green',outline='grey',)
        cv.tag_bind(perle[(x,y)],"<Button-1>", lambda e,X=x,Y=y:schieb(X,Y))
           
quit = Button(root, text="Beenden", width=6, command=root.destroy)
quit.pack(side="right")

root.focus_force()
if not usingIDLE:
   root.mainloop()

hth
Jan

BTW: Zumindest für mich gilt: Je weniger ein Beitrag sich an den Regeln der dt. Schriftsprache orientiert, desto weniger bin ich zur Hilfe bereit.
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

nicht schlecht

Beitragvon niko » Sonntag 25. Januar 2004, 18:06

Danke Voges!!
Die Perlen lassen sich verschieben.Dafür vielen dank. Jedoch lassen sie sich nur einmal verschieben. entweder liegt das an der Funktion schieb selbst oder daran, dass er die Koordinaten nicht richtig speichert. Außerdem bewegt sich die Perle beim Klick auf das Stäbchen auch nicht. Kann man die Stäbchen irgendwie in den Hintergrund verbannen?

Mfg
Niko
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Re: nicht schlecht

Beitragvon Voges » Sonntag 25. Januar 2004, 18:31

Hallo!
niko hat geschrieben:Jedoch lassen sie sich nur einmal verschieben.
Wenn Du z.B. die Perle perle[(2,5)] anklickst, verschiebst Du sie ja relativ zu 5*r nach oben, und zwar um 32 Pixel. Aber die Perle heißt dann immer noch perle[(2,5)], obwohl sie sich ja jetzt auf der Position (2,4) befindet. Wenn Du jetzt nochmal auf die selbe Perle klickst, rechnest Du wieder 5*r + 32, aber da ist sie ja schon und tritt somit auf der Stelle.

Ich hätte das ganze nicht als 10 x 10 Perlen realisiert, sondern als 11 x 10 mögliche Perlenplätze, wovon die unteren 10 Zeilen am Anfang gefüllt sind und die obere eben leer. Beim Klick auf einen Perlenplatz müsste man dann nur gucken, ob da eine Perle ist und ob dadrüber keine ist. Dann kann man "verschieben".
niko hat geschrieben:Außerdem bewegt sich die Perle beim Klick auf das Stäbchen auch nicht. Kann man die Stäbchen irgendwie in den Hintergrund verbannen?
Die Stangen zuerst zeichnen, damit sie von den Perlen verdeckt werden. Entspricht ja auch der 'Natur'.
Jan
Benutzeravatar
wuf
User
Beiträge: 1366
Registriert: Sonntag 8. Juni 2003, 09:50

Beitragvon wuf » Sonntag 25. Januar 2004, 22:39

Hallo Niko

Hier eine mögliche Lösung für dein Abakus!
Diese muss sicher noch optimiert werden, aber
die Animationsmechanik lässt sich einbauen.

Linke Maustaste = Aufwärts
Rechte Maustaste = Abwärts

Slogan:
"TKINTER and PYTHON ist just a FANTASTIC combination!!"

Code: Alles auswählen

from Tkinter import *

def MoveUp(perle):
   #~~ Schiebt Objekt nach oben
   cv.move(perle,0,-32)

def MoveDown(perle):
   #~~ Schiebt Objekt nach unten
   cv.move(perle,0,+32)

#  ->>----THE-ABAKUS----<<-
if __name__ == '__main__':

   root = Tk()
   root.title("Abakus")
   cv = Canvas(root,height=450,width=85,bd=6,relief=RAISED,bg='khaki2')
   cv.pack()

   usingIDLE = 0

   r = 30   # Durchmesser der Perle
   s = 32   # Nur um in Zeile 14 nicht über 79 Zeichen zu kommen
   breite = 4
   xpos = s+r/2+breite/2-1
   stange = cv.create_line(xpos,8,xpos,380,fill='darkolivegreen4',width=breite)

   for x in range(1):
      for y in range(10):
         q = x*r

         x0 = s+q+q
         y0 = s+y*r
         x1 = s+(x+1)*r+q
         y1 = s+(y+1)*r

         object = cv.create_oval(x0,y0,x1,y1,fill='green',outline='red')
         cv.tag_bind(object,"<Button-1>",lambda e,Object=object:MoveUp(Object))
         cv.tag_bind(object,"<Button-3>",lambda e,Object=object:MoveDown(Object))

   quit = Button(root, text="Beenden", width=6, command=root.destroy)
   quit.pack(side="right")

   if not usingIDLE:
        root.mainloop()


All the best wuf
Take it easy Mates!

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder