Категории
Самые читаемые
Лучшие книги » Компьютеры и Интернет » Программирование » Программирование на языке Ruby - Хэл Фултон

Программирование на языке Ruby - Хэл Фултон

Читать онлайн Программирование на языке Ruby - Хэл Фултон

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 101 102 103 104 105 106 107 108 109 ... 156
Перейти на страницу:

В самом конце мы создаем экземпляр класса Qt::HBoxLayout. При добавлении виджетов в этот контейнер он автоматически изменяет их размеры, так что нам больше не о чем беспокоиться.

12.4.4. Текстовые поля

Как видно из листинга 12.14, в QtRuby есть класс Qt::LineEdit для ввода одной строки текста. Для ввода нескольких строк предназначен класс Qt::TextEdit.

В листинге 12.15 демонстрируется многострочное текстовое поле. Под ним расположена метка, в которой отображается текущая длина текста (рис. 12.8).

Листинг 12.15. Простой редактор в Qt

require 'Qt'

class MyTextWindow < Qt::Widget

 slots 'theTextChanged()'

 def initialize(parent = nil)

  super(parent)

  @textedit = Qt::TextEdit.new(self)

  @textedit.setWordWrapMode(Qt::TextOption::WordWrap)

  @textedit.setFont( Qt::Font.new("Times", 24) )

  @status = Qt::Label.new(self)

  box = Qt::VBoxLayout.new

  box.addWidget(@textedit)

  box.addWidget(@status)

  setLayout(box)

  @textedit.insertPlainText("This really is an editor")

  connect(@textedit, SIGNAL('textChanged()'),

   self, SLOT('theTextChanged()'))

 end

 def theTextChanged

  text = "Length: " + @textedit.toPlainText.length.to_s

  @status.setText(text)

 end

end

app = Qt:Application.new(ARGV)

widget = MyTextWindow.new

widget.setWindowTitle("QtRuby Text Editor")

widget.show

app.exec

Рис. 12.8. Простой редактор в Qt

Виджет конструируется примерно так же, как в предыдущем примере. Но теперь мы создаем объект Qt::TextEdit, а также метку Qt::Label для показа текущего состояния.

Стоит отметить, что для объекта @textedit мы указали шрифт Times высотой 24 пункта. У каждого класса, наследующего Qt::Widget (в том числе и у Qt::TextEdit) есть свойство font, которое можно опросить или установить.

Затем мы создаем менеджер вертикального размещения (Qt::QBoxLayout), который будет контейнером для всех своих потомков, добавляем в него виджет @textedit и связываем сигнал textChanged с определенным нами слотом theTextChanged.

В методе theTextChanged мы запрашиваем у редактора текст и получаем его длину, а затем записываем возвращенное значение в метку @status.

Отметим, что весь механизм сигналов и слотов работает асинхронно. После того как приложение входит в цикл обработки событий (арр.ехес), оно уже не получает управления явно. Вот почему сигналы и слоты так важны. Мы определяем события, которые нас интересуют (сигналы), и действия, которые нужно выполнить при возникновении таких событий (слоты).

12.4.5. Прочие виджеты

В библиотеке Qt есть еще много встроенных виджетов, например переключатели, флажки и т.п. В листинге 12.16 продемонстрированы некоторые из них, а на рис. 12.9 показано, как выглядит окно приложения.

Листинг 12.16. Прочие виджеты в Qt

require 'Qt'

class MyWindow < Qt::Widget

 slots 'somethingClicked(QAbstractButton *)'

 def initialize(parent = nil)

  super(parent)

  groupbox = Qt::GroupBox.new("Some Radio Button",self)

  radio1 = Qt::RadioButton.new("Radio Button 1", groupbox)

  radio2 = Qt::RadioButton.new("Radio Button 2", groupbox)

  check1 = Qt::CheckBox.new("Check Box 1", groupbox)

  vbox = Qt::QBoxLayout.new

  vbox.addWidget(radio1)

  vbox.addWidget(radio2)

  vbox.addWidget(check1)

  groupbox.setLayout(vbox)

  bg = Qt::ButtonGroup.new(self)

  bg.addButton(radio1)

  bg.addButton(radio2)

  bg.addButton(check1)

  connect(bg, SIGNAL('buttonClicked(QAbscractButton *)'),

   self, SLOT('somethingClicked(QAbstractButton *)') )

  @label = Qt::Label.new(self)

  vbox = Qt::VBoxLayout.new

  vbox.addWidget(groupbox)

  vbox.addWidget(@label)

  setLayout(vbox)

 end

 def somethingClicked(who)

  @label.setText("You clicked on a " + who.className)

 end

end

app = Qt::Application.new(ARGV)

widget = MyWindow.new

widget.show

app.exec

Рис. 12.9. Простое приложение Tk

В этом классе мы сначала создаем объект Qt::GroupBox — контейнер с рамкой и необязательным заголовком, в который можно помещать другие виджеты. Далее создаются два переключателя Qt::RadioButtons и флажок Qt::CheckBox, а в качестве их родителя указывается ранее созданный контейнер.

Затем создается менеджер размещения Qt::VBoxLayout, в который помещаются переключатели и флажок, после чего этот менеджер связывается с групповым контейнером и начинает управлять его размещением на экране.

Следующий важный шаг — создание объекта Qt::ButtonGroup, в который помещаются флажок и переключатели. Qt::ButtonGroup предназначен для логической группировки кнопок, флажков и переключателей. На их визуальное расположение он никак не влияет, зато обеспечивает, к примеру, взаимное исключение (гарантирует, что только один из группы виджетов может быть отмечен). В данном случае этот объект будет источником сигнала buttonClicked, который испускается при нажатии любой кнопки в группе.

Этот сигнал отличается от виденных ранее тем, что ему сопутствует аргумент, а именно объект, по которому щелкнули мышкой. Обратите внимание на то, как синтаксис — QAbstractButton* — напоминает о C++-ных корнях Qt. В некоторых случаях употребления принятой в C++ нотации для обозначения типов параметров не избежать (хотя в будущих версиях это, возможно, и исправят).

В результате такого вызова метода connect при щелчке по любому виджету, принадлежащему группе, этот виджет будет передан слоту somethingClicked. Наконец, мы создаем метку Qt::Label, контейнер Qt::QBoxLayout и увязываем все вместе.

Внутри слота somethingClicked мы модифицируем текст метки при щелчке по любому переключателю или флажку. В данном случае выводится имя класса объекта, который испустил сигнал, приведший к вызову слота.

Если встроенных виджетов недостаточно, то Qt предоставляет мощную систему рисования для создания собственных. В листинге 12.17 приведен небольшой пример, иллюстрирующий малую часть возможностей.

Листинг 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. Когда виджет собирается перерисовать себя (то есть при срабатывании таймера), он вызывает этот метод. Переопределяя его, мы решаем, как виджет должен отображаться на экране. Код этого метода вызывает различные графические примитивы рисования.

1 ... 101 102 103 104 105 106 107 108 109 ... 156
Перейти на страницу:
На этой странице вы можете бесплатно скачать Программирование на языке Ruby - Хэл Фултон торрент бесплатно.
Комментарии