bind und Mausklicks

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

Hallo!
Ich hab auch noch mal rumgespielt. Ich muss sagen, die Idee, das Ganze mit einem Dictionary zu managen, gefällt mir immer besser. Ich denke einfach immer noch zuviel in Arrays.

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
ax = 40   # Perlen-Offset in x-Richtung
ay = 35   # Perlen-Offset in y-Richtung
originx = 10 # Ursprung ...
originy = 50 # ... des Ganzen


### Aktion:Kugel nach oben schieben.
def schieb(xc,yc):
    ycNeu = yc-1   # einen hochrücken
    if ycNeu == -2 or perle.has_key((xc,ycNeu)):  # wenn wir schon ganz oben waren oder dort eine Perle ist ...
        ycNeu = yc+1 # einen runterrücken
        if ycNeu == 10 or perle.has_key((xc,ycNeu)): # wenn wir schon ganz unten waren oder da auch schon eine Perle ist, ...
            return  # ... dann gibt es nichts zu tun
    xx = originx + xc*ax;  yy = originy + ycNeu*ay
    cv.coords(perle[(xc,yc)],xx,yy,xx+r,yy+r)
    perle[(xc,ycNeu)] = perle[(xc,yc)] # Die Perle bekommt einen neuen Dict-Eintrag entspr. der neuen Position
    cv.tag_bind(perle[(xc,ycNeu)],"<Button-1>", lambda e,X=xc,Y=ycNeu:schieb(X,Y))  # nötig, da sich ja y verändert hat
    del perle[(xc,yc)] # alten Dict-Eintrag löschen


for x in range(10):
    for y in range(10):
        xx = originx + x*ax;  yy = originy + y*ay
        perle[(x,y)]=cv.create_oval(xx,yy,xx+r,yy+r,fill='green',outline='black',)
        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()
Sicherlich noch optimierbar. Irgendwie werde ich das Gefühl nicht los, dass da was redundant ist.
Jan
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

Voges wirklich vielen Dank.Sehr interessante Ideen!
Ich habe jetzt fast den ganzen Abend hin und herprogrammiert. So siehts aus.Die Perlen bewegen sich halbwegs so wie ich es will.

zuerstmal wird unterschieden ob die perle die 9te oder sonst eine aus der jeweiligen Reihe ist(der fall es sei die erste mach ich morgen). Danach werden, abhängig davon ob sie in der Liste "verschoben" drin ist oder nicht, die betroffenen Perlen verschoben.

irgendwie will

del verschoben[(xc,yc)] (In der Zeile 16)

nicht so ganz gehen. Es kommt die Fehlermeldung "sequence index must be integer".

gute nacht
Niko

p.s.:im folgenden der neueste 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 
verschoben = []
 
def schieb(xc,yc):
    print perle[(xc,yc)]
    print verschoben
    if yc == 9:
        if perle[(xc,yc)] in verschoben:
            cv.coords(perle[(xc,yc)],s+xc*r+xc*r,s+yc*r,s+(xc+1)*r+xc*r,s+(yc+1)*r)
            del verschoben[(xc,yc)] ### Löschen aus verschoben
        elif perle[(xc,yc)] not in verschoben:
            for o in range(yc+1):
                print verschoben
                verschoben.append(perle[(xc,o)]) ### Der WERT vom Schlüssel
                cv.coords(perle[(xc,o)],s+xc*r+xc*r,s+o*r,s+(xc+1)*r+xc*r,s+(o-1)*r)
    else:
        if perle[(xc,yc+1)] not in verschoben:
            #print xc,yc+1,"nicht in verschoben vorhanden"
            for t in range(yc+1):
                #print xc,t
                verschoben.append(perle[(xc,t)]) ### Der WERT vom Schlüssel
                cv.coords(perle[(xc,t)],s+xc*r+xc*r,s+t*r,s+(xc+1)*r+xc*r,s+(t-1)*r)
        elif perle[(xc,yc-1)] in verschoben:
            for z in range(yc,10):
                cv.coords(perle[(xc,z)],s+xc*r+xc*r,s+z*r,s+(xc+1)*r+xc*r,s+(z+1)*r)
                del verschoben[(xc,z)]

r = 30   # Durchmesser der Perle 
s = 32   # Nur um in Zeile 14 nicht über 79 Zeichen zu kommen 
for x in range(10): 
    cv.create_line(47+x*r+x*r,2,47+x*r+x*r,332,width=1)
for x in range(10): 
    for y in range(10):
        q = x*r  # Nur um in Zeile 43 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')
        #perle[(x,y)] = [str(x*10+y)]
        cv.tag_bind(perle[(x,y)],"<Button-1>", lambda e,X=x,Y=y:schieb(X,Y))
        cv.create_text(47+x*r+x*r,352,text = "0")
print perle
quit = Button(root, text="Beenden", width=6, command=root.destroy) 
quit.pack(side="right") 

root.focus_force() 
if not usingIDLE: 
   root.mainloop()
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Niko

Ich habe dir auf der ersten Seite (letzter Eintrag)
noch ein bischen Code zu diesem Thema beigelegt.

Gruss wuf
Take it easy Mates!
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

wuf vielen dank!
hab das irgendwie noch übersehen.aber auch keine schlechte Idee.Naja aber nun is spät und Schlaf is Mangelware.In dem Sinne gute Nacht.
Niko
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi niko,

verschoben ist ja auch eine liste, nimm statt del verschoben[(xc,yc)] einfach verschoben.remove(perle[(xc,yc)])


