This example will show how to create a user application which contains a top level menu. Adding a menu bar with icons and shortcuts is the next step in creating a graphical application.
#include <QtCore>
#include <QtGui>
class MainWindow : public QMainWindow
{
public:
MainWindow();
private:
void showAboutJournal();
};
In our prior examples the MainWindow class inherited from QWidget, which works well for a basic window. Adding a top level menu requires that our class inherit from QMainWindow, which is part of the CsGui library. The QMainWindow class provides methods to support the components of the main window in a GUI application. This example will be using several of these methods to define what actions should be taken when a user selects a given menu option.
Our MainWindow class declaration has one public constructor and one private slot method.
MainWindow::MainWindow()
{
setMinimumSize(700, 500);
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
// *
QAction *openFile = new QAction("Open", this);
openFile->setShortcuts(QKeySequence::Open);
openFile->setIcon(QIcon("../file_open.png"));
QAction *closeFile = new QAction("Close", this);
closeFile->setIcon(QIcon("../file_close.png"));
QAction *saveFile = new QAction("Save", this);
saveFile->setShortcuts(QKeySequence::Save);
saveFile->setIcon(QIcon("../file_save.png"));
QAction *exit = new QAction("Exit", this);
connect(exit, &QAction::triggered, this, &QWidget::close);
#ifdef Q_OS_WIN
exit->setShortcut(QKeySequence(Qt::AltModifier|Qt::Key_F4));
#else
exit->setShortcuts(QKeySequence::Quit);
#endif
// *
QAction *undo = new QAction("Undo", this);
undo->setIcon(QIcon("../undo.png"));
QAction *redo = new QAction("Redo", this);
redo->setIcon(QIcon("../redo.png"));
QAction *cut = new QAction("Cut", this);
cut->setIcon(QIcon("../cut.png"));
QAction *copy = new QAction("Copy", this);
copy->setIcon(QIcon("../copy.png"));
QAction *paste = new QAction("Paste", this);
paste->setIcon(QIcon("../paste.png"));
QAction *about = new QAction("About Journal", this);
connect(about, &QAction::triggered,
this, &MainWindow::showAboutJournal);
QMenu *fileMenu = menuBar()->addMenu("File");
fileMenu->addAction(openFile);
fileMenu->addAction(closeFile);
fileMenu->addAction(saveFile);
fileMenu->addSeparator();
fileMenu->addAction(exit);
QMenu *editMenu = menuBar()->addMenu("Edit");
editMenu->addAction(undo);
editMenu->addAction(redo);
editMenu->addSeparator();
editMenu->addAction(cut);
editMenu->addAction(copy);
editMenu->addAction(paste);
QMenu *helpMenu = menuBar()->addMenu("Help");
helpMenu->addAction(about);
// *
QPushButton *pb_close = new QPushButton();
pb_close->setText("Close");
QHBoxLayout *layout = new QHBoxLayout();
layout->addStretch();
layout->addWidget(pb_close);
layout->addStretch();
centralWidget->setLayout(layout);
connect(pb_close, &QPushButton::clicked,
this, &QWidget::close);
}
The QMainWindow class requires a central widget on every main window. On line 5 a new QWidget object is created and then on line 6 a pointer to this widget is passed to the method setCentralWidget(). There are other classes which can be used as the central widget such as QTextEdit.
Starting on line 9 and continuing through line 43, the actions which will be taken when a particular menu item is selected by the user, are created. As an example, on line 16 the action for save file is constructed. The pointer saveFile is declared and a new QAction is created which defines the name of the menu item.
A shortcut for “Save” is set on line 17 by passing an enum value. The value of QKeySequence::Save will set the shortcut to Ctrl+S on every platform. Something like QKeySequence::FindNext will set the shortcut to F3 or Ctrl+G depending on the user’s operating system. On line 18 an icon is set and is displayed adjacent to the menu item.
On lines 23 through 27 we have an interesting situation. The Windows platform does not define a standard shortcut for the Exit action. This code shows how to set up a shortcut key sequence when there is nothing defined or when an alternative shortcut is needed for your specific application.
The code shown on lines 49 through 65 sets up the menu. Top level menus for File, Edit, and Help are added and then followed by the menu items. Let’s look at the first call to menuBar()->addMenu() on line 49. The method menuBar() in QMainWIndow returns a pointer to the QMenuBar for our main window. The call to QMenuBar::addMenu() creates a new top level menu with the given name and returns a pointer to a new QMenu.
The other code like line 50, calls QMenu::addAction() and will pass a pointer to the QAction which was previously defined.
The remaining code sets up a push button to close the application. This button is added to a horizontal layout. In previous example the layout was added directly to the main window. This was fine since the main window was a QWidget. In this example we need to add our new layout to the central widget as shown on line 76.
Signal / Slot Connections
Line 46 in the code shown above contains a call to connect(). This sets up what action should be taken when the user selects the “Help”, “About Journal” menu item. The following slot method is called and displays a message box for the user.
void MainWindow::showAboutJournal()
{
QMessageBox::about(this, "About Journal",
"Text which typically contains the Developer "
"or Organization Name, Version Number, and "
"Copyright details.");
}
Main Function
Since the source code for main() has not changed there is no need to show it again. Refer to example 3 or download the full source for this example.
Running the Example
To build and run this example use the same CMake build file and commands as we showed for the first example. The only suggested modification is on line 2 of the CMakeLists.txt file, change “example_1” to “example_26”.