На этой неделе будем заниматься усовершенствованием нашего приложения 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;
Спасибо, я уже разобрался)