Gruß

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

Hallo Niko

Habe meinen Vorschlag für deinen Abakus
noch ein bisschen erweitert

Linke Maustaste = Schieb rechts
Rechte Maustaste = Schiebe links

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

Code: Alles auswählen

from Tkinter import *

def MoveRight(perle):
	#~~ Schiebt Objekt nach rechts
	print "pos = ", cv.bbox(perle),perle
	pos = cv.bbox(perle)
	#~~ Kontrolle ob eine Perle im Weg ist oder rechtes Rahmenende
	enclosed = cv.find_enclosed(pos[0]+r,pos[1],pos[2]+r,pos[3])
	if enclosed == ():
		if pos[0] < numcol*s:
			cv.move(perle,+s,0)
			cv.itemconfigure(perle,fill="darkolivegreen3")

def MoveLeft(perle):
	#~~ Schiebt Objekt nach links
	pos = cv.bbox(perle)
	#~~ Kontrolle ob eine Perle im Weg ist oder linkes Rahmenende
	enclosed = cv.find_enclosed(pos[0]-r,pos[1],pos[2]-r,pos[3])
	if enclosed == ():
		if pos[0] > s:
			cv.move(perle,-s,0)
			cv.itemconfigure(perle,fill="green")

#  ->>----THE-ABACUS-APPLICATION----<<-
if __name__ == '__main__':

	root = Tk()
	root.title("Abakus-Prototyp")
	root['bg'] = 'steelblue3'
	cv = Canvas(root,height=450,width=250,bd=4,relief=RAISED,bg='khaki2')
	cv.pack()

	usingIDLE = 0

	r       = 30   # Durchmesser der Perle
	s       = r+2  # Linker Anschlag für Perlen
	gap     = 6    # Vertikaler Zwischenraum
	numcol  = 5    # Anzahl Perlen pro Perlenreihe
	numrows = 9    # Anzahl der Perlenreihen

	dicke   = 4    # Dicke der Reihenstange
	top     = r    # Oberes Rahmenende
	left    = s    # Linkes Rahmenende
	right   = left+(numcol+1)*r+8  #Rahmenende rechts
	bottom  = top+(numrows*r)+(numrows*gap) # Rahmenende unten
	ypos    = 0    # Vertikalposition der Reihenstange
	yg      = 0    # Hilfsvariable

	#~~ Erzeugt Stangen
	for rod in range(numrows):
		ypos = s+(r/2+1)+yg+rod*r
		stange = cv.create_line(left,
								ypos,
								right,
								ypos,
								fill='darkolivegreen4',
								width=dicke)
		yg += gap

	#~~ Erzeugt Abakusrahmen
	rectangle = cv.create_rectangle(left-2,
									top-4,
									right,bottom+4,
									width= 8,
									outline='darkgoldenrod4'
									)

	#~~ Erzeugt die Perlen
	for x in range(numcol):
		yg = 0
		for y in range(numrows):
			x0 = s+x*r
			y0 = s+yg+y*r
			x1 = s+(x+1)*r
			y1 = s+yg+(y+1)*r
			yg += gap
			# Zeichne Perle
			object = cv.create_oval(x0,y0,x1,y1,fill='green',outline='darkgreen')
			# Event für die Rechtschiebung
			cv.tag_bind(object,"<Button-1>",lambda e,Object=object:MoveRight(Object))
			# Event für die Linksschiebung
			cv.tag_bind(object,"<Button-3>",lambda e,Object=object:MoveLeft(Object))

	quit = Button(root, text="Beenden", width=10, command=root.destroy)
	quit.pack(side="bottom",pady=4)

	if not usingIDLE:
  		root.mainloop()
Gruss wuf :wink:
Take it easy Mates!
NOTZE
User
Beiträge: 106
Registriert: Mittwoch 21. Januar 2004, 20:28

@ wuf
is echt gut geworden der Abskus und er funktiniert ziemlich gut.
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

wuf wirklich nicht schlecht.vielen dank.
jedoch will ich das so realisieren, dass, z.b. wenn man auf ne perle in der mitte klickt es auch geht und sich alle über bzw. unter ihr,entsprechend ihrer position, nach oben oder unten mitbewegen.

mein code zur zeit(ich weiß,noch einige überarbeitungen nötig,aber es wird schon):

Code: Alles auswählen

from Tkinter import * 
root = Tk() 
root.title("Abakus") 
cv = Canvas(root,height=450,width=650) 
cv.pack() 
perle = {} 
usingIDLE = 0 
verschoben = []
 
