(action).
При создании действия указывается родительский элемент и, при необходимости, пиктограмма и/или текстовая метка: QAction::QAction(QObject *parent) QAction::QAction(const QString& text, QObject *parent) QAction::QAction(const QIcon& icon, const QString& text, QObject *parent)
Метод QAction::setStatusTip(текст) определяет текст подсказки по данному действию, выводимую в строке состояния, а QAction::setShortcut(QKeySequence& shortcut) -- привязывает к действию некоторую комбинацию клавиш.
С каждым действием связывается функция-обработчик, для этого используется всё тот же метод connect, например: QAction *exitAction = new QAction(tr("В&ыход"), this); exitAction->setStatusTip(tr("Выход из программы")); exitAction->setShortcut(tr("Ctrl+Q")); connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
Пользователь может влиять на процесс выполнения программы с помощью указателя и кнопок мыши, выбирая нужный пункт меню или кнопку на панели инструментов. Кроме того, в его распоряжении имеются клавиши со стрелками, а также различные клавиатурные комбинации. Все эти события объединены в библиотеке Qt под общим названием
moc, который автоматически формирует на языке C++ необходимый код (в папке проекта после компиляции можно найти файл moc_*.cpp).
1 #include <QtGui>
2 3 class MainWindow : public QMainWindow { 4 Q_OBJECT 5 6 public: 7 MainWindow();
8 9 protected: 10 virtual void resizeEvent(QResizeEvent *event);
11 virtual void mouseMoveEvent(QMouseEvent *event);
12 virtual void closeEvent(QCloseEvent *event);
13 14 private slots: 15 void about();
16 17 private: 18 QAction *aboutAction; 19 QAction *exitAction; 20 QMenu *fileMenu; 21 QLabel *sb1; 22 QLabel *sb2; 23 QLabel *sb3; 24 25 bool askOnClose();
26 };
(1) Подключили заголовочный файл QtGui, в котором описаны все объекты, относящиеся к элементам графического интерфейса. Это проще, чем отдельно подключать QMainWindow, QLabel, QMenu и т.д. (3) Объявили новый класс MainWindow, использовав в качестве базового класс QMainWindow (наследника QObject). (4) Не забыли про обязательный макрос Q_OBJECT. (7) Конструктор без параметров. (10-12) Виртуальные методы, вызываемые автоматически при изменении размеров окна, при перемещении указателя мыши и при закрытии окна. (14-15) Описание слотов (функций-обработчиков). В данном случае здесь упомянута только функция, вызываемая при выборе пункта меню "Опрограмме" (т.к. все остальные обработчики -- это виртуальные функции или уже определённые методы базового класса). (17-23) Переменные-члены класса: два действия для пунктов меню, само меню и три текстовые метки для строки состояния. (25) Служебная функция, вызываемая при закрытии окна (просит подтверждения у пользователя).
1 #include <QtGui>
2 #include "02.h" 3 4 MainWindow::MainWindow() { 5 6 QTextCodec *codec = QTextCodec::codecForName("CP1251");
7 QTextCodec::setCodecForTr(codec);
8 9 aboutAction = new QAction(tr("&О программе"), this);
10 aboutAction->
setStatusTip(tr("Сведения о программе"));
11 connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
12 13 exitAction = new QAction(tr("В&ыход"), this);
14 exitAction->
setStatusTip(tr("Выход из программы"));
15 exitAction->
setShortcut(tr("Ctrl+Q"));
16 connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
17 18 fileMenu = menuBar()->
addMenu(tr("&Файл"));
19 fileMenu->
addAction(aboutAction);
20 fileMenu->
addSeparator();
21 fileMenu->
addAction(exitAction);
22 23 sb1 = new QLabel(statusBar());
24 sb2 = new QLabel(statusBar());
25 sb3 = new QLabel(statusBar());
26 27 statusBar()->
setSizeGripEnabled(false);
28 statusBar()->
addWidget(sb1, 2);
29 statusBar()->
addWidget(sb2, 1);
30 statusBar()->
addWidget(sb3, 1);
31 32 sb1->
setText(tr("Привет!"));
33 34 setMouseTracking(true);
35 } 36 37 38 void MainWindow::resizeEvent(QResizeEvent *event) { 39 QSize sz = event->
size();
40 sb2->
setText( 41 QString( "(%1, %2)" ).arg( sz.width() ).arg( sz.height() ) );
42 } 43 44 void MainWindow::mouseMoveEvent(QMouseEvent *event) { 45 QPoint pos = event->
pos();
46 sb3->
setText( 47 QString( "%1, %2" ).arg( pos.x() ).arg( pos.y() ) );
48 } 49 50 void MainWindow::about() { 51 QMessageBox::about( 52 this, tr("О программе"), 53 tr("<h2>
Простое приложение Qt4</h2>
" 54 "<p>
Окно с меню и строкой состояния"));
55 } 56 57 bool MainWindow::askOnClose() { 58 int r = QMessageBox::question( 59 this, tr("Подтвердите"), 60 tr("Выйти из программы?"), 61 QMessageBox::Yes | QMessageBox::No, 62 QMessageBox::Yes, 63 QMessageBox::Cancel | QMessageBox::Escape);
64 return (r == QMessageBox::Yes);
65 } 66 67 void MainWindow::closeEvent(QCloseEvent *event) { 68 if (askOnClose()) { 69 event->
accept();
70 } else { 71 event->
ignore();
72 } 73 } 74 75 int main(int argc, char *argv[]) { 76 QApplication app(argc, argv);
77 MainWindow mainWin; 78 mainWin.show();
79 return app.exec();
80 }
Горизонтальная панель меню QMenuBar создаётся автоматически, если мы обращаемся к ней для добавления хотя бы одного вертикального меню QMenu. Например: // Определяем действия: QAction *aboutAction = new QAction(tr("&О программе"), this); QAction *exitAction = new QAction(tr("В&ыход"), this);
// Создаём вертикальное меню и добавляем // его на автоматически созданную панель QMenuBar: QMenu *fileMenu = menuBar()->addMenu(tr("&Файл")); fileMenu->addAction(aboutAction); // Добавили действие 'О программе'. fileMenu->addSeparator(); // Разделитель пунктов меню. fileMenu->addAction(exitAction); // Добавили действие 'Выход'. Здесь мы создали меню "Файл" с двумя пунктами "Опрограмме" и "Выход" и горизонтальной полосой-разделителем между ними.
Любые пользовательские классы, разрабатываемые программистом, обычно являются наследниками базового класса QObject (или какого-нибудь из его потомков). Только в этом случае для них можно использовать механизм сигналов и слотов, а также некоторые другие возможности, реализованные в библиотеке Qt (в частности, информацию о типах во время выполнения программы и динамические свойства объектов). При этом необходимо соблюдать следующие правила:
в секции private при объявлении класса необходимо указать макрос Q_OBJECT объявления классов, содержащих макрос Q_OBJECT, обязательно должны располагаться в заголовочном файле *.h, а не в самой программе *.cpp.
Утилита qmake просматривает заголовочные файлы проекта, и если в описании какого-нибудь класса встречается макрос Q_OBJECT, то в make-файл вставляется вызов так называемого
Кроме механизма сигналов и слотов, в Qt используется также старый метод виртуальных функций. Так, например, базовый класс QWidget (элемент интерфейса, виджет) и все его многочисленные потомки имеют виртуальный метод mouseMoveEvent void QWidget::mouseMoveEvent ( QMouseEvent * event ) который вызывается при перемещении указателя мыши над данным элементом. Если требуется определить какую-либо реакцию на это событие, то достаточно в собственном классе переопределить метод mouseMoveEvent. Текущие координаты мыши в системе отсчёта данного виджета можно узнать с помощью методов QMouseEvent::x() и QMouseEvent::y(). Следует иметь в виду, что по умолчанию метод mouseMoveEvent вызывается, только если при перемещении указателя мыши удерживается любая из её кнопок. Чтобы это происходило независимо от состояния кнопок, надо для данного виджета вызвать метод setMouseTracking(true).
Аналогично можно обрабатывать событие изменения размеров любого элемента, только в этом случае для него придётся переопределить метод resizeEvent.
В листингах 6 и 7 приведён текст небольшой программы, в которой иллюстрируются все описанные в данном разделе элементы: меню, строка состояния с несколькими текстовыми полями, обработка перемещения указателя мыши и изменения размеров окна с помощью виртуальных функций, а также определение собственного класса на основе QObject. На рис. показано, как выглядит окно программы в Windows и Linux.

для определения действий, создания меню и других элементов интерфейса.
Строка состояния QStatusBar создаётся автоматически в нижней части главного окна приложения, если в программе хоть раз вызвается метод MainWindow::statusBar. При наведении указателя мыши на кнопку панели инструментов или пункт меню в строке состояния на время появляется текст подсказки, если этот текст определён для данной кнопки или данного пункта.
Указатель на экземпляр QStatusBar можно получить с помощью метода QMainWindow::statusBar(). Чтобы вывести в строке состояния произвольный текст (и затереть предыдущий), используется функция showMessage: void QStatusBar::showMessage( const QString &message, // Выводимая строка. int timeout = 0 ) // Кол-во миллисекунд. Если timeout>0, то сообщение автоматически исчезает через указанный промежуток времени, а на его место возвращается текст предыдущей надписи.
По умолчанию строка состояния представляется в виде одной панели, располагаемой по всей ширине родительского окна. Но её можно разбить по ширине на отдельные поля, если вставить в неё другие элементы, например, QLabel. Для этого предназначены методы addWidget, addPermanentWidget и insertWidget: void QStatusBar::addWidget ( QWidget *widget, // Вставляемый элемент. int stretch = 0 ) // Коэффициент растяжимости.
void QStatusBar::addPermanentWidget ( QWidget *widget, int stretch = 0 )
int QStatusBar::insertWidget ( int index, // Позиция. QWidget *widget, // Вставляемый элемент. int stretch = 0 ) // Коэффициент растяжимости.
Элементы, добавляемые с помощью метода addPermanentWidget, располагаются в правой части строки состояния и не затираются сообщениями, выводимыми с помощью showMessage.
В нижней правой части строки состояния по умолчанию отображается специальный маркер, который можно "зацепить" указателем мыши для изменения размеров окна. Его показ можно запретить, вызвав QStatusBar::setSizeGripEnabled(false). При этом возможность изменять размеры окна по-прежнему остаётся.