Программирование на языке Ruby.

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

В библиотеке GTK+ есть класс Gtk::Entry для ввода одной строки текста — мы видели его в предыдущем примере. Существует также класс Gtk::Textview, представляющий собой мощный многострочный редактор; его мы и опишем.

Программа в листинге 12.6 создает многострочное текстовое поле и помещает в него текст. По мере изменения содержимого поля текущая длина текста отображается с помощью метки, расположенной в нижней части окна (рис. 12.5).

Листинг 12.6. Текстовый редактор в GTK.

$KCODE = "U".

Require "gtk2".

Class TextWindow < Gtk::Window.

 def initialize.

  super("Ruby/GTK2 Text Sample").

  signal_connect("destroy") { Gtk.main_quit }.

  set_default_size(200, 100).

  @text = Gtk::TextView.new.

  @text.wrap_mode = Gtk::TextTag::WRAP_WORD.

  @buffer = @text.buffer.

  @buffer.signal_connect("changed") {

   @status.text = "Length: :" + @buffer.char_count.to_s.

  }

  @buffer.create_tag('notice',

   'font' => "Times Bold Italic 18",

   'foreground' => "red").

  @status = Gtk::Label.new.

  scroller = Gtk::ScrolledWindow.new.

  scroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_NEVER).

  scroller.add(@text).

  box = Gtk::VBox.new.

  box.add(scroller).

  box.add(@status).

  add(box).

  iter = @buffer.start_iter.

  @buffer.insert(iter, "This is an editor").

  iter.offset = 5.

  @buffer.insert(iter, "really ", "notice").

  show_all.

 end.

End.

Gtk.init.

TextWindow.new.

Gtk.main.

Программирование на языке Ruby.

Рис. 12.5. Небольшой текстовый редактор в GTK.

Структура программы такая же, как в примере с кнопкой: инициализировать Ruby/GTK2, определить класс главного окна, задать обработчик события, корректно завершающий приложение, и установить начальный размер окна. После initialize вызывается метод show_all, который делает окно видимым. В последних двух строчках создается окно и запускается цикл обработки событий.

Мы создали виджет редактора с именем @text. Включен режим переноса строк, по умолчанию строки разрываются без учета границы слов.

Переменная @buffer — это текстовый буфер для виджета @text. Мы установили обработчик события changed; он будет вызываться при вставке, удалении и изменении текста. Обработчик пользуется методом char_count, чтобы узнать текущую длину текста в редакторе и преобразовать ее в строку сообщения. Предложение @status.text=text отображает это сообщение в окне.

Далее мы конфигурируем виджет @text так, чтобы он показывал текст другим стилем. Для этого с помощью метода create_tag создается тег «notice», с которым связан шрифт «Times Bold Italic 18» и красный цвет. Класс Gtk::TextTag позволяет задавать и другие свойства тегов.

В данном случае мы хотим воспользоваться шрифтом из семейства Times; на платформе Windows мы, скорее всего, получим какой-то вариант шрифта Times Roman. В ОС Linux/UNIX параметром должна быть стандартная для X Window System строка указания шрифта. Система вернет шрифт, наиболее близкий к заданному.

Метка @status первоначально пуста. Ее текст будет изменен позже.

GTK+ предлагает два способа добавить полосы прокрутки. Можно напрямую создать объект Gtk::ScrollBar и с помощью сигналов синхронизировать его с ассоциированным виджетом. Но в большинстве случаев проще воспользоваться виджетом Gtk::ScrolledWindow.

Виджет Gtk::ScrolledWindow наследует Gtk::Bin, поэтому может содержать только один дочерний виджет. Но этот виджет может принадлежать классу Gtk::Вох или любому другому контейнеру, допускающему несколько потомков. Ряд виджетов GTK+, в том числе и Gtk::TextView, автоматически взаимодействуют с Gtk::ScrolledWindow, не требуя почти никакого дополнительного кода.

В данном примере мы создали виджет Gtk::ScrolledWindow с именем scroller и сконфигурировали его методом set_policy. Мы решили не отображать горизонтальную полосу прокрутки вовсе, а вертикальную — только тогда, когда в редакторе больше строк, чем видно в окне. Сам текстовый редактор сделан непосредственным потомком scroller.

Теперь надо настроить контейнер Gtk::Vbox, который расположит наши виджеты по вертикали. Сначала добавляется прокручиваемое окно, содержащее поле ввода, поэтому оно окажется самым верхним. Метка @status располагается под ним. Напоследок сам контейнер добавляется в главное окно.

В следующих четырех строчках в поле ввода добавляется текст. В первой строчке мы получаем объект Gtk::TextIter, соответствующий началу текста (offset = 0), и вставляем в это место строку. Поскольку до этого момента никакого текста в поле еще не было, только сюда и можно его вставить. Затем вставляется другой кусок текста со смещением 5. В результате редактор будет содержать строку This really is an editor.

Поскольку мы предварительно установили обработчик события changed, он будет вызываться после каждого обращения к insert. Следовательно, статус будет отображаться правильно, несмотря на то что пользователь еще не вносил никаких изменений в текст.