def schieb(xc,yc):
    print perle[(xc,yc)]
    print verschoben
    if yc == 9:
        if perle[(xc,yc)] in verschoben:
            cv.coords(perle[(xc,yc)],s+xc*r+xc*r,s+yc*r,s+(xc+1)*r+xc*r,s+(yc+1)*r)
            verschoben.remove(perle[(xc,yc)]) 
            print verschoben
        elif perle[(xc,yc)] not in verschoben:
            for o in range(yc+1):
                print verschoben
                if perle[(xc,o)] not in verschoben:
                    verschoben.append(perle[(xc,o)]) ### Der WERT vom Schlüssel
                cv.coords(perle[(xc,o)],s+xc*r+xc*r,s+o*r,s+(xc+1)*r+xc*r,s+(o-1)*r)
                print verschoben
    elif yc == 1:
        if perle[(xc,yc)] in verschoben:
            for u in range(yc,10):
                cv.coords(perle[(xc,u)],s+xc*r+xc*r,s+u*r,s+(xc+1)*r+xc*r,s+(u-1)*r)
                verschoben.remove(perle[(xc,yc)])
                print verschoben
        elif perle[(xc,yc)] not in verschoben:
            verschoben.append(perle[(xc,yc)]) ### Der WERT vom Schlüssel
            cv.coords(perle[(xc,yc)],s+xc*r+xc*r,s+yc*r,s+(xc+1)*r+xc*r,s+(yc+1)*r)
    elif yc <> 9:
        if perle[(xc,yc+1)] not in verschoben:
            #print xc,yc+1,"nicht in verschoben vorhanden"
            for t in range(yc+1):
                if perle[(xc,t)] not in verschoben:
                    verschoben.append(perle[(xc,t)]) ### Der WERT vom Schlüssel
                cv.coords(perle[(xc,t)],s+xc*r+xc*r,s+t*r,s+(xc+1)*r+xc*r,s+(t-1)*r)
                print verschoben
        elif perle[(xc,yc-1)] in verschoben:
            for z in range(yc,10):
                cv.coords(perle[(xc,z)],s+xc*r+xc*r,s+z*r,s+(xc+1)*r+xc*r,s+(z+1)*r)
                verschoben.remove(perle[(xc,z)])
                print verschoben

r = 30   # Durchmesser der Perle 
s = 32   # Nur um in Zeile 14 nicht über 79 Zeichen zu kommen 
for x in range(10): 
    cv.create_line(47+x*r+x*r,2,47+x*r+x*r,332,width=1)
for x in range(10): 
    for y in range(10):
        q = x*r  # Nur um in Zeile 43 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')
        #perle[(x,y)] = [str(x*10+y)]
        cv.tag_bind(perle[(x,y)],"<Button-1>", lambda e,X=x,Y=y:schieb(X,Y))
        cv.create_text(47+x*r+x*r,352,text = "0")
print perle
quit = Button(root, text="Beenden", width=6, command=root.destroy) 
quit.pack(side="right") 

root.focus_force() 
if not usingIDLE: 
   root.mainloop()
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

noch was:
was haltet ihr von der zeile 56(noch auskommentiert):

perle[(x,y)] = [str(x*10+y)]

Hier versuche ich dem jeweiligen schlüssel den wert str(x*10+y) zuzuweisen.Das würde, wenns klappt, einiges leichter machen.

Während ich das geschrieben hab,hab ich das nochmal ausprobiert:

jedoch die zeile perle[(x,y)] = [str(x*10+y)] unter die darauffolgende zeile mit cv.tag_bind(.......)... verschoben.außerdem habe ich aus
perle[(x,y)] = [str(x*10+y)] folgendes gemacht:
perle[(x,y)] = [x*10+y]
das sollte praktischer sein.
konkret sieht das so aus(Zeile 56/57):

Code: Alles auswählen

cv.tag_bind(perle[(x,y)],"<Button-1>", lambda e,X=x,Y=y:schieb(X,Y))
perle[(x,y)] = [x*10+y]
Nun stimmen natürlich die ganzen verschiebungsunterscheidungen nicht mehr.Das versuch ich jetz zu korrigieren.
Mfg
Niko
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Niko wie läufts?

Habe mein Script auf dein Abakus-Anforderungs-
profil angepasst. Es brauchte ein paar kleinere
Modifikationen in den Schiebemethoden.

Linke Maustaste = Schieb rechts
Rechte Maustaste = Schiebe links

TKINTER & PYTHON is still the BEST!

Code: Alles auswählen

from Tkinter import *

def MoveRight(perle):
	#~~ Schiebt Objekte nach rechts

	#~~ Hilfsliste deklarieren
	auxlist = []
	pos = cv.bbox(perle)

	#~~ Objektnummern der Perlen auf der rechten Seite
	#   der angeklickten Perle inklusive der angeklickten.
	auxlist = list(cv.find_enclosed(pos[0],pos[1],right,pos[3]))
	auxlist.reverse()

	for obj in auxlist:
		pos = cv.bbox(obj)
		enclosed = cv.find_enclosed(pos[0]+r,pos[1],pos[2]+r,pos[3])
		if enclosed == ():
			if pos[0] < numcol*s:
				cv.move(obj,+s,0)
				cv.itemconfigure(obj,fill="darkolivegreen3")
	return()

def MoveLeft(perle):
	#~~ Schiebt Objekte nach links

	#~~ Hilfsliste deklarieren
	auxlist = []
	pos = cv.bbox(perle)

	#~~ Objektnummern der Perlen auf der linken Seite
	#   der angeklickten Perle inklusive der angeklickten.
	auxlist = list(cv.find_enclosed(left-1,pos[1],pos[2],pos[3]))

	for obj in auxlist:
		pos = cv.bbox(obj)
		enclosed = cv.find_enclosed(pos[0]-r,pos[1],pos[2]-r,pos[3])
		if enclosed == ():
			if pos[0] > s:
				cv.move(obj,-s,0)
				cv.itemconfigure(obj,fill="green")
	return()

