2009-05-01 14 views
1

Ok, ich bin mir in Shoes nicht wirklich sicher über viele Dinge, aber mein Trial-and-Error-Ansatz hat mich bisher auf diesem Weg enttäuscht.Wie kann ich den Fortschrittsbalken in Shoes verwenden?

Ich habe eine Klasse, die eine Art von Berechnung ausführt, die eine Weile dauert, und ich möchte einen Fortschrittsbalken für den Benutzer werfen, um zu betrachten, während es beendet wird. Meine rechenintensive Methode liefert seinen Prozent abgeschlossen, wenn ein Block übergeben:

class MathyStuff 

    def initialize() 
    end 

    ## Some expensive, time consuming method which yields it's percent complete 
    def expensiveMethod(&block) 
    0.upto(100) do |i| 
     0.upto(100000) do |j| 
     k = j; 
     end 

     yield i.to_f/100; 
    end 
    end 

end 

Hier ist, was ich wie würde in Schuhe sagen:

require 'MathyStuff.rb' 

Shoes.app do 

    @myMathyStuff = MathyStuff.new(); 

    button("Do expensive mathy thing...") do 
    window() do 
     @progress = progress(); 
     @myMathyStuff.expensiveMethod() {|percent| @progress.fraction = percent;} 
    end 
    end 

end 

Aber es scheint nicht zu funktionieren. Ich habe versucht mit/ohne den Fensteranruf, ich habe animate() auf verschiedene Arten versucht, ich habe sogar versucht, Thread.new aufzurufen und ihm den Fensterblock zu übergeben, indem er über Shoes.APPS() [0] .get/setPercent-Methoden; nichts scheint richtig zu funktionieren.

Vielleicht verwende ich den Fortschrittsbalken nicht so, wie er verwendet werden soll. Andererseits, wofür wäre sonst noch ein Fortschrittsbalken? ;-)

Antwort

4

Zuallererst ist das Teilen von Daten zwischen zwei Fenstern in Shoes ein königlicher Schmerz. Ich empfehle es nicht. Verstecken Sie stattdessen den Inhalt des ersten Fensters und rufen Sie statt dessen den Fortschrittsbalken auf.

Zweitens werden wir MathyStuff verlängern sie wechseln von der Verarbeitung eines Blocks ein Prozent Attribut zu bieten, so dass wir es von einem Animations Thread zugreifen:

class MathyStuff 
    attr_accessor :percent 

    def expensiveMethodWrapper 
    @percent = 0.0 
    expensiveMethod {|x| @percent = x} 
    end 
end 

Shoes.app do 

    @myMathyStuff = MathyStuff.new(); 
    @window_slot = stack do 
    button("Do expensive mathy thing...") do 
     @window_slot.toggle 
     @progress_slot = flow do 
     @progress = progress :width => 1.0 
     end 
    end 
    Thread.new do 
     @myMathyStuff.expensiveMethodWrapper 
    end 
    @animate = animate do 
     @progress.fraction = @myMathyStuff.percent 
     if @myMathyStuff.percent == 1.0 
     @progress_slot.remove 
     @window_slot.toggle 
     @animate.stop 
     end 
    end 
    end 
end 
+0

Danke, das hat sehr geholfen. Es scheint, dass GUI-Programmierung, selbst in Shoes, eine andere Art des Denkens erfordert. Ich bin bald wieder mit mehr Fragen zurück, da bin ich mir sicher! – shawn

3

Wie ich es verstehe, Dinge wie die Fortschritte bar muss nach dem Eingeben eines Prozentwerts neu auf dem Bildschirm angezeigt werden. In diesem Fall würden Sie animate verwenden.

Wenn Sie nur das tun wollen, was Sie in Ihrer Frage angegeben haben, dann ist dieser Ansatz - obwohl nicht sehr flexibel - für Ihr Beispiel geeignet. Da Sie jedoch Ihre Fortschrittslogik von Ihrer tatsächlichen Methode trennen, können Sie die Prozentwerte nur vor und nach dem Ausführen dieser Methoden ändern. Da Sie also nur 100 Mal eine Iteration ausführen, können Sie dies auf diese Weise effektiv tun.

class Mathy 
    def foo 
    100000.times do |bar| 
     foo = bar 
    end 
    end 
end 

Shoes.app do 
    @mathy = Mathy.new 
    button("Run") do 
    @p = progress 
    animate do |percent| 
     break if percent > 100 
     @mathy.foo 
     @p.fraction = percent.to_f/100 
    end 
    end 
end 

Wenn Ihre Methode wird mehr tun, als nur die gleiche Iteration wiederholen, dann ja, dann würden Sie wollen den Fortschritt innerhalb der Methode häufig ergeben. Um diesen Fortschritt von der Methode zurückzugeben, während sie läuft, können Sie sie in einen separaten Thread einfügen, wie Pesto vorgeschlagen hat, und sie einfach für den Fortschritt in Ihrem animierten Block abfragen. Es ist auch eine gute Idee, einen attr_accessor zum Zurückgeben des Prozentsatzes zu verwenden. Ich hoffe, das hilft.

Verwandte Themen