Разработка графического интерфейса с помощью библиотеки Qt3 | ||
---|---|---|
Пред. | Глава 3. Создание главного окна приложения | След. |
Большинство современных приложений имеют как меню, так и панели инструментов, которые содержат более или менее идентичный набор команд. Меню дают пользователю возможность заняться "исследованием" приложения, изучать доступные команды, а панели инструментов служат для быстрого доступа к командам, используемым наиболее часто.
Qt значительно упрощает разработку меню и панелей инструментов за счет использования концепции "действия" (action). Action -- это элемент, который может быть добавлен в меню и/или на панель инструментов. Для создания меню и панели инструментов необходимо выполнить следующие шаги:
Создать "действие" (action).
Добавить его в меню.
Добавить его на панель инструментов.
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".
Пред. | В начало | След. |
Создание главного окна приложения | На уровень выше | Реализация меню "File". |