#  ->>----THE-ABACUS-APPLICATION----<<-
if __name__ == '__main__':

	root = Tk()
	root.title("Abakus-Prototyp-26.01.04 22:30")
	root['bg'] = 'steelblue3'
	cv = Canvas(root,height=450,width=250,bd=4,relief=RAISED,bg='khaki2')
	cv.pack()

	usingIDLE = 0

	r       = 30   # Durchmesser der Perle
	s       = r+2  # Linker Anschlag für Perlen
	gap     = 6    # Vertikaler Zwischenraum
	numcol  = 5    # Anzahl Perlen pro Perlenreihe
	numrows = 9    # Anzahl der Perlenreihen

	dicke   = 4    # Dicke der Reihenstange
	top     = r    # Oberes Rahmenende
	left    = s    # Linkes Rahmenende
	right   = left+(numcol+1)*r+8  #Rahmenende rechts
	bottom  = top+(numrows*r)+(numrows*gap) # Rahmenende unten
	ypos    = 0    # Vertikalposition der Reihenstange
	yg      = 0    # Hilfsvariable

	#~~ Erzeugt Stangen
	for rod in range(numrows):
		ypos = s+(r/2+1)+yg+rod*r
		stange = cv.create_line(left,
								ypos,
								right+2,
								ypos,
								fill='darkolivegreen4',
								width=dicke)
		yg += gap

	#~~ Erzeugt Abakusrahmen
	rectangle = cv.create_rectangle(left-2,
									top-4,
									right,bottom+4,
									width= 8,
									outline='darkgoldenrod4'
									)

	#~~ Erzeugt die Perlen
	for x in range(numcol):
		yg = 0
		for y in range(numrows):
			x0 = s+x*r
			y0 = s+yg+y*r
			x1 = s+(x+1)*r
			y1 = s+yg+(y+1)*r
			yg += gap
			# Zeichne Perle
			object = cv.create_oval(x0,y0,x1,y1,fill='green',outline='darkgreen')
			# Event für die Rechtschiebung
			cv.tag_bind(object,"<Button-1>",lambda e,Object=object:MoveRight(Object))
			# Event für die Linksschiebung
			cv.tag_bind(object,"<Button-3>",lambda e,Object=object:MoveLeft(Object))

	quit = Button(root, text="Beenden", width=10, command=root.destroy)
	quit.pack(side="bottom",pady=4)

	if not usingIDLE:
  		root.mainloop()
Gruss wuf :wink:
Take it easy Mates!
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

also ich werd verrückt. erst jetzt merk ich,dass usingIDLE die ganze zeit auf 0 steht und ich hab die IDLE laufen.schlagartig haben sich in paar problemchen gelöst. ich wage mich fast zu sagen, dass viele Aktionen im Sinne von Perlen verschieben gehen.Natürlich noch nicht alle und langsam werd ich verrückt,weil ich effektiv gesehen die ganze Zeit nur auf einem fleck rumtrample.
naja die aktuellste version:

Code: Alles auswählen

from Tkinter import * 
root = Tk() 
root.title("Abakus") 
cv = Canvas(root,height=450,width=650) 
cv.pack() 
perle = {} 
usingIDLE = 1 
verschoben = []
 
def schieb(xc,yc):
    print perle[(xc,yc)]
    print verschoben
    if yc == 9:
        if perle[(xc,yc)] in verschoben:
            cv.coords(perle[(xc,yc)],s+xc*r+xc*r,s+yc*r,s+(xc+1)*r+xc*r,s+(yc+1)*r)
            verschoben.remove(perle[(xc,yc)]) 
            print verschoben
        elif perle[(xc,yc)] not in verschoben:
            for o in range(yc+1):
                print verschoben
                if perle[(xc,o)] not in verschoben:
                    verschoben.append(perle[(xc,o)]) ### Der WERT vom Schlüssel
                cv.coords(perle[(xc,o)],s+xc*r+xc*r,s+o*r,s+(xc+1)*r+xc*r,s+(o-1)*r)
                print verschoben
    elif yc == 1:
        if perle[(xc,yc)] in verschoben:
            for u in range(yc,10):
                cv.coords(perle[(xc,u)],s+xc*r+xc*r,s+u*r,s+(xc+1)*r+xc*r,s+(u-1)*r)
                verschoben.remove(perle[(xc,yc+1)])
                print verschoben
        elif perle[(xc,yc)] not in verschoben:
            verschoben.append(perle[(xc,yc)]) ### Der WERT vom Schlüssel
            cv.coords(perle[(xc,yc)],s+xc*r+xc*r,s+yc*r,s+(xc+1)*r+xc*r,s+(yc+1)*r)
    elif yc <> 9:
        if perle[(xc,yc+1)] not in verschoben:
            #print xc,yc+1,"nicht in verschoben vorhanden"
            for t in range(yc+1):
                if perle[(xc,t)] not in verschoben:
                    verschoben.append(perle[(xc,t)]) ### Der WERT vom Schlüssel
                cv.coords(perle[(xc,t)],s+xc*r+xc*r,s+t*r,s+(xc+1)*r+xc*r,s+(t-1)*r)
                print verschoben
        elif perle[(xc,yc-1)] in verschoben:
            for z in range(yc,10):
                cv.coords(perle[(xc,z)],s+xc*r+xc*r,s+z*r,s+(xc+1)*r+xc*r,s+(z+1)*r)
                verschoben.remove(perle[(xc,z)])
                print verschoben

r = 30   # Durchmesser der Perle 
s = 32   # Nur um in Zeile 14 nicht über 79 Zeichen zu kommen 
for x in range(10): 
    cv.create_line(47+x*r+x*r,2,47+x*r+x*r,332,width=1)
