На этой неделе будем заниматься усовершенствованием нашего приложения Qt, созданного ранее (подробнее тут).
Очевидно, что любое приложение должно предоставлять пользователю возможность изменить какие-либо параметры и настройки, сохранить результат работы приложения, посмотреть справочную информацию и т. п. Поэтому сегодня мы займемся созданием меню в Qt. В прошлых статьях мы создали проект, в котором при помощи библиотеки Qwt рисовался график функции y=|x|. Давайте в качестве примера прикрутим меню как раз к этому приложению.
Раз приложение может нарисовать график, то естественно, у пользователя может возникнуть желание сохранить его, чтобы потом без проблем можно было открыть результат своей работы в любом графическом редакторе как обычную картинку. Именно эту возможность мы сейчас и предоставим будущему пользователю нашего приложения 👍
Итак, начнем с того, что создадим в верхней части главного окна приложения пункт меню "File". В файле MainWindow.h объявляем новый член класса MainWindow:
QMenu *fileMenu;
Также добавим два метода в этот класс, чтобы не перегружать кодом конструктор, а просто вызвать там эти методы:
void createMenu(); void createActions();
Первая функция создаст пункты верхнего меню (пока это только пункт File), а вторая создаст QAction, то есть в данном примере подпункт Save, при нажатии на который произойдет сохранение графика.
void MainWindow::createMenu() { fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(saveAction); } void MainWindow::createActions() { saveAction = new QAction(tr("&Save"), this); connect(saveAction, SIGNAL(activated()), this, SLOT(showSaveMenu())); }
Мы привязали сигнал activated() объекта saveAction к слоту showSaveMenu() объекта MainWindow. Другими словами, при выборе пункта меню Save произойдет вызов функции showSaveMenu(). В конструктор класса MainWindow добавим вызовы:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); createActions(); createMenu(); // Далее идет код нашего приложения из предыдущих статей 🙂
Теперь пришло время реализовать слот showSaveMenu(). В файле MainWindow.h объявляем:
public slots: void showSaveMenu();
И в файле MainWindow.c пишем:
void MainWindow::showSaveMenu() { QString filename = QFileDialog::getSaveFileName(this, tr("Save Document"), QDir::currentPath(), tr("Images (*.JPG)")); QPixmap plotToPix; plotToPix = QPixmap::grabWidget(this->plot); plotToPix.save(filename, "JPG"); }
Алгоритм тут следующий... Создаем объект класса QString для хранения имени сохраняемого файла. Это имя будет получено в результате вызова диалогового окна сохранения файла:
QFileDialog::getSaveFileName(this, tr("Save Document"), QDir::currentPath(), tr("Images (*.JPG)"));
Параметры – название диалогового окна, путь и формат. Мы будем сохранять файл в jpg. Дальше мы объявляем объект plotToPix. Он нам нужен для того, чтобы непосредственно произвести сохранение. Сначала сохраняем график (объект plot) в объекте класса QPixmap, а затем уже сохраняем картинку вызовом функции save(). Вот собственно и все! Можно запустить и посмотреть, что получилось в итоге:
С сохранением разобрались, теперь давайте добавим еще один пункт меню – Help и подпункт About. При выборе этого пункта будет открываться новое окно с информацией о приложении. Для примера добавим в это окно какой-нибудь текст и тестовое изображение.
Делать все будем немного иначе по сравнению с меню сохранения файла. Добавим два новых файла в наш проект – menuclass.h и menuclass.cpp. Там мы реализуем класс окна, которое будет появляться при выборе пункта About в меню Help. А назовем мы этот класс InfoWindow. Вот полный код:
- Файл menuclass.h:
class InfoWindow : public QWidget { Q_OBJECT public: explicit InfoWindow(QWidget *parent = 0); signals: void activated(int i); public slots: private: QPixmap *aboutWindowPix; QLabel *aboutWindowLabel; QLabel *aboutWindowPixLabel; };
- Файл menuclass.cpp:
#include "menuclass.h" InfoWindow::InfoWindow(QWidget *parent) : QWidget(parent) { this->setWindowTitle("About"); aboutWindowLabel = new QLabel("Info"); aboutWindowPix = new QPixmap(); aboutWindowPix->load(":images/testpicture.JPG"); aboutWindowPixLabel = new QLabel(); aboutWindowPixLabel->setPixmap(*aboutWindowPix); QVBoxLayout *aboutWindowLayout = new QVBoxLayout(); aboutWindowLayout->addWidget(aboutWindowPixLabel); aboutWindowLayout->addWidget(aboutWindowLabel); this->setLayout(aboutWindowLayout); this->resize(100,200); }
Давайте разбираться по порядку... Наше окно будет содержать текст и картинку, соответственно добавляем в класс три поля:
QPixmap *aboutWindowPix; QLabel *aboutWindowLabel; QLabel *aboutWindowPixLabel;
Не забываем объявить сигнал, ведь нам нужно как то реагировать на выбор пункта меню:
signals: void activated(int i);
Идем в конструктор класса. Для начала даем имя нашему окну:
this->setWindowTitle("About");
Создаем два объекта класса QLabel – в один поместим наш текст, а в другой - нашу картинку. Саму картинку мы поместим в папку images, которую в свою очередь создадим в папке с проектом. Загружаем картинку в объект aboutWindowPix:
aboutWindowPix->load(":images/testpicture.JPG");
Но тут не все так просто. Приложение то соберется, вот только картинки там не окажется. А чтобы все стало на свои места нужно добавить к проекту файл ресурсов:
Открываем файл ресурсов в блокноте и прописываем туда путь к нашей картинке, например:
Вот теперь изображение появится, где надо, продолжаем… Устанавливаем объект aboutWindowPix в качестве Pixmap для aboutWindowPixLabel:
aboutWindowPixLabel->setPixmap(*aboutWindowPix);
Располагаем два объекта класса QLabel друг над другом:
QVBoxLayout *aboutWindowLayout = new QVBoxLayout(); aboutWindowLayout->addWidget(aboutWindowPixLabel); aboutWindowLayout->addWidget(aboutWindowLabel); this->setLayout(aboutWindowLayout);
Задаем размер окна и собственно все, окно информации готово! Осталось создать соответствующий пункт меню, как в случае с сохранением графика в начале статьи. Дополняем код функций createActions() и createMenu():
void MainWindow::createMenu() { fileMenu = menuBar()->addMenu(tr("&File")); helpMenu = menuBar()->addMenu(tr("&Help")); fileMenu->addAction(saveAction); helpMenu->addAction(aboutAction); } void MainWindow::createActions() { saveAction = new QAction(tr("&Save"), this); connect(saveAction, SIGNAL(activated() ), this, SLOT(showSaveMenu())); aboutAction = new QAction(tr("&About"), this); connect(aboutAction, SIGNAL( activated() ), this, SLOT(showInfo())); }
Тут все аналогично созданию меню File - Save, так что двигаемся дальше. Мы привязали к выбору пункта About слот showInfo(), вот его нам и осталось реализовать:
void MainWindow::showInfo() { InfoWindow *info = new InfoWindow(); info->setVisible(true); }
Вот и все, просто создаем объект нашего класса InfoWindow и делаем его видимым, собираем проект и пробуем запустить:
C:\Users\velichanskij\Documents\Menu\mainwindow.cpp:21: ошибка: C2065: saveAction: необъявленный идентификатор
В MainWindow.h нужно определить saveAction.
QAction *saveAction;
Спасибо, я уже разобрался)