QToolBar中設置三態QToolButton按鈕
首先,我這個其實是模仿VS Code那個左側菜單欄做的,看一下目標效果:先分析一下,這是一個狀態欄,由按鈕組成,按鈕有三個狀態:正常(灰),鼠標懸浮(白),點擊後(白+豎線)
這是最後的效果:
我這個是不是模仿的很逼真?
需要準備的東西:
1.知道原VS code工具欄的背景色,是rgb(51,51,51);
2.準備好每個按鈕的三態圖片,我是從百度上挑的幾張按鈕圖標,再使用PhotoShop進行顏色變化,背景透明處理,白色豎線添加,拿一個圖標舉例如下:
正常狀態:
點擊後的狀態(顏色比較淺,仔細看)
鼠標懸浮狀態(也是比較淺的顏色)
這裏來說一下實現思路:
1.選擇QToolBar作爲工具欄
2.至於按鈕,這裏選擇QToolButton,
因爲:(1):QToolButton沒有邊框,QPushButton有邊框(雖然你可以設置爲Flat,但那樣也有很多麻煩),(2):QToolButton的QSS屬性有一個叫border-image,可以在:hover等僞裝態時修改,從而達到修改圖標顏色的效果,但QPushButton的qproperty-icon這個QSS屬性無法在僞裝態的樣式表中修改,只能調用相關接口,沒有樣式表簡單.
結論就是用QToolButton實現,圖標使用QSS的border-image屬性來實現(這對於圖像的要求比普通的icon要高,你要1.調整背景圖片中實際圖標的比例,這裏涉及PS裏的調整畫布大小,2.每個狀態中背景圖片的圖案的顏色,3.把背景圖片的背景變透明)
3.設置正常狀態和懸浮狀態都是常規操作,這裏不羅嗦,基礎的QSS使用.但是點擊後那個有點小問題,:pressed這個僞裝態只能設置點擊一瞬間的樣式,如果你通過設置:pressed,效果是這樣的:
這裏我看了一些別的博客,發現最後只能用信號來機制解決了,信號是工具欄上的按鈕被點擊clicked,那麼槽函數呢?
要解決兩個問題:(1):把上次點擊的按鈕恢復爲正常狀態的背景圖片,(2)把被點擊的按鈕設置爲點擊狀態的背景圖片.
那怎麼確定上次點擊的按鈕呢?難道還要再定義個變量chosen_button來確定?
還有,樣式表每次都是覆蓋式設置,你不能只設置部分控件的樣式,只要setStyleSheet(),那就要所有都設置一遍.
解決方案1:直接在槽函數把所有控件重新設置一遍,簡單粗暴.
上源碼(裏面還有一些小細節,QSS屬性名稱及值格式,函數接口注意點,建議看一看註釋):
//獲取工具欄;
toolbar_v=addToolBar("");
//因爲我們不是用ui,所以要設置ObjectName來作爲QSS用的id
toolbar_v->setObjectName("toolbar_v");
toolbar_v->setAllowedAreas(Qt::LeftToolBarArea);
toolbar_v->setOrientation(Qt::Vertical);
toolbar_v->setMovable(false);
//設置最大寬度,要不然它總是expand
toolbar_v->setMaximumWidth(123);
toolbar_v->setMinimumHeight(1980);
//資源管理器按鈕
manage=new QToolButton(this);
//一定要設置ObjectName,否則沒法用樣式表
manage->setObjectName("manage");
//編輯按鈕
edit=new QToolButton(this);
edit->setObjectName("edit");
//主頁按鈕:
home=new QToolButton(this);
home->setObjectName("home");
//設置按鈕:
set=new QToolButton(this);
set->setObjectName("set");
//添加到工具欄上
toolbar_v->addWidget(manage);
toolbar_v->addWidget(edit);
toolbar_v->addWidget(home);
toolbar_v->addWidget(set);
//設置按下按鈕的槽函數,這裏先做了樣式方面的設置:
connect(manage,&QToolButton::clicked,[=](){
setStyleSheet("QToolBar QToolButton{"
"color:white;"
"font-size:20px;"
"min-width:123px;"
"min-height:123px}"
""
"#manage{"
"border-image: url(:/images/menu_pressed);}"
""
"#edit{"
"border-image: url(:/images/edit_normal);}"
"#edit:hover{"
"border-image:url(:/images/edit_hover);}"
""
"#home{"
"border-image: url(:/images/home_normal);}"
"#home:hover{"
"border-image:url(:/images/home_hover);}"
""
"#set{"
"border-image: url(:/images/set_normal);}"
"#set:hover{"
"border-image:url(:/images/set_hover);}"
""
"#toolbar_v{"
"background-color:rgb(51,51,51);}"
"");
});
connect(edit,&QToolButton::clicked,[=](){
setStyleSheet("QToolBar QToolButton{"
"color:white;"
"font-size:20px;"
"min-width:123px;"
"min-height:123px}"
""
"#manage{" //需要區分-和_,很容易搞混
"border-image: url(:/images/menu_normal);}"
"#manage:hover{"
"border-image:url(:/images/menu_hover);}"
""
"#edit{"
"border-image: url(:/images/edit_pressed);}"
""
"#home{"
"border-image: url(:/images/home_normal);}"
"#home:hover{"
"border-image:url(:/images/home_hover);}"
""
"#set{"
"border-image: url(:/images/set_normal);}"
"#set:hover{"
"border-image:url(:/images/set_hover);}"
""
"#toolbar_v{"
"background-color:rgb(51,51,51);}"
"");
});
connect(home,&QToolButton::clicked,[=]{
this->hide();});
//最後,設置一遍狀態下的樣式
this->setStyleSheet("QToolBar QToolButton{"
"color:white;"
"font-size:20px;"
"min-width:123px;"
"min-height:123px}"
""
"#manage{"
"border-image: url(:/images/menu_normal);}"
"#manage:hover{"
"border-image:url(:/images/menu_hover);}"
""
"#edit{"
"border-image: url(:/images/edit_normal);}"
"#edit:hover{"
"border-image:url(:/images/edit_hover);}"
""
"#home{"
"border-image: url(:/images/home_normal);}"
"#home:hover{"
"border-image:url(:/images/home_hover);}"
""
"#set{"
"border-image: url(:/images/set_normal);}"
"#set:hover{"
"border-image:url(:/images/set_hover);}"
""
"#toolbar_v{"
"background-color:rgb(51,51,51);}"
""
);
這種方法解決這個問題是沒有問題,但一些缺點很明顯:
1.假如我的窗口還要設置其它控件的樣式,那每次都重新複製粘貼,再修改目標段落,要求我要對整個樣式表很清楚,但前面寫的還要時刻記着浪費時間複習.
2.同樣的,每次都要複製,粘貼,太佔地方,複雜,降低了整個代碼的可讀性,所以:
解決方法2:對上一個方法的優化,可以減少代碼行數,方便樣式表的擴展.
我在主窗口類中定義一個globel_styleString的QString變量,用來儲存總的樣式字符串,
再定義一個函數:void add_styleString(QString partial_styleString);
每次我修改某個部分樣式表,就調用該方法,傳參爲該部分的樣式表字符串.
在該函數內部進行字符串拼接,將該部分字符串拼接至全局樣式字符串中,然後在我的add_styleString()方法內部調用setStyleSheet()函數.
用這個方法,解決了控件擴展和控件更新的樣式字符串更新問題.
代碼如下:
類的頭文件中相關部分定義和聲明如下:
//一些成員變量
QToolBar *toolbar_v=NULL;
QString toolbar_v_styleString;
QToolButton *manage =NULL;
QToolButton *edit=NULL;
QToolButton *home=NULL;
QToolButton *set=NULL;
QTabWidget *tabwidget=NULL;
QTreeView *treeview=NULL;
/*因爲樣式表字符串只能有一個,
* 這裏我採用拼接的方式,有一個總樣式表,
* 每次新添加樣式表,就添加到總樣式表字符串中
* 最後直接設置總樣式就行
*/
QString globel_styleString="";
//用來設置樣式表的函數:
public:
void add_styleString(QString);
該頭文件對應cpp文件相關部分如下:
Note_MainWindow::Note_MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Note_MainWindow)
{
ui->setupUi(this);
//1301:工具欄準備工作
//獲取工具欄;
toolbar_v=addToolBar("");
//因爲我們不是用ui,所以要設置ObjectName來作爲QSS用的id
toolbar_v->setObjectName("toolbar_v");
toolbar_v->setAllowedAreas(Qt::LeftToolBarArea);
toolbar_v->setOrientation(Qt::Vertical);
toolbar_v->setMovable(false);
//設置最大寬度,要不然它總是expand
toolbar_v->setMaximumWidth(123);
toolbar_v->setMinimumHeight(1980);
//資源管理器按鈕
manage=new QToolButton(this);
//一定要設置ObjectName,否則沒法用樣式表
manage->setObjectName("manage");
//編輯按鈕
edit=new QToolButton(this);
edit->setObjectName("edit");
//主頁按鈕:
home=new QToolButton(this);
home->setObjectName("home");
//設置按鈕:
set=new QToolButton(this);
set->setObjectName("set");
//添加到工具欄上
toolbar_v->addWidget(manage);
toolbar_v->addWidget(edit);
toolbar_v->addWidget(home);
toolbar_v->addWidget(set);
//設置按下按鈕的槽函數,這裏先做了樣式方面的設置:
connect(manage,&QToolButton::clicked,[=](){
//因爲實際中按下按鈕保持效果的只有兩個,所以我可以只重新說明這兩個按鈕的樣式字符串就好
add_styleString(
"#manage{"
"border-image: url(:/images/menu_pressed);}"
"#manage:hover{"
"border-image:url(:/images/menu_pressed);}"
""
"#edit{"
"border-image: url(:/images/edit_normal);}"
"#edit:hover{"
"border-image:url(:/images/edit_hover);}");
});
connect(edit,&QToolButton::clicked,[=](){
add_styleString(
"#manage{"
"border-image: url(:/images/menu_normal);}"
"#manage:hover{"
"border-image:url(:/images/menu_hover);}"
""
"#edit{"
"border-image: url(:/images/edit_pressed);}"
"#edit:hover{"
"border-image:url(:/images/edit_pressed);}"
);
});
connect(home,&QToolButton::clicked,[=]{
this->hide();});
//這個是toolbar的基礎樣式字符串
QString basic_toolbar_styleString="QToolBar QToolButton{"
"color:white;"
"font-size:20px;"
"min-width:123px;"
"min-height:123px}"
""
"#manage{"
"border-image: url(:/images/menu_normal);}"
"#manage:hover{"
"border-image:url(:/images/menu_hover);}"
"#manage:pressed{"
"border-image:url(:/images/menu_pressed);}"
""
"#edit{"
"border-image: url(:/images/edit_normal);}"
"#edit:hover{"
"border-image:url(:/images/edit_hover);}"
"#edit:pressed{"
"border-image:url(:/images/edit_pressed);}"
""
"#home{"
"border-image: url(:/images/home_normal);}"
"#home:hover{"
"border-image:url(:/images/home_hover);}"
""
"#set{"
"border-image: url(:/images/set_normal);}"
"#set:hover{"
"border-image:url(:/images/set_hover);}"
""
"#toolbar_v{"
"background-color:rgb(51,51,51);}"
"";
add_styleString(basic_toolbar_styleString);
//1301:工具欄準備工作完成
}
//設置樣式表的函數,只要樣式表有變化,就調用該方法
//直接將改變部分的樣式字符串傳進來就好
void Note_MainWindow::add_styleString(QString partial_styleString){
globel_styleString+=partial_styleString;
this->setStyleSheet(globel_styleString);
}
Note_MainWindow::~Note_MainWindow()
{
delete ui;
}