for x in range(10): 
    for y in range(10):
        q = x*r  # Nur um in Zeile 43 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')
        #perle[(x,y)] = [x*10+y]
        cv.tag_bind(perle[(x,y)],"<Button-1>", lambda e,X=x,Y=y:schieb(X,Y))
        cv.create_text(47+x*r+x*r,352,text = "0")
print perle
quit = Button(root, text="Beenden", width=6, command=root.destroy) 
quit.pack(side="right") 

root.focus_force() 
if not usingIDLE: 
   root.mainloop()
Mfg
Niko
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

wuf also wirklich respekt.wie machst du das nur?
was hälst du eigentlich von dem was ich da die ganze zeit "programmiere"?langsam gebe ich vollends die hoffnung auf.
Mfg
Niko
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Niko

Erfüllt mein Script deine Anforderungen? Ich
bin nicht sicher ob das Programm eine andere
Perlenanzahl problemlos schnallt. Es muss evt.
noch optimiert werden.

Das Programmieren habe ich auf die gleiche
Art erarbeitet wie du es machst. Oberstes
Gebot ist gebe nie auf! Manchmal braucht es
eine Pause. Ein Bierchen oder ein Spaziergang
und ein neuer Lösungsansatz lässt den Motor
wieder hochfahren

Alles Gute wuf! :wink:
Take it easy Mates!
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

Hi wuf!
Also das Skript ist in dem Sinne wirklich gut. Das problem ist, dass noch n paar Sachen gehen müssen. So z.b., dass wenn alle perlen einer reihe verschoben sind, der Text "Bereinigen!" erscheint. Zudem soll bei jeder Reihe die Anzahl der verschobenen Perlen stehen.d.h wenn in einer Reihe 5 Perlen von 10 verschoben, soll eine 5 neben der Reihe stehen usw.
Ich sehe in all dem nur eine Lösung, wenn ich ne extraListe verschoben benutze, wo alle verschobenen perlen reinkommen.
n paar fragen:
dass bbox die ungefähren koordinaten bstimmt hab ich kapiert, aber was machen cv.find_enclosed und cv.itemconfigure?
jetz weiß ich nicht wo ich weitermachen soll.ob ich elemente von dir übernehme und dass in mein script einstreue oder mein script wegwerfe.
was denkst du?
also ich glaub das wird heut ne lange nacht.
mfg
niko
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Niko

Besten Dank für deine Antwort!

1. Wo auf der Canvas möchtest du den Text "Bereinigen" an-
gezeigt haben?

2. Die canvas.bbox(Canvas-Objekt-Nr.) Methode gibt dir die genauen Koordinatenpunkte x1,y1,x2,y2
(Eckpunkte des Canvas-Objektes) als Integer (in Pixels) für ein Perle (Canvas-Objekt Oval) zurück.
Die Canvas-Objekt-Nr ist nicht ein hochkomplexe Nummer wie bei Referenzen auf ein übliches Objekt,
sondern eine fortlaufende Integer Nummer, in der Reihenfolge wie die Canvas-Objekte auf der Canvas-
fläche abgelegt wurden.

3. Wenn dir die Integernummer des Canvas-Objektes bekannt ist kannst du mit canvas.itemconfiger(Canvas-
Objekt-Nr.,option) die Eigenschaft des betreffeden Canvas-Objekts verändern. In unserem Falle ist es
die option "fill", welches die Füllfarbe der Perle ist.

4. Mit der Methode canvas.find_enclosed(x1,y1,x2,y2) kannst du herausfinden, welche Canvas-Objekte also
in unserem Falle sind es Perlen sich im Rechteck x1,y1,x2,y2 befinden. Es werden die Integer-Nummern
der Canvas-Objekte in einem Tuple zurückgegeben. Da sich ein Tuple nicht verändern lässt, transferier
ich das Tuple mit der Anweisung list(Tuple) in eine Liste (auxlist im Script). Manipulieren muss ich
den Inhalt dieser Hilfsliste in einem Fall mit der Listenmethode liste.reverse(). Das ist bei der Ver-
schiebung der Perlen nach rechts nötig.

OK das wäre einmal mein erste Antwortpacket

Gruss wuf
Take it easy Mates!
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

Hallo wuf,
also zuerst mal danke, dass du dir solche mühe gibst.
1.wenns geht neben den reihen, da wo die anzahl der verschobenen perlen steht.
etwa so(anzahl der verschobenen perlen):

Code: Alles auswählen

#~~ Erzeugt Stangen 
for rod in range(numrows): 
  ypos = s+(r/2+1)+yg+rod*r 
  stange = cv.create_line(left, 
                    ypos, 
                    right+2, 
                    ypos, 
                    fill='darkolivegreen4', 
                    width=dicke) 
  yg += gap
  cv.create_text(right+2+8,ypos - dicke/2,text = "0")
Bereinigen einfach neben die betreffende Zeile.
2.verstanden
3.verstanden

nunja also ich hab mir überlegt, dass die Länge (also len) von auxlist jeweils den verschobenen perlen entspricht.jetzt ist nur die frage wie man das konkret umsetzt.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Niko

Ich schaute in der Zwischenzeit leider nicht mehr ins
Forum, da ich mit einer Brain storm Phase konfrontiert
war. Ich habe die Abakus-Skript auf deine wünsche an-
gepasst. Niko ich werde deine Fragen später beantworten.

Überigens danke dem Form für das PowerUser-Certificate!

