The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Каталог документации / Раздел "Программирование, языки" / Оглавление документа

3.2. Создание меню и панелей инструментов.

Большинство современных приложений имеют как меню, так и панели инструментов, которые содержат более или менее идентичный набор команд. Меню дают пользователю возможность заняться "исследованием" приложения, изучать доступные команды, а панели инструментов служат для быстрого доступа к командам, используемым наиболее часто.

Qt значительно упрощает разработку меню и панелей инструментов за счет использования концепции "действия" (action). Action -- это элемент, который может быть добавлен в меню и/или на панель инструментов. Для создания меню и панели инструментов необходимо выполнить следующие шаги:

В нашем приложении все необходимое выполняет функция createActions():
void MainWindow::createActions() 
{ 
  newAct = new QAction(tr("&New"), tr("Ctrl+N"), this); 
  newAct->setIconSet(QPixmap::fromMimeSource("new.png")); 
  newAct->setStatusTip(tr("Create a new spreadsheet file")); 
  connect(newAct, SIGNAL(activated()), this, SLOT(newFile()));      
      
В данном случае создается новое "действие" с названием "New", горячей комбинацией клавиш Ctrl+N и с владельцем -- главным окном приложения. Затем к "действию" прицепляются иконка (new.png) и текст подсказки, который будет выводиться в строке состояния. В заключение -- сигнал activated() подключается к слоту главного окна newFile(), который будет описан в следующем разделе. Без этого соединения, при выборе пункта меню "File|New" или при нажатии на кнопку "New" (в панели инструментов), ничего происходить не будет.

Аналогичным образом создаются все остальные "действия" (action).

Рисунок 3.3. Меню приложения Spreadsheet.


Команда (action) "Show Grid", в меню "Options" реализуется несколько иначе:

  showGridAct = new QAction(tr("&Show Grid"), 0, this); 
  showGridAct->setToggleAction(true); 
  showGridAct->setOn(spreadsheet->showGrid()); 
  showGridAct->setStatusTip(tr("Show or hide the spreadsheet s " "grid")); 
  connect(showGridAct, SIGNAL(toggled(bool)), spreadsheet, SLOT(setShowGrid(bool)));      
      
Эта команда имеет два фиксированных состояния -- включено-выключено. В меню рядом с ней отображается галочка (когда включено), а на панели инструментов она выглядит как кнопка с фиксацией. Когда "действие" включено, то компонент Spreadsheet отображается в окне приложения. Мы инициализируем "действие" значением по-умолчанию -- включено. Таким образом выполняется начальная синхронизация "действия" с фактическим режимом отображения компонента Spreadsheet. Затем мы подключаем сигнал toggled(bool) к слоту setShowGrid(bool), компонента Spreadsheet. После этого "действие" (action) добавляется в меню или на панель инструментов. Теперь пользователь может "включать" и "выключать" таблицу.

Команды "Show Grid" и "Auto-recalculate" -- являются "действиями" с независимой фиксацией. Однако, QAction имеет наследника -- QActionGroup, с помощью которого можно создавать группы "действий" с зависимой фиксацией.

Рисунок 3.4. About Qt.


  aboutQtAct = new QAction(tr("About &Qt"), 0, this); 
  aboutQtAct->setStatusTip(tr("Show the Qt library's About box")); 
  connect(aboutQtAct, SIGNAL(activated()), qApp, SLOT(aboutQt())); 
}    
    

Для вызова диалога "AboutQt" используется слот aboutQt() глобальной переменной qApp -- экземпляр класса QApplication.

После создания всех "действий" (action) мы можем разместить их в меню:

void MainWindow::createMenus() 
{ 
  fileMenu = new QPopupMenu(this); 
  newAct->addTo(fileMenu); 
  openAct->addTo(fileMenu); 
  saveAct->addTo(fileMenu); 
  saveAsAct->addTo(fileMenu); 
  fileMenu->insertSeparator(); 
  exitAct->addTo(fileMenu); 
  
  for (int i = 0; i < MaxRecentFiles; ++i) 
    recentFileIds[i] = -1;      
      
В Qt все меню являются экземплярами QPopupMenu. Мы создали меню "File" и затем добавили в него пункты "New", "Open", "Save", "Save As" и "Exit". Перед пунктом "Exit" добавлен разделитель, чтобы визуально отделить его от остальных. Цикл for инициализирует recentFileIds -- массив файлов, открывавшихся недавно. Мы еще вернемся к этому массиву, когда приступим к рассмотрению реализации слотов меню "File" в следующем разделе.
  editMenu = new QPopupMenu(this); 
  cutAct->addTo(editMenu); 
  copyAct->addTo(editMenu); 
  pasteAct->addTo(editMenu); 
  deleteAct->addTo(editMenu); 
  
  selectSubMenu = new QPopupMenu(this); 
  selectRowAct->addTo(selectSubMenu); 
  selectColumnAct->addTo(selectSubMenu); 
  selectAllAct->addTo(selectSubMenu); 
  editMenu->insertItem(tr("&Select"), selectSubMenu); 
  
  editMenu->insertSeparator(); 
  findAct->addTo(editMenu); 
  goToCellAct->addTo(editMenu);      
      
Меню "Edit" включает в себя подменю, которое так же является экземпляром класса QPopupMenu. Мы просто создаем подменю и вставляем его в то место меню "Edit", где оно должно находиться.
  toolsMenu = new QPopupMenu(this); 
  recalculateAct->addTo(toolsMenu); 
  sortAct->addTo(toolsMenu); 
  
  optionsMenu = new QPopupMenu(this); 
  showGridAct->addTo(optionsMenu);      
  autoRecalcAct->addTo(optionsMenu); 
  
  helpMenu = new QPopupMenu(this); 
  aboutAct->addTo(helpMenu); 
  aboutQtAct->addTo(helpMenu); 
  
  menuBar()->insertItem(tr("&File"), fileMenu); 
  menuBar()->insertItem(tr("&Edit"), editMenu); 
  menuBar()->insertItem(tr("&Tools"), toolsMenu); 
  menuBar()->insertItem(tr("&Options"), optionsMenu); 
  menuBar()->insertSeparator(); 
  menuBar()->insertItem(tr("&Help"), helpMenu); 
}  
      
