一、QAction類詳解
【詳細描述】
??????? QAction類提供了抽象的用戶界面action,這些action可以被放置在窗口部件中。
??????? 應用程序可以通過菜單,工具欄按鈕以及鍵盤快捷鍵來調用通用的命令。由于用戶期望每個命令都能以相同的方式執行,而不管命令所使用的用戶界面,
這個時候使用action來表示這些命令就顯得十分有用。
???????? Actions可以被添加到菜單和工具欄中,并且可以自動保持在菜單和工具欄中的同步。例如,在一個字處理軟件中,如果用戶在工具欄中按下了Bold按鈕,那么菜單中的Bold選項就會自動被選中。
???????? Actions可以作為獨立的對象被創建,但是我們也可以在構建菜單的時候創建它們;QMenu類包含了非常簡便的方法用于創建適合用作菜單項的actions。
?????? QAction可以包括一個圖標,菜單文本,快捷鍵,狀態文本,"What`s This"文本以及一個tooltip。這些內容的絕大部分都可以在構造函數中設置。也可以通過setIcon(),setIconText(),setShortCut(),setStatusTip(),setWhatsThis和SetToolTip()函數分別設置。對于菜單項,我們還可以通過
setFont()單獨為它們設置font。
?????? 可以通過QWidget::addAction()或者是QGraphicsWidget::addAction()函數將Actions添加到窗口部件上。注意,只有將Actions添加到窗口部件上之后,我們才可以使用這些actions;當actions的快捷鍵是全局的時候,我們也必須先將actions添加到窗口部件上。
?????? 一旦QAction被創建了,那么就必須將它添加到相關的菜單和工具欄上,然后將它們鏈接到實現相應action功能的槽函數上。例如:
openAct = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this);
openAct->setShortcuts(QKeySequence::Open);
openAct->setStatusTip(tr("Open an existing file"));
connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
fileMenu->addAction(openAct);
fileToolBar->addAction(openAct);
???? 我們建議將actions作為使用它們的窗口的孩子創建。在絕大多數情況下,actions都是應用程序主窗口的孩子。
?????? 類的枚舉成員變量:
這個枚舉類型主要是在調用QAction::activate()函數的時候被使用到。我們來看看QAction::activate()函數的原型:
???????? 從上面可以看出,我們使用該函數發射信號,而參數event則指明了發射的信號類型。基于action的widgets可以自己發射信號,然而我們也可以顯式的調用本API來發射信號。
??????? 由于Mac OS X系統的一些特性,Qt 會對一些菜單項進行自動排列。比如,如果你的菜單是“關于”、“設置”、“首選項”、“退出”等等,我們可以給它們分配一個角色,Qt 則會根據這些角色對菜單項的順序作出正確的排列。方法是,設置 QAction::menuRole 屬性,例如:AboutRole、PreferencesRole、QuitRole 或者 NoRole。舉例
來說,我們可以將“設置”菜單項作為 Mac OS X 的 Application::preferences。
???????? QAction::MenuRole類型的枚舉主要描述了在Mac OS X系統上,action如何移動到應用程序的菜單上。設置這個值只對菜單上的直接菜單有效,對子菜單無效。例如:如果有一個File菜單,該File菜單又包含有子菜單,那么如果你針對子菜單設置這些值,那么這些值永遠不會起作用。
?????????? 該優先級用于表明action在用戶界面上的優先級。例如,當你的工具欄設置了Qt::ToolButtonTextBesideIcon模式,那么低優先級的actions將不會顯示出標簽。
【示例】
(1) 使用Action構造工具欄和菜單欄
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
initMenu();
initToolBar();
}
void MainWindow::initMenu()
{
/* 初始化File菜單 */
fileMenu = new QMenu(tr("File"), this);
fileOpenAction = new QAction("&Open...", this);
fileSaveAction = new QAction("&Save...", this);
fileMenu->addAction(fileOpenAction);
fileMenu->addAction(fileSaveAction);
/* 初始化Edit菜單 */
editMenu = new QMenu("&Edit");
editCopyAction = editMenu->addAction("&Copy");
editCutAction = editMenu->addAction("&Cut");
/* 將菜單添加到菜單欄上 */
QMenuBar *menuBar = this->menuBar();
menuBar->addMenu(fileMenu);
menuBar->addMenu(editMenu);
}
void MainWindow::initToolBar()
{
/* 初始化FileToolBar */
fileToolBar = new QToolBar(this);
fileToolBar->addAction(fileOpenAction);
fileToolBar->addAction(fileSaveAction);
/* 初始化EditToolBar */
editToolBar = new QToolBar(this);
editToolBar->addAction(editCopyAction);
editToolBar->addAction(editCutAction);
/* 將工具添加到工具欄上 */
addToolBar(Qt::TopToolBarArea, fileToolBar);
addToolBar(Qt::TopToolBarArea, editToolBar);
}
MainWindow::~MainWindow()
{
}
(2)測試QAction::activate(QAction::ActionEvent)
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
initMenu();
initToolBar();
initConnect();
}
void MainWindow::initConnect()
{
connect(fileOpenAction, SIGNAL(triggered()),
this, SLOT(sendActivate()));
connect(fileSaveAction, SIGNAL(hovered()),
this, SLOT(ansHovered()));
}
void MainWindow::sendActivate()
{
/* 這將會導致fileSaveAction發送信號QAction::hovered() */
fileSaveAction->activate(QAction::Hover);
}
void MainWindow::ansHovered()
{
qDebug("Ans!!!");
}
運行結果:
(3)測試QAction::Priority
void MainWindow::initMenu()
{
/* 初始化File菜單 */
fileMenu = new QMenu(tr("File"), this);
fileOpenAction = new QAction("&Open...", this);
fileSaveAction = new QAction("&Save...", this);
fileMenu->addAction(fileOpenAction);
fileMenu->addAction(fileSaveAction);
/* 初始化Edit菜單 */
editMenu = new QMenu("&Edit");
editCopyAction = editMenu->addAction("&Copy");
editCutAction = editMenu->addAction(QIcon(":/cut.PNG"), "&Cut");
//editCutAction->setPriority(QAction::LowPriority);
/* 將菜單添加到菜單欄上 */
QMenuBar *menuBar = this->menuBar();
menuBar->addMenu(fileMenu);
menuBar->addMenu(editMenu);
}
void MainWindow::initToolBar()
{
/* 初始化FileToolBar */
fileToolBar = new QToolBar(this);
fileToolBar->addAction(fileOpenAction);
fileToolBar->addAction(fileSaveAction);
/* 初始化EditToolBar */
editToolBar = new QToolBar(this);
editToolBar->addAction(editCopyAction);
editToolBar->addAction(editCutAction);
/* 將工具添加到工具欄上 */
addToolBar(Qt::TopToolBarArea, fileToolBar);
addToolBar(Qt::TopToolBarArea, editToolBar);
/* 設置工具欄為QT::ToolButtonTextBesideIcon */
this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
}
此時注釋掉了設置優先級的語句,圖標和文字均能顯示出來,效果如下圖:
取消上面的注釋;
/* 初始化Edit菜單 */
editMenu = new QMenu("&Edit");
editCopyAction = editMenu->addAction("&Copy");
editCutAction = editMenu->addAction(QIcon(":/cut.PNG"), "&Cut");
editCutAction->setPriority(QAction::LowPriority);
運行效果如下:
二、QActionGroup類詳解
【詳細描述】
??????? QActionGroup類將actions分組。
?????? 在某些情況下將QAction分組是十分有用的。例如,如果你有一個Left Align的action,一個Right Align的action,一個Justify的action,
以及一個Center action,在統一時刻所有這些actions只能有一個被激活。一種簡便的做法就是將這些actions以分組的方式組織。
下面是一個示例:
alignmentGroup = new QActionGroup(this);
alignmentGroup->addAction(leftAlignAct);
alignmentGroup->addAction(rightAlignAct);
alignmentGroup->addAction(justifyAct);
alignmentGroup->addAction(centerAct);
leftAlignAct->setChecked(true);
??????? 在上面的示例中,我們創建了一個action組。由于action group默認是互斥的,因此在同一時刻只有一個會被選中。
??????? 當組內的某個action被選中的時候,QActionGroup就會發射triggered()信號。通常情況下,組內的每個action發射自己的triggered()信號。
??????? 正如上面提到的,action group默認是互斥的;它確保在同一時刻只有一個action會被選中。如果你想創建一個action group而不想時它們是互斥關系,那么你可以通過調用setExclusive(false)來關閉互斥關系。
??????? 可以使用addAction()函數將action添加到action group中,然而更常見的做法是在創建action的時候指定一個group;這確保了這些actions具有同一個父親。可以通過在group中添加分割線使得各個action分開顯示,可以使用QAction的setSeparator()添加分割線。通常使用QWidget::addActions()函數將action group添加到窗口部件上。
【示例】
/* 初始化Action菜單 */
actionMenu = new QMenu("Action");
leftAction = new QAction("Left", this);
rightAction = new QAction("Right", this);
centerAction = new QAction("Center", this);
justifyAction = new QAction("Justify", this);
actionGroup = new QActionGroup(this);
actionMenu->addAction(actionGroup->addAction(leftAction));
actionMenu->addAction(actionGroup->addAction(rightAction));
actionMenu->addAction(actionGroup->addAction(centerAction));
actionMenu->addAction(actionGroup->addAction(justifyAction));
可以使用下面的槽函數驗證默認情況下,一次只有一個action可以被選中。當然也可以設置action的
bool
isExclusive () const
為false,使得一次可以選中多個:
void MainWindow::initConnect()
{
connect(fileOpenAction, SIGNAL(triggered()),
this, SLOT(sendActivate()));
connect(fileSaveAction, SIGNAL(hovered()),
this, SLOT(ansHovered()));
connect(leftAction, SIGNAL(triggered()),
this, SLOT(ansTriggered()));
connect(rightAction, SIGNAL(triggered()),
this, SLOT(ansTriggered()));
connect(centerAction, SIGNAL(triggered()),
this, SLOT(ansTriggered()));
connect(justifyAction, SIGNAL(triggered()),
this, SLOT(ansTriggered()));
}
運行效果:
備注:
1、放置到ActionGroup中就默認是exclusive。
2、是否出現選中的標志"小圓點"是通過設置setcheckable完成的。兩者并無聯系。
關于QActionGroup的使用,我發的一個帖子中有提到,再次感謝網友jdwx1
帖子的連接如下,感興趣的可以看看QActionGroup只對子菜單生效?
三、QWidgetAction類詳解
【詳細描述】
??????? QWidgetAction通過接口方式繼承自QAction,用于將自定義的widget插入基于action的容器,例如工具欄。
??????? 出現在應用程序中的絕大多數的actions都是代表了一個菜單項或工具欄中的一個按鈕。然而有時候我們也許要復雜一點的widgets。例如,字處理程序工具欄中使用QComboBox實現zoom action,實現不同程度的縮放。QToolBar提供了QToolBar::insertWidget()函數可以十分方便的將單個widget插入到合適的位置。然而,如果你想在多個容器中實現自定義widget的action,那么你就必須實現QWidgetAction的子類。
??????? 如果QWidgetAction添加到QToolBar,那么就會調用QWidgetAction::createWidget()。我們可以重新實現這個函數創建自定義的widget。
??????? 如果將一個action從容器widget上刪除,那么就會調用QWidgetAction::deleteWidget(),調用該函數的參數就是上面創建的自定義widget。該函數的默認實現是將widget隱藏,然后使用QObject::deleteLater()刪除它。
??????? 如果你只有一個自定義的widget,那么你就可以使用setDefaultWidget()函數將它設置為默認的widget。那么以后當action被添加到QToolBar上時,就會自動將該自定義的widget添加到QToolBar上。如果將僅有一個默認widget的QWidgetAction同時添加到兩個工具欄上,那么僅有第一個添加才會顯示出來。QWidgetAction接管了默認的widget。
??????? 注意:這取決于widget激活action,例如重新實現鼠標事件處理者,然后調用QAction::trigger()。
Mac OS X:在Mac OS X上,如果你將一個widget添加到應用程序菜單欄的某個菜單上,那么該widget可以顯示出來,并且可以實現功能,只是有一些限制:
1、該widget的父對象不再是QMenu而是原生的菜單視圖。如果你在其他地方顯示菜單(例如作為一個彈出菜單),那么該菜單不會顯 示在你期望的地方;
2、針對該widget的Focus/Keyboard處理不再可用;
3、由于Apple的設計,該widget的鼠標軌跡暫時不可用;
4、將triggered()信號鏈接到打開模態對話框的槽函數上會導致應用程序崩潰(在Mac OS X10.4,這被告知是Apple的一個BUG),一個規避的方法是使用QueuedConnection代替DirecConnection。
【示例】
本示例代碼來自:http://www.qtcn.org/bbs/simple/?t28610.html
功能:設置QMenu中菜單項的高度
代碼片段:
class MyMenuItem:public QWidget
{
Q_OBJECT
public:
MyMenuItem(QWidget *parent)
{
new QLabel("test",this);
}
};
int main(int argc, char *argv[])
{
popupMenu = new QMenu(this);
QAction *action1 = new QAction(tr("&New1"), this);
QAction *action2 = new QAction(tr("&New2"), this);
QAction *action3 = new QAction(tr("&New3"), this);
QAction *action4 = new QAction(QIcon("./load.png"), tr("Bookstore"), this);
popupMenu->addAction(action1);
popupMenu->addAction(action2);
popupMenu->addAction(action3);
popupMenu->addAction(action4);
MyMenuItem *item1 = new MyMenuItem(this);
item1->setFixedSize(100,100); //這里可以設置大小
QWidgetAction *action1 = new QWidgetAction(popupMenu);
action1->setDefaultWidget(item1);
MyMenuItem *item2 = new MyMenuItem(this);
QWidgetAction *action2 = new QWidgetAction(popupMenu);
action2->setDefaultWidget(item2);
MyMenuItem *item3 = new MyMenuItem(this);
QWidgetAction *action3 = new QWidgetAction(popupMenu);
action3->setDefaultWidget(item3);
popupMenu->exec();
}