Das Skript ist nicht optimiert. Anregungen von Forumbe-
nutzern für die Verbesserung oder Verfeinerung des Skripts
sind herzlich willkommen.

Code: Alles auswählen

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

# Anwendung   : The Abacus
# Version     : 1.00
# Autor       : Fritz Wüst (CH-6048 Horw)
# Datum       : 27.01.2004 - 03:00
# Geändert    : 27.01.2004 - 03:00

from Tkinter import *


def MoveRight(perle):
	#~~ Schiebt Objekte nach rechts

	#~~ Hilfsliste deklarieren
	auxlist = []
	pos = cv.bbox(perle)

	#~~ Objektnummern der Perlen auf der rechten Seite
	#   der angeklickten Perle inklusive der angeklickten.
	auxlist = list(cv.find_enclosed(pos[0],pos[1],right,pos[3]))
	auxlist.reverse()

	for obj in auxlist:
		pos = cv.bbox(obj)
		enclosed = cv.find_enclosed(pos[0]+r,pos[1],pos[2]+r,pos[3])
		if enclosed == ():
			if pos[0] < numcol*s:
				cv.move(obj,+s,0)
				cv.itemconfigure(obj,fill="darkolivegreen3")

	UpdateNumOfPearls()

	return()

def MoveLeft(perle):
	#~~ Schiebt Objekte nach links

	#~~ Hilfsliste deklarieren
	auxlist = []
	pos = cv.bbox(perle)

	#~~ Objektnummern der Perlen auf der linken Seite
	#   der angeklickten Perle inklusive der angeklickten.
	auxlist = list(cv.find_enclosed(left-1,pos[1],pos[2],pos[3]))

	for obj in auxlist:
		pos = cv.bbox(obj)
		enclosed = cv.find_enclosed(pos[0]-r,pos[1],pos[2]-r,pos[3])
		if enclosed == ():
			if pos[0] > s:
				cv.move(obj,-s,0)
				cv.itemconfigure(obj,fill="green")

	UpdateNumOfPearls()

	return()

def UpdateNumOfPearls():
	#~~ Aktualisiert Texte auf der Canvasfläche
	global cleanmessage
	yg = 0
	cleaning = FALSE
	for row in range(numrows):
		y0 = s+yg+row*r
		y1 = s+yg+(row+1)*r
		foundobj = cv.find_enclosed(left-1,y0-1,right,y1+1)
		numpearls = 0
		numcolor  = 'blue'
		for obj in foundobj:
			fillcolor = cv.itemcget(obj,'fill')
			if fillcolor == 'darkolivegreen3':
				numpearls += 1
		if numpearls == numcol:
			cleaning = TRUE
			numcolor = 'red'
	 	xpos = right+15
	 	ypos = top+1+yg+r/2+row*r
	 	try:
	 		cv.delete(numlist[row])
	 	except:
	 		pass
		numlist[row] = cv.create_text(xpos,ypos,text=numpearls,anchor='w',fill=numcolor,font=font1)
		yg += gap
	try:
		cv.delete(cleanmessage)
	except:
		pass
	if cleaning == TRUE:
		xpos = (top+right)/2
		ypos = bottom+30
		text = cleantext
		cleanmessage = cv.create_text(xpos,ypos,text=text,anchor='center',fill='red',font=font2)

	return()

#  ->>----THE-ABACUS-APPLICATION----<<-
if __name__ == '__main__':

	root = Tk()
	root.title("Abakus-Prototyp-27.01.04 - 03:00")
	root['bg'] = 'steelblue3'
	cv = Canvas(root,height=430,width=450,bd=4,relief=RAISED,bg='khaki2')
	cv.pack()

	usingIDLE = 0

	#~~ Listendeklaration für die Anzahl verschobener Perlen
	numlist = []

	#~~ Zeichensätze
	font1 = ('Helvetica', 15, 'bold')
	font2 = ('Helvetica', 20, 'bold','underline')
	cleantext = 'Bitte Bereinigen!!!'

	r       = 30   # Durchmesser der Perle
	s       = r+2  # Linker Anschlag für Perlen
	gap     = 6    # Vertikaler Zwischenraum
	numcol  = 10    # Anzahl Perlen pro Perlenreihe
	numrows = 9    # Anzahl der Perlenreihen

	dicke   = 4    # Dicke der Reihenstange
	top     = r    # Oberes Rahmenende
	left    = s    # Linkes Rahmenende
	right   = left+(numcol+1)*r+8  #Rahmenende rechts
	bottom  = top+(numrows*r)+(numrows*gap) # Rahmenende unten
	ypos    = 0    # Vertikalposition der Reihenstange
	yg      = 0    # Hilfsvariable

	#~~ Erzeugt Stangen
	for rod in range(numrows):
		ypos = s+(r/2+1)+yg+rod*r
		stange = cv.create_line(left,
								ypos,
								right+2,
								ypos,
								fill='darkolivegreen4',
								width=dicke)
		yg += gap

	#~~ Erzeug Textobjekte für die Anzahl verschobener Perlen
	yg = 0
	for num in range(numrows):
		xpos    = right+15
		ypos    = top+1+yg+r/2+num*r
		textobj = cv.create_text(xpos,ypos,text=0,anchor='w',fill='blue',font=font1)
		numlist.append(textobj)
		yg += gap

	#~~ Erzeugt Meldetext-Objekt für "Bereinigen"
	xpos = (top+right)/2
	ypos = bottom+30
	text = ''
	cleanmessage = cv.create_text(xpos,ypos,text=text,anchor='center',fill='red',font=font2)

	#~~ Erzeugt Abakusrahmen
	rectangle = cv.create_rectangle(left-2,
									top-4,
									right,bottom+4,
									width= 8,
									outline='darkgoldenrod4'
									)

	#~~ Erzeugt die Perlen
	for x in range(numcol):
		yg = 0
		for y in range(numrows):
			x0 = s+x*r
			y0 = s+yg+y*r
			x1 = s+(x+1)*r
			y1 = s+yg+(y+1)*r
			yg += gap
			# Zeichne Perle
			object = cv.create_oval(x0,y0,x1,y1,fill='green',outline='darkgreen')
			# Event für die Rechtschiebung
			cv.tag_bind(object,"<Button-1>",lambda e,Object=object:MoveRight(Object))
			# Event für die Linksschiebung
			cv.tag_bind(object,"<Button-3>",lambda e,Object=object:MoveLeft(Object))

	quit = Button(root, text="Beenden", width=10, command=root.destroy)
	quit.pack(side="bottom",pady=4)

	if not usingIDLE:
  		root.mainloop()