Меню "Tools", "Options" и "Help" создаются аналогичным образом и в конце, все созданные меню вставляются в полосу меню, в верхней части главного окна приложения. Функция QMainWindow::menuBar() возвращает указатель на экземпляр класса QMenuBar, который создается автоматически, при первом вызове menuBar(). Мы добавили разделитель между меню "Options" и "Help". В случае отображения в стиле Motif и ему подобных, меню "Help" смещается в крайнее правое положение, в других стилях отображения разделитель игнорируется.

Рисунок 3.5. Полоса меню в стиле Motif и Windows.


Создание панелей инструментов происходит очень похожим образом:

void MainWindow::createToolBars() 
{ 
  fileToolBar = new QToolBar(tr("File"), this); 
  newAct->addTo(fileToolBar); 
  openAct->addTo(fileToolBar); 
  saveAct->addTo(fileToolBar); 
  
  editToolBar = new QToolBar(tr("Edit"), this); 
  cutAct->addTo(editToolBar); 
  copyAct->addTo(editToolBar); 
  pasteAct->addTo(editToolBar); 
  editToolBar->addSeparator(); 
  findAct->addTo(editToolBar); 
  goToCellAct->addTo(editToolBar); 
}      
      
Мы создали две панели инструментов -- "File" и "Edit". Как и меню, панели инструментов могут включать в себя разделители.

Рисунок 3.6. Панели инструментов приложения Spreadsheet.

Теперь, когда мы закончили создание главного меню и панелей инструментов, добавим контекстное меню.

void MainWindow::contextMenuEvent(QContextMenuEvent *event) 
{ 
  QPopupMenu contextMenu(this); 
  cutAct->addTo(&contextMenu); 
  copyAct->addTo(&contextMenu); 
  pasteAct->addTo(&contextMenu); 
  contextMenu.exec(event->globalPos()); 
}      
      
Когда пользователь щелкает правой кнопкой мыши, то виджету посылается событие (event) "контекстное меню". Перекрывая метод QWidget::contextMenuEvent(), мы можем перехватить это событие и показать контекстное меню в позиции курсора мыши.

Рисунок 3.5. Контекстное меню приложения Spreadsheet.


События, точно так же как сигналы и слоты, являются одним из фундаментальных аспектов программирования в Qt. События рождаются в недрах библиотеки, чтобы сообщить о щелчках мышью, о нажатиях клавиш, о попытках изменения размеров и т.п.. Они могут быть перехвачены и обработаны за счет перекрытия виртуальных функций, как это делается в нашем случае.

Отлавливать событие мы будем в MainWindow потому, что здесь реализуются все наши "действия" (actions). Однако, это событие можно поймать и в виджете Spreadsheet. Когда пользователь щелкнет правой кнопкой мыши по виджету, то этот виджет первым получит событие. Если виджет перекроет реализацию функции contextMenuEvent() и обработает событие, то дальше передаваться оно не будет. В противном случае оно будет передано дальше -- владельцу виджета (MainWindow). Более подробно события будут рассматриваться в Главе 7.

Функция-обработчик события вызова контекстного меню отличается от всего, что мы до сих пор видели, поскольку она создает экземпляр QPopupMenu, размещая его на стеке. Хотя, в принципе, можно было бы создать/удалить этот виджет и с помощью операторов new/delete:

  QPopupMenu *contextMenu = new QPopupMenu(this); 
  cutAct->addTo(contextMenu); 
  copyAct->addTo(contextMenu); 
  pasteAct->addTo(contextMenu); 
  contextMenu->exec(event->globalPos()); 
  delete contextMenu;      
      
Еще один примечательный аспект -- это функция exec(). Она выводит меню на экран, в заданную позицию, и ожидает, пока пользователь не сделает свой выбор, после чего управление возвращается в точку вызова. С этого момента экземпляр QPopupMenu нам больше не нужен, поэтому он удаляется. В случае размещения на стеке -- он будет уничтожен автоматически, по завершении работы функции.

Часть интерфейса, касающуюся меню и панелей инструментов, можно считать завершенной. В следующем разделе мы рассмотрим реализацию слотов меню "File".




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру