Назад Содержание Вперед

Меню и строка состояния

Строка состояния

Строка состояния 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). При этом возможность изменять размеры окна по-прежнему остаётся.

Действия

Пользователь может влиять на процесс выполнения программы с помощью указателя и кнопок мыши, выбирая нужный пункт меню или кнопку на панели инструментов. Кроме того, в его распоряжении имеются клавиши со стрелками, а также различные клавиатурные комбинации. Все эти события объединены в библиотеке Qt под общим названием действие (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()));

Меню

Горизонтальная панель меню 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);  // Добавили действие 'Выход'.
Здесь мы создали меню "Файл" с двумя пунктами "О программе" и "Выход" и горизонтальной полосой-разделителем между ними.

Обработка событий с помощью виртуальных методов

Кроме механизма сигналов и слотов, в Qt используется также старый метод виртуальных функций. Так, например, базовый класс QWidget (элемент интерфейса, виджет) и все его многочисленные потомки имеют виртуальный метод mouseMoveEvent
void QWidget::mouseMoveEvent ( QMouseEvent * event )
который вызывается при перемещении указателя мыши над данным элементом. Если требуется определить какую-либо реакцию на это событие, то достаточно в собственном классе переопределить метод mouseMoveEvent. Текущие координаты мыши в системе отсчёта данного виджета можно узнать с помощью методов QMouseEvent::x() и QMouseEvent::y(). Следует иметь в виду, что по умолчанию метод mouseMoveEvent вызывается, только если при перемещении указателя мыши удерживается любая из её кнопок. Чтобы это происходило независимо от состояния кнопок, надо для данного виджета вызвать метод setMouseTracking(true).

Аналогично можно обрабатывать событие изменения размеров любого элемента, только в этом случае для него придётся переопределить метод resizeEvent.

Наследники класса QObject и метакомпилятор

Любые пользовательские классы, разрабатываемые программистом, обычно являются наследниками базового класса QObject (или какого-нибудь из его потомков). Только в этом случае для них можно использовать механизм сигналов и слотов, а также некоторые другие возможности, реализованные в библиотеке Qt (в частности, информацию о типах во время выполнения программы и динамические свойства объектов). При этом необходимо соблюдать следующие правила:

Утилита qmake просматривает заголовочные файлы проекта, и если в описании какого-нибудь класса встречается макрос Q_OBJECT, то в make-файл вставляется вызов так называемого компилятора метаобъектов moc, который автоматически формирует на языке C++ необходимый код (в папке проекта после компиляции можно найти файл moc_*.cpp).

Пример приложения с меню и строкой состояния

В листингах 6 и 7 приведён текст небольшой программы, в которой иллюстрируются все описанные в данном разделе элементы: меню, строка состояния с несколькими текстовыми полями, обработка перемещения указателя мыши и изменения размеров окна с помощью виртуальных функций, а также определение собственного класса на основе QObject. На рис. показано, как выглядит окно программы в Windows и Linux.


Рис. Меню и строка состояния: внешний вид окна программы в системе Windows (верхний скриншот) и Linux (для двух различных тем рабочего стола). В строке состояния отображаются размеры окна и координаты указателя мыши

Листинг 6. Меню и строка состояния (файл examples-qt/02/02.h)

    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 };
Листинг 7. Меню и строка состояния (файл examples-qt/02/02.cpp)
    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 }

Чуть позже мы узнаем, как использовать программу Qt Designer для определения действий, создания меню и других элементов интерфейса.

Назад Содержание Вперед