Gruss wuf :wink:
Take it easy Mates!
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

Hi wuf!
Also ich komm nich ausm straunen raus. :shock: das is der wahnsinn.

ich versuche jetz mal dem Abakus das rechnen beizubringen.
Meld mich in ner stunde nochmal.
Mfg
Niko
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Niko

Gemäss deiner Antwort vom 26.0.2004-23:32
Betreffs deiner Frage ob du mit deinem Skript
weitermachen sollst oder wegwerfen würde ich
sagen unbedingt weitermachen bis es funktionier,
wenn du genügend Zeit hast. Es funktioniert ja
schon einiges ziemlich gut.
Mit einem Programm ist es wie mit einem Wiener-
Schnitzel. Du kannst in 10 verschieden Restaurants
ein Wiener-Schnitzel konsumieren. Jedes wird vom
Geschmack deiner Vorstellung anderst sein. Hat
also vor und Nachteile.
So ist es mit dem Erstellen eines Programms. Du
wirst es nach deiner momentanen Erfahrung zu-
sammenbauen. Wichtig ist es einfach, dass du es
fertig machst bis es läuft. So wirst du am meisten
profitieren. Mein Lösungsansatz weicht evt. von deinem
zu stark ab, dass du Teile davon in dein Skript über-
nehmen kannst. Weil ich habe mich mit den Tkinter-
Canvas-Objekten schon ein wenig herumquälen müssen und
habe und dabei gesehen, dass Tkinter, was die Koordinaten-
Rechnerei anbelang schon vieles selber verwaltet. Darum
habe ich mich bei meiner Lösung mehr auf die Nummern der
einzelnen Canvas-Objekte konzentriert.


Ok Niko
Gruss wuf :wink:
Take it easy Mates!
niko
User
Beiträge: 24
Registriert: Freitag 23. Januar 2004, 20:53

hi wuf!
also ich habe mich ziemlich lang damit herumgeschlagen mein script mit deinem zusammenzufügen.aber ich denke da sind die ansätze einfach zu verschieden. so habe ich mich entschieden dein script weiterzuverfolgen, denn es ist halt einfach gut und im grunde ist es auch logischer (und um einiges einfacher), wenn man erstmal weiß wieviele nützliche methoden das Canvas Widget hat. wieso also nicht von anderen lernen? :wink:
jetzt hab ich mal probiert die Zahl, die jetzt rechts vom Abakus steht( also alle Zahlen, die ja wenn man sie von oben nach unten anschaut) als die gerade angezeigte Zahl in einem Text (namens sum) zu schreiben. Dies dient der Tatsache, dass ich dann schauen kann, ob der Benutzer, wenn ich ihm ne Aufgabe so wie etwa 15+25 vorsetze und er auf fertig klickt, ob es auch fertig ist.
dass klappt soweit alles.Ich füge jetzt noch den Aufgabensteller in den Script ein.
um die gerade angezeigte zahl zu kriegen habe folgendes gemacht:

Code: Alles auswählen

from Tkinter import * 


def MoveRight(perle): 
   #~~ Schiebt Objekte nach rechts 

   #~~ Hilfsliste deklarieren 
   auxlist = [] 
   pos = cv.bbox(perle) 

   #~~ Objektnummern der Perlen auf der rechten Seite 
   #   der angeklickten Perle inklusive der angeklickten. 
   auxlist = list(cv.find_enclosed(pos[0],pos[1],right,pos[3])) 
   auxlist.reverse() 

   for obj in auxlist: 
      pos = cv.bbox(obj) 
      enclosed = cv.find_enclosed(pos[0]+r,pos[1],pos[2]+r,pos[3]) 
      if enclosed == (): 
         if pos[0] < numcol*s: 
            cv.move(obj,+s,0) 
            cv.itemconfigure(obj,fill="darkolivegreen3") 

   UpdateNumOfPearls() 

   return() 

def MoveLeft(perle): 
   #~~ Schiebt Objekte nach links 

   #~~ Hilfsliste deklarieren 
   auxlist = [] 
   pos = cv.bbox(perle) 

   #~~ Objektnummern der Perlen auf der linken Seite 
   #   der angeklickten Perle inklusive der angeklickten. 
   auxlist = list(cv.find_enclosed(left-1,pos[1],pos[2],pos[3])) 

   for obj in auxlist: 
      pos = cv.bbox(obj) 
      enclosed = cv.find_enclosed(pos[0]-r,pos[1],pos[2]-r,pos[3]) 
      if enclosed == (): 
         if pos[0] > s: 
            cv.move(obj,-s,0) 
            cv.itemconfigure(obj,fill="green") 

   UpdateNumOfPearls() 

   return() 

