[ fromfile: menus.xml id: actions ]
QAction emits signals and connects to slots as needed.
In Qt GUI applications, actions are typically "triggered" in one of the following ways:
A user clicks on a menu choice.
A user presses a shortcut key.
A user clicks on a toolbar button.
There are several overloaded forms of QMenu::addAction()
.
We use the version inherited from QWidget, addAction(QAction*)
, in Example 10.3.
Here you can see how to add actions to menus, action groups, and toolbars.
Example 10.3. src/widgets/menus/study.h
[ . . . . ] class Study : public QMainWindow { Q_OBJECT public: explicit Study(QWidget* parent=0); public slots: void actionEvent(QAction* act); private: QActionGroup* actionGroup; QToolBar* toolbar; QAction* useTheForce; QAction* useTheDarkSide; QAction* studyWithObiWan; QAction* studyWithYoda; QAction* studyWithEmperor; QAction* fightYoda; QAction* fightDarthVader; QAction* fightObiWan; QAction* fightEmperor; protected: QAction* addChoice(QString name, QString text); }; [ . . . . ]
Example 10.4. src/widgets/menus/study.cpp
[ . . . . ] Study::Study(QWidget* parent) : QMainWindow(parent) { actionGroup = new QActionGroup(this); actionGroup->setExclusive(false); statusBar(); QWidget::setWindowTitle( "to become a jedi, you wish?"); QMenu* useMenu = new QMenu("&Use", this); QMenu* studyMenu = new QMenu("&Study", this); QMenu* fightMenu = new QMenu("&Fight", this); useTheForce = addChoice("useTheForce", "Use The &Force"); useTheForce->setStatusTip("This is the start of a journey..."); useTheForce->setEnabled(true); useMenu->addAction(useTheForce); [ . . . . ] studyWithObiWan = addChoice("studyWithObiWan", "&Study With Obi Wan"); studyMenu->addAction(studyWithObiWan); studyWithObiWan->setStatusTip("He will certainly open doors " "for you..."); fightObiWan = addChoice("fightObiWan", "Fight &Obi Wan"); fightMenu->addAction(fightObiWan); fightObiWan->setStatusTip("You'll learn some tricks from him " "that way, for sure!"); [ . . . . ] QMainWindow::menuBar()->addMenu(useMenu); QMainWindow::menuBar()->addMenu(studyMenu); QMainWindow::menuBar()->addMenu(fightMenu); toolbar = new QToolBar("Choice ToolBar", this); toolbar->addActions(actionGroup->actions()); QMainWindow::addToolBar(Qt::LeftToolBarArea, toolbar); QObject::connect(actionGroup, SIGNAL(triggered(QAction*)), this, SLOT(actionEvent(QAction*))); QWidget::move(300, 300); QWidget::resize(300, 300); }
Some of the ClassName:: prefixes used here are not necessary, because the functions can be called on "this". The class names can be used to explicitly call a baser- version, or show the reader which version is called. | |
It's already in a QActionGroup, but we also add it to a QMenu. | |
This gives us visible buttons in a dockable widget for each of the QActions. | |
Instead of connecting each individual action's signal, perform one connect to an actionGroup that contains them all. |
It is possible to connect individual QAction triggered()
signals to individual slots.
In Example 10.5 we group related QAction
s together in a QActionGroup.
If any member of this group is triggered, QActionGroup emits a single signal, triggered(QAction*)
, which makes it possible to handle all of those actions in a uniform way.
Example 10.5. src/widgets/menus/study.cpp
[ . . . . ] // Factory function for creating QActions initialized in a uniform way QAction* Study::addChoice(QString name, QString text) { QAction* retval = new QAction(text, this); retval->setObjectName(name); retval->setEnabled(false); retval->setCheckable(true); actionGroup->addAction(retval); return retval; }
Add every action to a QActionGroup so we need only one signal connected to one slot. |
After being created, each QAction is added to three other objects, (via addAction()
):
A QActionGroup, for signal handling
A QToolBar, where it is rendered as a button
Example 10.6. src/widgets/menus/study.cpp
[ . . . . ] void Study::actionEvent(QAction* act) { QString name = act->objectName(); QString msg = QString(); if (act == useTheForce ) { studyWithObiWan->setEnabled(true); fightObiWan->setEnabled(true); useTheDarkSide->setEnabled(true); } if (act == useTheDarkSide) { studyWithYoda->setEnabled(false); fightYoda->setEnabled(true); studyWithEmperor->setEnabled(true); fightEmperor->setEnabled(true); fightDarthVader->setEnabled(true); } if (act == studyWithObiWan) { fightObiWan->setEnabled(true); fightDarthVader->setEnabled(true); studyWithYoda->setEnabled(true); } [ . . . . ] if (act == fightObiWan ) { if (studyWithEmperor->isChecked()) { msg = "You are victorious!"; } else { msg = "You lose."; act->setChecked(false); studyWithYoda->setEnabled(false); } } [ . . . . ] if (msg != QString()) { QMessageBox::information(this, "Result", msg, "ok"); } }
Because all actions are in a QActionGroup, a single triggered(QAction*)
results in a call to actionEvent()
.
As the user selects from the available choices, other options become enabled or disabled, as shown in Figure 10.2.
QAction stores the state (enabled/checked), and the QMenu and QToolBar provide views of the QAction.
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |