Как я могу использовать индикатор выполнения в программе Shoes?

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

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

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 методы; вроде ничего не работает должным образом.

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


person shawn    schedule 01.05.2009    source источник


Ответы (2)


Прежде всего, совместное использование данных между двумя окнами в 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
person Pesto    schedule 02.05.2009
comment
Спасибо, это очень помогло. Кажется, что программирование с графическим интерфейсом, даже в Shoes, требует другого подхода к вещам. Я уверен, что скоро вернусь с другими вопросами! - person shawn; 03.05.2009

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

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

person Michael Richards    schedule 02.05.2009