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

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

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

Шрифт:

-
+

Интервал:

-
+

Закладка:

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

При конструировании каждого переключателя задается получатель данных, а идентификатор сообщения от переключателя делается равным FXDataTarget::ID_OPTION плюс желаемое значение. Если теперь запустить пример, то вы увидите, что переключатель стал вести себя как положено.

Для добавления в окно списка FXList и его инициализации тоже достаточно нескольких строк. Значение LIST_BROWSESELECT позволяет выбирать из списка ровно один элемент. В начальный момент выбран самый первый из них. Значение LIST_SINGLESELECT допускает выбор не более одного элемента; в этом случае в начальный момент ни один элемент не выбран:

@list = FXList.new(self, nil, 0,

 LIST_BROWSESELECT |

 LAYOUT_FILL_X)

@names = ["Chuck", "Sally", "Franklin", "Schroeder",

 "Woodstock", "Matz", "Lucy"]

@names.each { |name| @list.appendItem(name) }

Отметим, что вместо метода appendItem можно использовать оператор вставки в массив, то есть последнюю строку можно было бы записать и так:

@names.each { |name| @list << name }

Весь пример целиком приведен в листинге 12.12. Сообщение обрабатывается в главном окне, в результате выводится выбранный элемент. Если был задан режим LIST_SINGLE_SELECT, то важно отличать щелчок, при котором элемент был выбран, от щелчка, который отменил выбор.

Листинг 12.12. Виджет FXList

require 'fox16'

include Fox

class ListHandlerWindow < FXMainWindow

 def initialize(app)

  # Сначала вызвать инициализатор базового класса.

  super(app, "List Handler", nil, nil,

   DECOR_TITLE | DECOR_CLOSE)

  @list = FXList.new(self, nil, 0,

   LIST_BROWSESELECT |

   LAYOUT_FILL_X)

  @list.connect(SEL_COMMAND) do |sender, sel, pos|

   puts pos.to_s + " => " + @names[pos]

  end

  @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 приведен полный текст примера использования модальных и немодальных диалогов.

Листинг 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

  layout = FXHorizontalFrame.new(self, layout_options)

  options = FRAME_RAISED | FRAME_THICK |

   LAYOUT_RIGHT | LAYOUT_CENTER_Y

  hide_btn = FXButton.new(layout, "&Hide", nil, nil, 0,

   options)

  hide_btn.connect(SEL_COMMAND) { hide }

 end

 def text

  @text_field.text

 end

end

class ModalDialogBox < 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 |

   PACK_UNIFORM_WIDTH

  layout = FXHorizontalFrame.new(self, layout_options)

  options = FRAME_RAISED | FRAME_THICK |

   LAYOUT_RIGHT | LAYOUT_CENTER_Y

  cancel_btn = FXButton.new(layout, "&Cancel", nil,

   self, 0, options)

  cancel_btn.connect(SEL_COMMAND) do

   app.stopModal(self, 0)

   hide

  end

  accept_btn = FXButton.new(layout, "&Accept", nil,

   self, 0, options)

  accept_btn.connect(SEL_COMMAND) do

   app.stopModal(self, 1)

   hide

  end

 end

 def text

  @text_field.text

 end

end

class DialogTestWindow < FXMainWindow

 def initialize(app)

  # Сначала инициализировать базовый класс.

  super(app, "Dialog Test", nil, nil,

   DECOR_ALL, 0, 0, 400, 200)

  layout_options = LAYOUT_SIDE_TOP | FRAME_NONE |

   LAYOUT_FILL_X | LAYOUT_FILL_Y |

   PACK_UNIFORM_WIDTH

  layout = FXHorizontalFrame.new(self, layout_options)

  button_options = FRAME_RAISED | FRAME_THICK |

   LAYOUT_CENTER_X | LAYOUT_CENTER_Y

  nonmodal_btn = FXButton.new(layout, "&Non-Modal Dialog...", nil,

   nil, 0, button_options)

  nonmodal_btn.connect(SEL_COMMAND) do

   @non_modal_dialоg.show(PLACEMENT_OWNER)

  end

  modal_btn = FXButton.new(layout, "&Modal Dialog...", nil,

   nil, 0, button_options)

  modal_btn.connect(SEL_COMMAND) do

   dialog = ModalDialogBox.new(self)

   if dialog.execute(PLACEMENT_OWNER) == 1

    puts dialog.text

   end

  end

  getApp.addTimeout(1000, method(:onTimer))

  @non_modal_dialog = NonModalDialogBox.new(self)

 end

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