def UpdateNumOfPearls(): 
   #~~ Aktualisiert Texte auf der Canvasfläche
    global cleanmessage
    global zusammen
    zusammen = ''
    yg = 0
    cleaning = FALSE
    for row in range(numrows):
        y0 = s+yg+row*r
        y1 = s+yg+(row+1)*r
        foundobj = cv.find_enclosed(left-1,y0-1,right,y1+1)
        numpearls = 0
        numcolor  = 'blue'
        for obj in foundobj:
            fillcolor = cv.itemcget(obj,'fill')
            if fillcolor == 'darkolivegreen3':
                numpearls += 1
        if numpearls == numcol:
            cleaning = TRUE
            numcolor = 'red'
        xpos = right+15
        ypos = top+1+yg+r/2+row*r
        try:
            cv.delete(numlist[row])
        except:
            pass
        numlist[row] = cv.create_text(xpos,ypos,text=numpearls,anchor='w',fill=numcolor,font=font1)
        yg += gap
        zusammen = zusammen + str(numpearls)
    try:
        cv.delete(zusammen)
    except:
        pass
    #zusammen = str(numpearls)
    sum = cv.create_text(60,420,text=zusammen,font=font1)
    try:
        cv.delete(cleanmessage)
    except:
        pass
    if cleaning == TRUE:
        xpos = (top+right)/2
        ypos = bottom+30
        text = cleantext
        cleanmessage = cv.create_text(xpos,ypos,text=text,anchor='center',fill='red',font=font2)
    return() 

#  ->>----THE-ABACUS-APPLICATION----<<- 
root = Tk() 
root.title("Abakus-Prototyp-27.01.04 - 03:00") 
root['bg'] = 'steelblue3' 
cv = Canvas(root,height=430,width=450,bd=4,relief=RAISED,bg='khaki2') 
cv.pack() 

usingIDLE = 1 

#~~ Listendeklaration für die Anzahl verschobener Perlen 
numlist = [] 

#~~ Zeichensätze 
font1 = ('Helvetica', 15, 'bold') 
font2 = ('Helvetica', 15, 'bold','underline') 
cleantext = 'Bitte Bereinigen!!!' 

r       = 30    # Durchmesser der Perle 
s       = r+2   # Linker Anschlag für Perlen 
gap     = 6     # Vertikaler Zwischenraum 
numcol  = 10    # Anzahl Perlen pro Perlenreihe 
numrows = 10    # Anzahl der Perlenreihen 

dicke   = 4    # Dicke der Reihenstange 
top     = r    # Oberes Rahmenende 
left    = s    # Linkes Rahmenende 
right   = left+(numcol+1)*r+8  #Rahmenende rechts 
bottom  = top+(numrows*r)+(numrows*gap) # Rahmenende unten 
ypos    = 0    # Vertikalposition der Reihenstange 
yg      = 0    # Hilfsvariable 

#~~ Erzeugt Stangen 
for rod in range(numrows): 
  ypos = s+(r/2+1)+yg+rod*r 
  stange = cv.create_line(left, 
                    ypos, 
                    right+2, 
                    ypos, 
                    fill='darkolivegreen4', 
                    width=dicke) 
  yg += gap 

#~~ Erzeug Textobjekte für die Anzahl verschobener Perlen 
yg = 0 
for num in range(numrows): 
  xpos    = right+15 
  ypos    = top+1+yg+r/2+num*r 
  textobj = cv.create_text(xpos,ypos,text=0,anchor='w',fill='blue',font=font1) 
  numlist.append(textobj) 
  yg += gap 

#~~ Erzeugt Meldetext-Objekt für "Bereinigen" 
xpos = (top+right)/2 
ypos = bottom+30 
text = '' 
cleanmessage = cv.create_text(xpos,ypos,text=text,anchor='center',fill='red',font=font2) 
#~~ Erzeugt Fenster, dass die dargestellte Zahl anzeigt
sum = cv.create_text(20,420,text=text)

#~~ Erzeugt Abakusrahmen 
rectangle = cv.create_rectangle(left-2, 
                       top-4, 
                       right,bottom+4, 
                       width= 8, 
                       outline='darkgoldenrod4' 
                       ) 

#~~ Erzeugt die Perlen 
for x in range(numcol): 
  yg = 0 
  for y in range(numrows): 
     x0 = s+x*r 
     y0 = s+yg+y*r 
     x1 = s+(x+1)*r 
     y1 = s+yg+(y+1)*r 
     yg += gap 
     # Zeichne Perle 
     object = cv.create_oval(x0,y0,x1,y1,fill='green',outline='darkgreen') 
     # Event für die Rechtschiebung 
     cv.tag_bind(object,"<Button-1>",lambda e,Object=object:MoveRight(Object)) 
     # Event für die Linksschiebung 
     cv.tag_bind(object,"<Button-3>",lambda e,Object=object:MoveLeft(Object)) 

quit = Button(root, text="Beenden", width=10, command=root.destroy) 
quit.pack(side="bottom",pady=4) 

if not usingIDLE: 
    root.mainloop()
Antworten