Как я могу использовать индикатор прогресса в обуви? - PullRequest
1 голос
/ 02 мая 2009

Хорошо, поэтому я не совсем уверен во многих вещах в Обуви, но мой метод проб и ошибок не помог мне в этом.

У меня есть класс, который выполняет какое-то вычисление, которое занимает некоторое время, и я хочу вызвать индикатор выполнения, чтобы пользователь мог посмотреть, пока он завершится. Мой вычислительно интенсивный метод дает свой процент завершения, если передан блок:

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

Вот что я бы хотел бы сказать в туфлях:

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

Но, похоже, это не работает. Я пробовал с / без вызова окна, я пробовал animate () различными способами, я даже пытался вызвать Thread.new и передать ему блок окна, чтобы они общались через Shoes.APPS () [0] .get / setPercent методы; кажется, ничего не работает должным образом.

Может быть, я не использую индикатор выполнения так, как он предназначен для использования. Опять же, для чего еще будет индикатор выполнения? ; -)

Ответы [ 2 ]

5 голосов
/ 02 мая 2009

Прежде всего, обмен данными между двумя окнами в Shoes - это королевская боль. Я не рекомендую это. Вместо этого скройте содержимое первого окна и выведите индикатор выполнения на его место.

Во-вторых, мы расширим MathyStuff, чтобы переключить его с обработки блока на предоставление атрибута процента, чтобы мы могли получить к нему доступ из потока анимации:

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
3 голосов
/ 02 мая 2009

Насколько я понимаю, такие вещи, как индикатор выполнения, должны отображаться на экране после ввода процентного значения, для этого в этом случае вы бы использовали animate.

Если вы просто хотите сделать то, что заявили в своем вопросе, тогда этот подход - хотя и не очень гибкий - работает для вашего примера. Но поскольку она отделяет логику прогресса от вашего фактического метода, вы можете изменять процентные значения только до и после запуска этих методов. Итак, поскольку вы просто выполняете итерацию 100 раз, вы можете сделать это эффективно таким образом.

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

Если ваш метод делает больше, чем просто повторяет одну и ту же итерацию, тогда да, вы захотите часто получать информацию о его прогрессе изнутри метода. Затем, чтобы вернуть этот прогресс из метода во время его работы, вы можете поместить его в отдельный поток, как предложил Песто, и просто опросить его о прогрессе в вашем блоке анимации. Использование attr_accessor для возврата процента также является хорошей идеей. Надеюсь, это поможет.

...