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

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 приведен небольшой пример, иллюстрирующий малую часть возможностей.