ACHTUNG. Das ist ein Archiv des alten forum.ruby-portal.de. Die aktuelle Mailingliste gibt es auf lists.ruby-lang.org/pipermail/ruby-de.

NOTICE. This is a ready-only copy of the old forum.ruby-portal.de. You can find the current mailing list at lists.ruby-lang.org/pipermail/ruby-de.

Die Programmiersprache Ruby

Blog|

Forum|

Wiki  


Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]

Ein neues Thema erstellen Auf das Thema antworten  [ 3 Beiträge ] 
Autor Nachricht
BeitragVerfasst: 11 Okt 2011, 19:13 
Offline
Nuby

Registriert: 11 Okt 2011, 18:29
Beiträge: 2
Hallo,

ich bin jetzt einfach mal so unhöflich und formuliere als ersten Beitrag in diesem Forum eine Frage – ich habe allerdings seit geraumer Zeit einen Knoten im Hirn und glaube, daß mein Problem ganz interessant sein könnte. Vielleicht ist es auch trivial, und ich kapiere es nicht.

Das Problem ist folgendes: Ich habe zwei ineinandergeschachtelte Konstrukte mit laufenden Indizes x und y. Innen werden Objekte in einem zweidimensionalen Array an den jeweiligen Koordinaten (x;y) angelegt. Diese einzelnen Objekte sollen nun klickbar sein. Beim anklicken wird die Hintergrundfarbe geändert (und es passiert noch mehr, was jetzt hier aber egal ist).

Das ganze sieht dann vereinfacht etwa so aus:



1
2
3
4
5
6
7
8
9
10
10.times do |x|
20.times do |y|
@my_ary[x][y] = flow do
background white
end
@my_ary[x][y].click do
#???
end
end
end


Die Frage lautet nun: wie kann ich bei #??? das Objekt selbst referenzieren? Wenn ich an dieser Stelle einfach


1
2
3
@my_ary[x][y].clear do
background black
end

hinschreibe, funktioniert das ganze natürlich nicht, weil x und y in dem Moment, wo geklickt wird, wieder in einem ganz anderen Zustand bzw. gar nicht mehr existent / außerhalb des Scope sind. Auf self kann ich mich auch nicht beziehen, da self in Shoes eben immer das Shoes-Objekt ist.

Das einzige Workaround das mir eingefallen ist, besteht darin in dem Moment wo geklickt wird die Mausposition auszulesen und dann wieder auszurechnen, wohin geklickt wurde. Das geht so lange gut, wie man sich immer auf derselben Plattform befindet. Sobald man eine Plattform hat, die Buttons und Texte ein bisschen anders gestaltet, stimmen natürlich auch die Rechnungen hinten und vorne nicht mehr.

So sehr ich mich geistig auch verrenke, mir will einfach nicht einfallen, wie ich an der Stelle die Koordinaten "festbacken" kann, so daß das Objekt, wenn sein click-Block aufgerufen wird, auch weiß, "wer" es ist.

Eventuell ist das Problem total trivial und ich stehe einfach nur auf dem Schlauch. Würde mich auf jeden Fall über den ein oder anderen Anstoß freuen!

Sorry nochmal für meine Unverschämtheit :oops:, vielen Dank und beste Grüße
feliks


Nach oben
 Profil  
 
BeitragVerfasst: 11 Okt 2011, 23:42 
Offline
Interpreter
Benutzeravatar

Registriert: 21 Mai 2007, 11:30
Beiträge: 1283
Wohnort: Thüringen
Zitat:
weil x und y in dem Moment, wo geklickt wird, wieder in einem ganz anderen Zustand bzw. gar nicht mehr existent
Da hast du einen Denkfehler. x und y sind nur Variablen. Die haben keinen Zustand. Sie zeigen auf Integer-Objekte, die selbst wiederum unveränderliche Objekte sind (daher können sie ihren Zustand/Wert nicht ändern).

Es gibt einen Unterschied zwischen dem:


1
2
3
4
5
x = 5
callback = proc() {x}
3.times do |x|
end
callback.call #=> 2


und dem hier:


1
2
3
4
5
6

callbacks = []
3.times do |x|
callbacks << proc() {x}
end
callbacks.each {|callback| callback.call } #=> 0, 1, 2


In ersterem Fall wird die Variable x im äußeren Scope definiert und dann im Block verwendet. Nach Aufrufen von 3.times wird x erst 0, dann 1 und schließlich die 2 zugewiesen. Rufst du danach den Callback auf, bekommst du den Wert 2 zurück. Das ist ja auch der Wert, den die Variable x in diesem Moment inne hat.

Im zweiten Fall definierst du die Variable x im Scope des Blocks. Das heißt in jedem Durchlauf wird eine neue Variable x erzeugt bzw. auf den Stack gelegt. Im ersten Durchlauf hat diese den Wert 0, im zweiten den Wert 1 und schließlich den Wert 2. Beim Verlassen des Blocks wird die Variable wieder vom Stack entfernt. Jeder Callback bezieht sich auf die Variable x, die in dem Moment wo der Proc erzeugt wurde existent war. Die neue Variable x im nächsten Durchlauf überschreibt dabei nicht den Wert der alten Variable.

In Ruby >= 1.9 machen übrigens beide Codebeispiele dasselbe. Dort wurde festgelegt das Blöcke bei Parametern immer eigene Variablen einführen und keine bestehenden Variablen verwenden dürfen. Folgendes geht aber auch in Ruby 1.9 noch:


1
2
3
4
5
6
7
8
9
x = 5
y = 8
callback = proc() {puts(x); puts(y);}
3.times do |y|
x = 2
end
callback.call()
#=> 2
#=> 8

Hier wird die x Variable im Block überschrieben, die y Variable hingegen nicht (der Block erzeugt stattdessen seine eigene).

Aber ganz egal welche Rubyversion du verwendest. Folgendes sollte funktionieren:


1
2
3
4
5
6
7
8
9
10
11
12
13
10.times do |x|
20.times do |y|
@my_ary[x][y] = flow do
background white
end
@my_ary[x][y].click do
@my_ary[x][y].do_something()
end
# alternativ geht auch
widget = @my_ary[x][y]
widget.click {widget.do_something}
end
end


Nach oben
 Profil  
 
BeitragVerfasst: 12 Okt 2011, 21:08 
Offline
Nuby

Registriert: 11 Okt 2011, 18:29
Beiträge: 2
Hallo Kai,

vielen Dank für die ausführliche Antwort! Zunächst war ich mir eigentlich sicher, daß ich die am Ende deines Postings vorgeschlagene Lösung zu Beginn selbst schon mal so programmiert hätte (steht ja auch so in meinem Posting), was aber nicht funktioniert hätte. Ich wollte mich schon beschweren, aber um ganz sicherzugehen probierte ich gerade nochmal aus, was passieren würde … und siehe da, es funktioniert!

Wieder so ein Problem, wo einem nur jemand gut zureden muß, und auf einmal klappt es :D – ich kann leider nicht mehr nachvollziehen, was ich zuerst falsch gemacht hatte. Deshalb kann ich leider auch nicht genau sagen, was ich heute gelernt habe …

Jedenfalls vielen Dank und Grüße
feliks


Nach oben
 Profil  
 
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 3 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach: