#(8):添加動作
本節,我們將在前面主窗口基礎之上,添加菜單和工具欄等的動作。雖然 Qt Creator 已經幫我們實現了主窗口的框架代碼,但是具體的功能,還是需要我們一行行添加。
Qt 使用`QAction`類作為動作。顧名思義,這個類就是代表了窗口的一個“動作”,這個動作可能顯示在菜單,作為一個菜單項,當用戶點擊該菜單項,對用戶的點擊做出響應;也可能在工具欄,作為一個工具欄按鈕,用戶點擊這個按鈕就可以執行相應的操作。有一點值得注意:無論是出現在菜單欄還是工具欄,用戶選擇之后,所執行的動作應該都是一樣的。因此,Qt 并沒有專門的菜單項類,只是使用一個`QAction`類,抽象出公共的動作。當我們把`QAction`對象添加到菜單,就顯示成一個菜單項,添加到工具欄,就顯示成一個工具按鈕。用戶可以通過點擊菜單項、點擊工具欄按鈕、點擊快捷鍵來激活這個動作。
`QAction`包含了圖標、菜單文字、快捷鍵、狀態欄文字、浮動幫助等信息。當把一個`QAction`對象添加到程序中時,Qt 自己選擇使用哪個屬性來顯示,無需我們關心。同時,Qt 能夠保證把`QAction`對象添加到不同的菜單、工具欄時,顯示內容是同步的。也就是說,如果我們在菜單中修改了`QAction`的圖標,那么在工具欄上面這個`QAction`所對應的按鈕的圖標也會同步修改。
下面我們來看看如何在`QMainWindow`中使用`QAction`:
~~~
// !!! Qt 5
// ========== mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
void open();
QAction *openAction;
};
#endif // MAINWINDOW_H
// ========== mainwindow.cpp
#include <QAction>
#include <QMenuBar>
#include <QMessageBox>
#include <QStatusBar>
#include <QToolBar>
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setWindowTitle(tr("Main Window"));
openAction = new QAction(QIcon(":/images/doc-open"), tr("&Open..."), this);
openAction->setShortcuts(QKeySequence::Open);
openAction->setStatusTip(tr("Open an existing file"));
connect(openAction, &QAction::triggered, this, &MainWindow::open);
QMenu *file = menuBar()->addMenu(tr("&File"));
file->addAction(openAction);
QToolBar *toolBar = addToolBar(tr("&File"));
toolBar->addAction(openAction);
statusBar() ;
}
MainWindow::~MainWindow()
{
}
void MainWindow::open()
{
QMessageBox::information(this, tr("Information"), tr("Open"));
}
~~~
上面的代碼分別屬于兩個文件:mainwindow.h 和 mainwindow.cpp。為了讓 MainWindow 運行起來,我們還需要修改 main() 函數如下:
~~~
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow win;
win.show();
return app.exec();
}
~~~
當我們編輯好文件,點擊運行,可以看到`MainWindow`的運行結果:
[](http://files.devbean.net/images/2012/08/mw-action.png)
這是一個相對完整的程序。首先,我們在`MainWindow`類中添加了一個私有函數`open()`和一個私有變量`openAction`。在 MainWindow 的構造函數中,第一行我們調用了`setWindowTitle()`,設置主窗口的標題。注意我們的文本使用`tr()`函數,這是一個用于 Qt 國際化的函數。在后續章節中我們可以看到,我們可以使用 Qt 提供的國際化工具,將`tr()`函數的字符串提取出來,進行國際化。由于所需進行國際化的文本應該被大多數人認識,所以,`tr()`函數里面一般會是英文文本。
然后,我們在堆上創建了`openAction`對象。在`QAction`構造函數,我們傳入了一個圖標、一個文本和 this 指針。我們將在后面的文章中解釋 this 指針的含義。
圖標我們使用了`QIcon`,傳入值是一個字符串,這個字符串對應于 Qt 資源文件中的一段路徑。Qt 資源文件的后綴名是 qrc。如果我們使用 Qt Creator,我們可以在新建文件中看到 Qt 資源文件。Qt 資源文件其實是一個 XML 描述的文件,表示 Qt 應用程序所需要的各個資源。我們可以使用普通文本編輯器打開這個文件:
~~~
<RCC>
<qresource prefix="/images">
<file alias="doc-open">document-open.png</file>
</qresource>
</RCC>
~~~
我們會在后面的章節中詳細介紹 Qt 資源文件(注意,資源文件需要在 pro 文件中使用 RESOURCES 引入。)。這里只需要了解,`QIcon`的參數,以 : 開始,意味著從資源文件中查找資源。`:/images/doc-open`就是找到了這里的 document-open.png 這個文件。*(我們使用的是 png 格式的圖片,這是 Qt 內置支持的圖片格式。其他格式的圖片,比如 jpg、gif 則需要插件支持。這些插件實際已經隨著 Qt 一同發布。)*
`QAction`第二個參數中,文本值前面有一個 &,意味著這將成為一個快捷鍵。注意看截圖中 File 的 F 有一個下劃線。
下面一句,我們使用了`setShortcut()`函數,用于說明這個`QAction`的快捷鍵。Qt 的`QKeySequence`為我們定義了很多內置的快捷鍵,比如我們使用的 Open。你可以通過查閱 API 文檔獲得所有的快捷鍵列表。 這個與我們自己定義的有什么區別呢?簡單來說,我們完全可以自己定義一個`tr("Ctrl+O")`來實現快捷鍵。原因在于,這是 Qt 跨平臺性的體現。比如 PC 鍵盤和 Mac 鍵盤是不一樣的,一些鍵在 PC 鍵盤上有,而 Mac 鍵盤上可能并不存在,或者反之。使用`QKeySequence`類來添加快捷鍵,會根據平臺的不同來定義相應的快捷鍵。
`setStatusTip()`則實現了當用戶鼠標滑過這個 action 時,會在主窗口下方的狀態欄顯示相應的提示。
后面的`connect()`函數,將這個`QAction`的`triggered()`信號與`MainWindow`類的`open()`函數連接起來。當用戶點擊了這個`QAction`時,會自動觸發`MainWindow`的`open()`函數。這是我們之前已經了解過的。
下面的`menuBar()`、`toolBar()`和`statusBar()`三個是`QMainWindow`的函數,用于創建并返回菜單欄、工具欄和狀態欄。我們可以從代碼清楚地看出,我們向菜單欄添加了一個 File 菜單,并且把這個`QAction`對象添加到這個菜單;同時新增加了一個 File 工具欄,也把`QAction`對象添加到了這個工具欄。我們可以看到,在菜單中,這個對象被顯示成一個菜單項,在工具欄變成了一個按鈕。至于狀態欄,則是出現在窗口最下方,用于顯示動作對象的提示信息的。
至于`open()`函數中的內容,我們會在后文介紹。這里可以運行一下,你會看到,觸發這個動作,程序會彈出一個提示框。
下面是 Qt 4 版本的程序,具體非常類似,這里不再贅述。
~~~
// !!! Qt 4
// ========== mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void open();
private:
QAction *openAction;
};
#endif // MAINWINDOW_H
// ========== mainwindow.cpp
#include <QAction>
#include <QMenuBar>
#include <QMessageBox>
#include <QToolBar>
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setWindowTitle(tr("Main Window"));
openAction = new QAction(QIcon(":/images/doc-open"), tr("&Open..."), this);
openAction->setShortcuts(QKeySequence::Open);
openAction->setStatusTip(tr("Open an existing file"));
connect(openAction, SIGNAL(triggered()), this, SLOT(open()));
QMenu *file = menuBar()->addMenu(tr("&File"));
file->addAction(openAction);
QToolBar *toolBar = addToolBar(tr("&File"));
toolBar->addAction(openAction);
statusBar();
}
MainWindow::~MainWindow()
{
}
void MainWindow::open()
{
QMessageBox::information(this, tr("Information"), tr("Open"));
}
~~~
- (1)序
- (2)Qt 簡介
- (3)Hello, world!
- (4)信號槽
- (5)自定義信號槽
- (6)Qt 模塊簡介
- (7)MainWindow 簡介
- (8)添加動作
- (9)資源文件
- (10)對象模型
- (11)布局管理器
- (12)菜單欄、工具欄和狀態欄
- (13)對話框簡介
- (14)對話框數據傳遞
- (15)標準對話框 QMessageBox
- (16)深入 Qt5 信號槽新語法
- (17)文件對話框
- (18)事件
- (19)事件的接受與忽略
- (21)事件過濾器
- (22)事件總結
- (23)自定義事件
- (24)Qt 繪制系統簡介
- (25)畫刷和畫筆
- (26)反走樣
- (27)漸變
- (28)坐標系統
- (29)繪制設備
- (30)Graphics View Framework
- (31)貪吃蛇游戲(1)
- (32)貪吃蛇游戲(2)
- (33)貪吃蛇游戲(3)
- (34)貪吃蛇游戲(4)
- (35)文件
- (36)二進制文件讀寫
- (37)文本文件讀寫
- (38)存儲容器
- (39)遍歷容器
- (40)隱式數據共享
- (41)model/view 架構
- (42)QListWidget、QTreeWidget 和 QTableWidget
- (43)QStringListModel
- (44)QFileSystemModel
- (45)模型
- (46)視圖和委托
- (47)視圖選擇
- (48)QSortFilterProxyModel
- (49)自定義只讀模型
- (50)自定義可編輯模型
- (51)布爾表達式樹模型
- (52)使用拖放
- (53)自定義拖放數據
- (54)剪貼板
- (55)數據庫操作
- (56)使用模型操作數據庫
- (57)可視化顯示數據庫數據
- (58)編輯數據庫外鍵
- (59)使用流處理 XML
- (60)使用 DOM 處理 XML
- (61)使用 SAX 處理 XML
- (62)保存 XML
- (63)使用 QJson 處理 JSON
- (64)使用 QJsonDocument 處理 JSON
- (65)訪問網絡(1)
- (66)訪問網絡(2)
- (67)訪問網絡(3)
- (68)訪問網絡(4)
- (69)進程
- (70)進程間通信
- (71)線程簡介
- (72)線程和事件循環
- (73)Qt 線程相關類
- (74)線程和 QObject
- (75)線程總結
- (76)QML 和 QtQuick 2
- (77)QML 語法
- (78)QML 基本元素
- (79)QML 組件
- (80)定位器
- (81)元素布局
- (82)輸入元素
- (83)Qt Quick Controls
- (84)Repeater
- (85)動態視圖
- (86)視圖代理
- (87)模型-視圖高級技術
- (88)Canvas
- (89)Canvas(續)