@names = ['Chuck', 'Sally', 'Franklin',
'Schroeder', 'Woodstock',
'Matz', 'Lucy']
@names.each { |name| @list << name }
end
end
application = FXApp.new
main = ListHandlerWindow.new(application)
application.create
main.show(PLACEMENT_SCREEN)
application.run
Если вместо LIST_BROWSESELECT
поставить LIST_EXTENDEDSELECT
, то в списке можно будет выбирать несколько элементов:
@list = FXList.new(self, nil, 0, LIST_EXTENDEDSELECT | LAYOUT_FILL_X)
Обработчик сообщений можно изменить так, чтобы он отображал все выбранные элементы. Чтобы понять, какие элементы списка выбраны, придется перебрать все:
@list.connect(SEL_COMMAND) do |sender, sel, pos|
puts 'Был щелчок по ' + pos.to_s +'=>' +
@names[pos]
puts 'Выбраны следующие элементы:'
@list.each do |item|
if item.selected?
puts ' ' + item.text
end
end
end
Атрибут numVisible
объекта FXList
позволяет указать, сколько элементов списка видно одновременно. Существует также виджет FXListBox
, который отображает только выбранное значение. Его интерфейс похож на интерфейс FXList
с несколькими отличиями. Аргументы конструктора точно такие же, как видно из следующего примера. Отметим, что FXListBox
позволяет выбирать только один элемент, поэтому значение LIST_EXTENDEDSELECT
игнорируется:
@list_box = FXListBox.new(self,nil,0,LIST_BROWSESELECT | LAYOUT_FILL_X)
@names = ['Chuck', 'Sally', 'Franklin', 'Schroeder',
'Woodstock', 'Matz', 'Lucy']
@names.each { |name| @list_box << name }
Диалоговое окно можно определить один раз как подкласс класса FXDialogBox
, а затем использовать для создания модальных или немодальных диалогов. Однако способы взаимодействия модальных и немодальных диалогов со своим владельцем различны.
Под модальным мы понимаем окно или диалог, который препятствует доступу к другим частям приложения, пока не будет закрыт. Немодальный диалог позволяет передавать фокус другим окнам приложения.
В следующем примере определяется класс модального и немодального диалога. Для модального класса используются предопределенные сообщения ID_CANCEL
и ID_ACCEPT
. Немодальный класс пользуется только предопределенным сообщением ID_HIDE
.
Для отображения немодального диалога применяется уже знакомый метод FXTopwindow.show
. Модальный диалог имеет собственный цикл обработки событий, отличный от цикла всего приложения. Для его отображения служит метод FXDialogBox.execute
. Как видно из полного листинга программы, значение, возвращаемое методом execute
, зависит от того, какое значение было передано методу приложения stopModal
для завершения цикла обработки событий модального диалога. В этом примере значение 1 говорит о том, что пользователь нажал кнопку Accept.
modal_btn.connect do
dialog = ModalDialogBox.new(self)
if dialog.execute(PLACEMENT_OWNER) == 1
puts dialog.text
end
end
Немодальный диалог работает параллельно с другими окнами приложения. Приложение должно запрашивать интересующие его данные у диалога по мере необходимости. Один из способов известить о появлении новых данных - включить в диалог кнопку Apply (Применить), которая будет посылать зависящее от приложения сообщение главному окну. В примере ниже используется также таймер — еще одна интересная особенность FxRuby. Когда таймер срабатывает, главному окну посылается сообщение. Обработчик этого сообщения (показан ниже) запрашивает у диалога новое значение и взводит таймер еще на одну секунду:
def onTimer(sender, sel, ptr)
text = @non_modal_dialog.text
unless text == @previous
@previous = text
puts @previous
end
getApp().addTimeout(1000, method(:onTimer))
end
В листинге 12.13 приведен полный текст примера использования модальных и немодальных диалогов.
require 'fox16'
include Fox
class NonModalDialogBox < FXDialogBox
def initialize(owner)
# Сначала вызвать инициализатор базового класса.
super(owner, 'Test of Dialog Box',
DECOR_TITLE|DECOR_BORDER)
text_options = JUSTIFY_RIGHT | FRAME_SUNKEN |
FRAME_THICK | LAYOUT_SIDE_TOP
@text_field = FXTextField.new(self, 20, nil, 0,
text_options)
@text_field.text = ''
layout_options = LAYOUT_SIDE_TOP | FRAME_NONE |
LAYOUT_FILL_X | LAYOUT_FILL_Y |
РАСK_UNIFORM_WIDTH