Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование на языке Ruby.docx
Скачиваний:
18
Добавлен:
06.09.2019
Размер:
1.74 Mб
Скачать

Листинг 12.17. Нестандартный виджет TimerClock

require 'Qt'

class TimerClock < Qt::Widget

 def initialize(parent = nil)

  super(parent)

  @timer = Qt::Timer.new(self)

  connect(@timer, SIGNAL('timeout()'), self, SLOT('update()'))

  @timer.start(25)

  setWindowTitle('Stop Watch')

  resize(200, 200)

 end

 def paintEvent(e)

  fastHand = Qt::Polygon.new([Qt::Point.new(7, 8),

   Qt::Point.new(-7, 8),

   Qt::Point.new(0, -80)])

  secondHand = Qt::Polygon.new([Qt::Point.new(7, 8),

   Qt::Point.new(-7, 8),

   Qt::Point.new(0, -65)])

  secondColor = Qt::Color.new(100, 0, 100)

  fastColor = Qt::Color.new(0, 150, 150, 150)

  side = [width, height].min

  time = Qt::Time.currentTime

  painter = Qt::Painter.new(self)

  painter.renderHint = Qt::Painter::Antialiasing

  painter.translate(width() / 2, height() / 2)

  painter.scale(side / 200.0, side / 200.0)

  painter.pen = Qt::NoPen

  painter.brush = Qt::Brush.new(secondColor)

  painter.save

  painter.rotate(6.0 * time.second)

  painter.drawConvexPolygon(secondHand)

  painter.restore

  painter.pen = secondColor

   (0...12).each do |i|

   painter.drawLine(88, 0, 96, 0)

   painter.rotate(30.0)

  end

  painter.pen = Qt::NoPen

  painter.brush = Qt::Brush.new(fastColor)

  painter.save

  painter.rotate(36.0 * (time.msec / 100.0))

  painter.drawConvexPolygon(fastHand)

  painter.restore

  painter.pen = fastColor

   (0...60).each do |j|

   if (j % 5) != 0

    painter.drawLine(92, 0, 96, 0)

   end

   painter.rotate(6.0)

  end

  painter.end

 end

end

app = Qt::Application.new(ARGV)

wid = TimerClock.new

wid.show

app.exec

Созданный в этом примере виджет называется TimerClock. В инициализаторе мы создаем объект Qt::Timer, который конфигурируется для периодического испускания сигнала. Его сигналtimeout мы соединяем со слотом update нашего виджета. Это встроенный слот, он заставляет виджет перерисовать себя.

Таймер запускается методом start. Переданный ему аргумент говорит, что таймер должен срабатывать (и испускать сигнал timeout) каждые 25 миллисекунд. Следовательно, слот update будет вызываться каждые 25 миллисекунд.

Далее определяется метод paintEvent. Мы переопределяем одноименный метод класса Qt::Widget. Когда виджет собирается перерисовать себя (то есть при срабатывании таймера), он вызывает этот метод. Переопределяя его, мы решаем, как виджет должен отображаться на экране. Код этого метода вызывает различные графические примитивы рисования.

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

Задаются значения нескольких свойств. Устанавливаются цвета Qt::Color обеих стрелок. Аргументами инициализатора Qt::Color являются значения в формате RGB с необязательной альфа-прозрачностью.

Часы должны быть квадратными, поэтому в переменную side (длина стороны) записывается минимум из ширины и высота виджета. Кроме того, мы запоминаем текущее время, обращаясь к методу Qt::Time.currentTime.

Далее создается объект Qt::Painter, и с его помощью мы начинаем рисовать. Задается режим сглаживания (antialiasing), чтобы на стрелках часов не было «лесенки». Начало координат помещается в центр области рисования (painter.translate (width/2, height/2)). Для объекта Painter устанавливается масштаб в предположении, что сторона квадрата составляет 200 единиц. Если размер окна изменится, то масштабирование будет произведено автоматически.

Затем выполняется последовательность операций рисования. Различные геометрические преобразования (например, поворот), сопровождаются парой вызовов painter.save и painter.restore. Метод save сохраняет текущие свойства объекта Painter в стеке, чтобы их можно было позднее восстановить.

Программа рисует обе стрелки, предварительно повернув их на нужный угол в соответствии с текущим временем. Кроме того, мы наносим риски вдоль границы циферблата.

И напоследок мы сообщаем объекту Painter, что рисование закончилось (вызывая метод painter.end). Довершают картину четыре строчки, в которых создаются объект приложенияQt::Application и наш виджет, а затем запускается цикл обработки событий. На рис. 12.10 показан конечный результат.

Рис. 12.10. Виджет TimerClock