1. 无边框窗口
1.1 主窗口实现
# pragma once
# include <QtWidgets/QWidget>
# include "CTitleBar.h"
# include "CFrameLessWidgetBase.h"
class MainWidget : public CFrameLessWidgetBase {
Q_OBJECT
public :
MainWidget ( QWidget * parent = Q_NULLPTR) ;
private slots:
void on_closeSlot ( ) ;
private :
void initUI ( ) ;
private :
CTitleBar* m_pTitleBar = nullptr ;
} ;
# include "MainWidget.h"
# include <QVBoxLayout>
# include <QMessageBox>
MainWidget :: MainWidget ( QWidget * parent) : CFrameLessWidgetBase ( parent) {
initUI ( ) ;
}
void MainWidget :: on_closeSlot ( ) {
QMessageBox:: StandardButton _exit = QMessageBox :: warning ( this , u8"提示" , u8"确定要退出吗" ,
QMessageBox:: Yes | QMessageBox:: No, QMessageBox:: Yes) ;
if ( _exit == QMessageBox:: Yes) {
close ( ) ;
}
}
void MainWidget :: initUI ( ) {
m_pTitleBar = new CTitleBar ( this ) ;
QWidget* w = new QWidget ( this ) ;
w-> setMinimumSize ( 800 , 600 ) ;
QVBoxLayout* pVlay = new QVBoxLayout ( this ) ;
pVlay-> addWidget ( m_pTitleBar) ;
pVlay-> addWidget ( w) ;
pVlay-> setContentsMargins ( 0 , 0 , 0 , 0 ) ;
setLayout ( pVlay) ;
connect ( m_pTitleBar, & CTitleBar:: sig_close, this , & MainWidget:: on_closeSlot) ;
}
1.2 标题栏实现
# pragma once
# include <QWidget>
# include <QLabel>
# include <QPushButton>
class CTitleBar : public QWidget {
Q_OBJECT
public :
CTitleBar ( QWidget* p = nullptr ) ;
~ CTitleBar ( ) ;
private :
void initUI ( ) ;
private :
void mousePressEvent ( QMouseEvent* event) override ;
void mouseDoubleClickEvent ( QMouseEvent* event) override ;
private slots:
void onClicked ( ) ;
signals:
void sig_close ( ) ;
private :
QLabel* m_pLogo;
QLabel* m_pTitleTextLabel;
QPushButton* m_pSetBtn;
QPushButton* m_pMinBtn;
QPushButton* m_pMaxBtn;
QPushButton* m_pCloseBtn;
} ;
# include "CTitleBar.h"
# include <QHBoxLayout>
# pragma comment ( lib, "user32.lib" )
# include <qt_windows.h>
CTitleBar :: CTitleBar ( QWidget* p) : QWidget ( p) {
this -> setAttribute ( Qt:: WA_DeleteOnClose) ;
initUI ( ) ;
}
CTitleBar :: ~ CTitleBar ( ) { }
void CTitleBar :: initUI ( ) {
setAttribute ( Qt:: WA_StyledBackground) ;
this -> setFixedHeight ( 32 + 5 * 2 ) ;
this -> setStyleSheet ( "background-color:rgb(54,54,54)" ) ;
m_pLogo = new QLabel ( this ) ;
m_pLogo-> setFixedSize ( 32 , 32 ) ;
m_pLogo-> setStyleSheet ( "background-image:url(:/LessWidgetPro/resources/titlebar/title_icon.png);border:none" ) ;
m_pTitleTextLabel = new QLabel ( this ) ;
m_pTitleTextLabel-> setText ( u8"我是标题" ) ;
m_pTitleTextLabel-> setFixedWidth ( 120 ) ;
m_pTitleTextLabel-> setStyleSheet ( "QLabel{font-family: Microsoft YaHei; \
font-size:18px; \
color:#BDC8E2;background-color:rgb(54,54,54);}" ) ;
m_pSetBtn = new QPushButton ( this ) ;
m_pSetBtn-> setFixedSize ( 32 , 32 ) ;
m_pSetBtn-> setStyleSheet ( "QPushButton{background-image:url(:/LessWidgetPro/resources/titlebar/set.svg);border:none}" \
"QPushButton:hover{" \
"background-color:rgb(99, 99, 99);" \
"background-image:url(:/LessWidgetPro/resources/titlebar/set_hover.svg);border:none;}" ) ;
m_pMinBtn = new QPushButton ( this ) ;
m_pMinBtn-> setFixedSize ( 32 , 32 ) ;
m_pMinBtn-> setStyleSheet ( "QPushButton{background-image:url(:/LessWidgetPro/resources/titlebar/min.svg);border:none}" \
"QPushButton:hover{" \
"background-color:rgb(99, 99, 99);" \
"background-image:url(:/LessWidgetPro/resources/titlebar/min_hover.svg);border:none;}" ) ;
m_pMaxBtn = new QPushButton ( this ) ;
m_pMaxBtn-> setFixedSize ( 32 , 32 ) ;
m_pMaxBtn-> setStyleSheet ( "QPushButton{background-image:url(:/LessWidgetPro/resources/titlebar/normal.svg);border:none}" \
"QPushButton:hover{" \
"background-color:rgb(99, 99, 99);" \
"background-image:url(:/LessWidgetPro/resources/titlebar/normal_hover.svg);border:none;}" ) ;
m_pCloseBtn = new QPushButton ( this ) ;
m_pCloseBtn-> setFixedSize ( 32 , 32 ) ;
m_pCloseBtn-> setStyleSheet ( "QPushButton{background-image:url(:/LessWidgetPro/resources/titlebar/close.svg);border:none}" \
"QPushButton:hover{" \
"background-color:rgb(99, 99, 99);" \
"background-image:url(:/LessWidgetPro/resources/titlebar/close_hover.svg);border:none;}" ) ;
QHBoxLayout* pHlay = new QHBoxLayout ( this ) ;
pHlay-> addWidget ( m_pLogo) ;
pHlay-> addWidget ( m_pTitleTextLabel) ;
pHlay-> addStretch ( ) ;
pHlay-> addWidget ( m_pSetBtn) ;
QSpacerItem* pItem1 = new QSpacerItem ( 20 , 20 , QSizePolicy:: Fixed, QSizePolicy:: Fixed) ;
pHlay-> addSpacerItem ( pItem1) ;
pHlay-> addWidget ( m_pMinBtn) ;
QSpacerItem* pItem2 = new QSpacerItem ( 18 , 20 , QSizePolicy:: Fixed, QSizePolicy:: Fixed) ;
pHlay-> addSpacerItem ( pItem2) ;
pHlay-> addWidget ( m_pMaxBtn) ;
QSpacerItem* pItem3 = new QSpacerItem ( 18 , 20 , QSizePolicy:: Fixed, QSizePolicy:: Fixed) ;
pHlay-> addSpacerItem ( pItem3) ;
pHlay-> addWidget ( m_pCloseBtn) ;
pHlay-> setContentsMargins ( 5 , 5 , 5 , 5 ) ;
connect ( m_pMinBtn, & QPushButton:: clicked, this , & CTitleBar:: onClicked) ;
connect ( m_pMaxBtn, & QPushButton:: clicked, this , & CTitleBar:: onClicked) ;
connect ( m_pCloseBtn, & QPushButton:: clicked, this , & CTitleBar:: onClicked) ;
}
void CTitleBar :: mousePressEvent ( QMouseEvent* event) {
if ( ReleaseCapture ( ) ) {
QWidget* pWindow = this -> window ( ) ;
if ( pWindow-> isTopLevel ( ) ) {
SendMessage ( HWND ( pWindow-> winId ( ) ) , WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0 ) ;
}
}
}
void CTitleBar :: mouseDoubleClickEvent ( QMouseEvent* event) {
emit m_pMaxBtn-> clicked ( ) ;
}
void CTitleBar :: onClicked ( ) {
QPushButton* pButton = qobject_cast < QPushButton* > ( sender ( ) ) ;
QWidget* pWindow = this -> window ( ) ;
if ( pButton == m_pMinBtn) {
pWindow-> showMinimized ( ) ;
} else if ( pButton == m_pMaxBtn) {
if ( pWindow-> isMaximized ( ) ) {
pWindow-> showNormal ( ) ;
m_pMaxBtn-> setStyleSheet ( "QPushButton{background-image:url(:/LessWidgetPro/resources/titlebar/normal.svg);border:none}" \
"QPushButton:hover{" \
"background-color:rgb(99, 99, 99);" \
"background-image:url(:/LessWidgetPro/resources/titlebar/normal_hover.svg);border:none;}" ) ;
} else {
pWindow-> showMaximized ( ) ;
m_pMaxBtn-> setStyleSheet ( "QPushButton{background-image:url(:/LessWidgetPro/resources/titlebar/max.svg);border:none}" \
"QPushButton:hover{" \
"background-color:rgb(99, 99, 99);" \
"background-image:url(:/LessWidgetPro/resources/titlebar/max_hover.svg);border:none;}" ) ;
}
} else if ( pButton == m_pCloseBtn) {
emit sig_close ( ) ;
}
}
1.3 无边框窗口公用类实现
# pragma once
# include <QWidget>
class CFrameLessWidgetBase : public QWidget {
public :
CFrameLessWidgetBase ( QWidget* p = nullptr ) ;
~ CFrameLessWidgetBase ( ) { }
protected :
bool nativeEvent ( const QByteArray& eventType, void * message, long * result) override ;
private :
int m_nBorderWidth = 5 ;
} ;
# include "CFrameLessWidgetBase.h"
# include <qt_windows.h>
# include <windows.h>
# include <windowsx.h>
# pragma comment ( lib, "user32.lib" )
# pragma comment ( lib, "dwmapi.lib" )
CFrameLessWidgetBase :: CFrameLessWidgetBase ( QWidget* p) : QWidget ( p) {
this -> setWindowFlags ( Qt:: FramelessWindowHint | Qt:: WindowMinMaxButtonsHint) ;
setAttribute ( Qt:: WA_Hover) ;
}
bool CFrameLessWidgetBase :: nativeEvent ( const QByteArray& eventType, void * message, long * result) {
MSG* param = static_cast < MSG* > ( message) ;
switch ( param-> message) {
case WM_NCHITTEST: {
int nX = GET_X_LPARAM ( param-> lParam) - this -> geometry ( ) . x ( ) ;
int nY = GET_Y_LPARAM ( param-> lParam) - this -> geometry ( ) . y ( ) ;
if ( nX > m_nBorderWidth && nX < this -> width ( ) - m_nBorderWidth &&
nY > m_nBorderWidth && nY < this -> height ( ) - m_nBorderWidth)
{
if ( childAt ( nX, nY) != nullptr )
return QWidget :: nativeEvent ( eventType, message, result) ;
}
if ( ( nX > 0 ) && ( nX < m_nBorderWidth) )
* result = HTLEFT;
if ( ( nX > this -> width ( ) - m_nBorderWidth) && ( nX < this -> width ( ) ) )
* result = HTRIGHT;
if ( ( nY > 0 ) && ( nY < m_nBorderWidth) )
* result = HTTOP;
if ( ( nY > this -> height ( ) - m_nBorderWidth) && ( nY < this -> height ( ) ) )
* result = HTBOTTOM;
if ( ( nX > 0 ) && ( nX < m_nBorderWidth) && ( nY > 0 )
&& ( nY < m_nBorderWidth) )
* result = HTTOPLEFT;
if ( ( nX > this -> width ( ) - m_nBorderWidth) && ( nX < this -> width ( ) )
&& ( nY > 0 ) && ( nY < m_nBorderWidth) )
* result = HTTOPRIGHT;
if ( ( nX > 0 ) && ( nX < m_nBorderWidth)
&& ( nY > this -> height ( ) - m_nBorderWidth) && ( nY < this -> height ( ) ) )
* result = HTBOTTOMLEFT;
if ( ( nX > this -> width ( ) - m_nBorderWidth) && ( nX < this -> width ( ) )
&& ( nY > this -> height ( ) - m_nBorderWidth) && ( nY < this -> height ( ) ) )
* result = HTBOTTOMRIGHT;
return true ;
}
}
return false ;
}
2. Qt 实现窗口阴影
# include "CLoginDlg.h"
# include "CLoginRealWidget.h"
# include <QGraphicsDropShadowEffect>
# include <QVboxLayout>
# include <QMouseEvent>
CLoginDlg :: CLoginDlg ( QWidget * parent) : QDialog ( parent) {
this -> setAttribute ( Qt:: WA_TranslucentBackground, true ) ;
this -> setWindowFlags ( Qt:: Window | Qt:: FramelessWindowHint | Qt:: WindowMinMaxButtonsHint) ;
QVBoxLayout* pMainLay = new QVBoxLayout ( this ) ;
CLoginRealWidget* pRealWidget = new CLoginRealWidget ( this ) ;
pMainLay-> addWidget ( pRealWidget) ;
pMainLay-> setContentsMargins ( 30 , 30 , 30 , 30 ) ;
setLayout ( pMainLay) ;
pRealWidget-> setStyleSheet ( "background-color:rgb(255, 254, 253)" ) ;
QGraphicsDropShadowEffect* shadow = new QGraphicsDropShadowEffect ( this ) ;
shadow-> setOffset ( 0 , 0 ) ;
shadow-> setColor ( QColor ( "#686868" ) ) ;
shadow-> setBlurRadius ( 30 ) ;
pRealWidget-> setGraphicsEffect ( shadow) ;
}
CLoginDlg :: ~ CLoginDlg ( ) { }
void CLoginDlg :: mousePressEvent ( QMouseEvent* event) {
this -> windowPos = this -> pos ( ) ;
this -> mousePos = event-> globalPos ( ) ;
this -> dPos = mousePos - windowPos;
}
void CLoginDlg :: mouseMoveEvent ( QMouseEvent* event) {
this -> move ( event-> globalPos ( ) - this -> dPos) ;
}
3. Qt 实现圆角窗口
3.1 方式一:绘制法
# pragma once
# include <QtWidgets/QWidget>
class MainWidget : public QWidget {
Q_OBJECT
public :
MainWidget ( QWidget * parent = Q_NULLPTR) ;
private :
void paintEvent ( QPaintEvent* event) override ;
} ;
# include "MainWidget.h"
# include <QPainter>
MainWidget :: MainWidget ( QWidget * parent) : QWidget ( parent) {
resize ( 600 , 400 ) ;
setAttribute ( Qt:: WA_TranslucentBackground) ;
setWindowFlags ( Qt:: FramelessWindowHint | Qt:: WindowMinMaxButtonsHint) ;
}
void MainWidget :: paintEvent ( QPaintEvent* event) {
QPainter painter ( this ) ;
painter. setRenderHint ( QPainter:: Antialiasing) ;
painter. setBrush ( QBrush ( QColor ( 168 , 68 , 68 ) ) ) ;
painter. setPen ( Qt:: transparent) ;
QRect rect = this -> rect ( ) ;
painter. drawRoundedRect ( rect, 15 , 15 ) ;
}
3.2 方式二:qss(推荐,更灵活)
# include "MainWidget.h"
# include <QStyleOption>
# include <QPainter>
MainWidget :: MainWidget ( QWidget * parent) : QWidget ( parent) {
setAttribute ( Qt:: WA_TranslucentBackground) ;
setWindowFlags ( Qt:: FramelessWindowHint | Qt:: WindowMinMaxButtonsHint) ;
this -> setStyleSheet ( "QWidget{background-color:#A84444; \
border-top-left-radius:15px; \
border-bottom-right-radius:15px; \
}" ) ;
}
void MainWidget :: paintEvent ( QPaintEvent* ) {
QStyleOption opt;
opt. init ( this ) ;
QPainter p ( this ) ;
style ( ) -> drawPrimitive ( QStyle:: PE_Widget, & opt, & p, this ) ;
}
4. 实现 WPS tab 页面
4.1 主窗口实现
# pragma once
# include <QtWidgets/QWidget>
# include "ui_WPSDemo.h"
class WPSDemo : public QWidget {
Q_OBJECT
public :
WPSDemo ( QWidget * parent = Q_NULLPTR) ;
protected :
bool nativeEvent ( const QByteArray& eventType, void * message, long * result) override ;
private slots:
void on_close ( ) ;
private :
Ui:: WPSDemoClass ui;
int m_BorderWidth = 5 ;
} ;
# include "WPSDemo.h"
# include "tabbrowser.h"
# include <QHBoxLayout>
# ifdef Q_OS_WIN
# include <qt_windows.h>
# include <Windows.h>
# include <windowsx.h>
# endif
# pragma comment ( lib, "user32.lib" )
# pragma comment ( lib, "dwmapi.lib" )
WPSDemo :: WPSDemo ( QWidget * parent) : QWidget ( parent) {
ui. setupUi ( this ) ;
setWindowFlags ( Qt:: FramelessWindowHint) ;
setStyleSheet ( "background-color:#E3E4E7" ) ;
CTabBrowser* pTab = new CTabBrowser ( this ) ;
QHBoxLayout* pHLay = new QHBoxLayout ( this ) ;
pHLay-> addWidget ( pTab) ;
pHLay-> setContentsMargins ( 6 , 6 , 6 , 6 ) ;
setLayout ( pHLay) ;
connect ( pTab, & CTabBrowser:: sig_close, this , & WPSDemo:: on_close) ;
}
void WPSDemo :: on_close ( ) {
close ( ) ;
}
bool WPSDemo :: nativeEvent ( const QByteArray& eventType, void * message, long * result) {
Q_UNUSED ( eventType)
MSG* param = static_cast < MSG* > ( message) ;
switch ( param-> message) {
case WM_NCHITTEST: {
int nX = GET_X_LPARAM ( param-> lParam) - this -> geometry ( ) . x ( ) ;
int nY = GET_Y_LPARAM ( param-> lParam) - this -> geometry ( ) . y ( ) ;
if ( childAt ( nX, nY) != nullptr )
return QWidget :: nativeEvent ( eventType, message, result) ;
if ( ( nX > 0 ) && ( nX < m_BorderWidth) )
* result = HTLEFT;
if ( ( nX > this -> width ( ) - m_BorderWidth) && ( nX < this -> width ( ) ) )
* result = HTRIGHT;
if ( ( nY > 0 ) && ( nY < m_BorderWidth) )
* result = HTTOP;
if ( ( nY > this -> height ( ) - m_BorderWidth) && ( nY < this -> height ( ) ) )
* result = HTBOTTOM;
if ( ( nX > 0 ) && ( nX < m_BorderWidth) && ( nY > 0 )
&& ( nY < m_BorderWidth) )
* result = HTTOPLEFT;
if ( ( nX > this -> width ( ) - m_BorderWidth) && ( nX < this -> width ( ) )
&& ( nY > 0 ) && ( nY < m_BorderWidth) )
* result = HTTOPRIGHT;
if ( ( nX > 0 ) && ( nX < m_BorderWidth)
&& ( nY > this -> height ( ) - m_BorderWidth) && ( nY < this -> height ( ) ) )
* result = HTBOTTOMLEFT;
if ( ( nX > this -> width ( ) - m_BorderWidth) && ( nX < this -> width ( ) )
&& ( nY > this -> height ( ) - m_BorderWidth) && ( nY < this -> height ( ) ) )
* result = HTBOTTOMRIGHT;
return true ;
}
}
return QWidget :: nativeEvent ( eventType, message, result) ;
}
4.2 标签栏实现
# pragma once
# include <QWidget>
# include <QPushButton>
class CTabTitleWidget : public QWidget {
Q_OBJECT
public :
CTabTitleWidget ( QWidget* parent = nullptr ) ;
~ CTabTitleWidget ( ) ;
void setEmptyWidgetWidth ( int w) ;
protected :
void paintEvent ( QPaintEvent* event) override ;
void mousePressEvent ( QMouseEvent* event) override ;
void mouseDoubleClickEvent ( QMouseEvent* event) ;
signals:
void sig_close ( ) ;
void sig_addtab ( ) ;
private slots:
void on_Clicked ( ) ;
private :
QPushButton* m_pAddBtn = nullptr ;
QWidget* m_pEmptyWidget = nullptr ;
QPushButton* m_pUserBtn = nullptr ;
QPushButton* m_pMinBtn = nullptr ;
QPushButton* m_pMaxBtn = nullptr ;
QPushButton* m_pCloseBtn = nullptr ;
} ;
# include "CTabTitleWidget.h"
# include <QHBoxLayout>
# include <QMouseEvent>
# include <QStyleOption>
# include <QPainter>
# ifdef Q_OS_WIN
# include <qt_windows.h>
# pragma comment ( lib, "user32.lib" )
# endif
CTabTitleWidget :: CTabTitleWidget ( QWidget* parent) {
setStyleSheet ( "background-color:#E3E4E7" ) ;
m_pAddBtn = new QPushButton ( this ) ;
m_pAddBtn-> setFlat ( true ) ;
m_pAddBtn-> setFixedSize ( 32 , 32 ) ;
m_pAddBtn-> setStyleSheet ( "background-image:url(:/WPSDemo/resources/add.svg)" ) ;
m_pEmptyWidget = new QWidget ( this ) ;
m_pUserBtn = new QPushButton ( this ) ;
m_pUserBtn-> setFlat ( true ) ;
m_pUserBtn-> setFixedSize ( 32 , 32 ) ;
m_pUserBtn-> setStyleSheet ( "background-image:url(:/WPSDemo/resources/user)" ) ;
m_pMinBtn = new QPushButton ( this ) ;
m_pMinBtn-> setFlat ( true ) ;
m_pMinBtn-> setFixedSize ( 32 , 32 ) ;
m_pMinBtn-> setStyleSheet ( "background-image:url(:/WPSDemo/resources/min.svg)" ) ;
m_pMaxBtn = new QPushButton ( this ) ;
m_pMaxBtn-> setFlat ( true ) ;
m_pMaxBtn-> setFixedSize ( 32 , 32 ) ;
m_pMaxBtn-> setStyleSheet ( "background-image:url(:/WPSDemo/resources/max.svg)" ) ;
m_pCloseBtn = new QPushButton ( this ) ;
m_pCloseBtn-> setFlat ( true ) ;
m_pCloseBtn-> setFixedSize ( 32 , 32 ) ;
m_pCloseBtn-> setStyleSheet ( "background-image:url(:/WPSDemo/resources/close.svg)" ) ;
QHBoxLayout* pHLay = new QHBoxLayout ( this ) ;
pHLay-> addWidget ( m_pAddBtn) ;
pHLay-> addWidget ( m_pEmptyWidget) ;
this -> setSizePolicy ( QSizePolicy:: Maximum, QSizePolicy:: Expanding) ;
pHLay-> addWidget ( m_pUserBtn) ;
pHLay-> addSpacing ( 8 ) ;
pHLay-> addWidget ( m_pMinBtn) ;
pHLay-> addWidget ( m_pMaxBtn) ;
pHLay-> addWidget ( m_pCloseBtn) ;
pHLay-> setContentsMargins ( 1 , 0 , 1 , 3 ) ;
setLayout ( pHLay) ;
connect ( m_pAddBtn, & QPushButton:: clicked, this , & CTabTitleWidget:: on_Clicked) ;
connect ( m_pMinBtn, & QPushButton:: clicked, this , & CTabTitleWidget:: on_Clicked) ;
connect ( m_pMaxBtn, & QPushButton:: clicked, this , & CTabTitleWidget:: on_Clicked) ;
connect ( m_pCloseBtn, & QPushButton:: clicked, this , & CTabTitleWidget:: on_Clicked) ;
}
CTabTitleWidget :: ~ CTabTitleWidget ( ) { }
void CTabTitleWidget :: setEmptyWidgetWidth ( int w) {
m_pEmptyWidget-> setMinimumWidth ( w) ;
}
void CTabTitleWidget :: paintEvent ( QPaintEvent* event) {
QStyleOption opt;
opt. init ( this ) ;
QPainter p ( this ) ;
style ( ) -> drawPrimitive ( QStyle:: PE_Widget, & opt, & p, this ) ;
QWidget :: paintEvent ( event) ;
}
void CTabTitleWidget :: mousePressEvent ( QMouseEvent* event) {
if ( ReleaseCapture ( ) ) {
QWidget* pWindow = this -> window ( ) ;
if ( pWindow-> isTopLevel ( ) ) {
SendMessage ( HWND ( pWindow-> winId ( ) ) , WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0 ) ;
}
}
event-> ignore ( ) ;
}
void CTabTitleWidget :: mouseDoubleClickEvent ( QMouseEvent* event) {
emit m_pMaxBtn-> clicked ( ) ;
}
void CTabTitleWidget :: on_Clicked ( ) {
QPushButton* pButton = qobject_cast < QPushButton* > ( sender ( ) ) ;
QWidget* pWindow = this -> window ( ) ;
if ( pWindow-> isTopLevel ( ) ) {
if ( pButton == m_pAddBtn) {
emit sig_addtab ( ) ;
} else if ( pButton == m_pMinBtn) {
pWindow-> showMinimized ( ) ;
} else if ( pButton == m_pMaxBtn) {
pWindow-> isMaximized ( ) ? pWindow-> showNormal ( ) : pWindow-> showMaximized ( ) ;
} else if ( pButton == m_pCloseBtn) {
emit sig_close ( ) ;
}
}
}
4.3 标签栏右键导航菜单实现
# pragma once
# include <QTabWidget>
# include <QMenu>
# include "CTabTitleWidget.h"
class CTabBrowser : public QTabWidget {
Q_OBJECT
public :
explicit CTabBrowser ( QWidget * parent = 0 ) ;
enum TAB_FLAG {
NEW,
CLOSE,
NORMAL,
SPECIAL
} ;
protected :
void resizeEvent ( QResizeEvent * e) override ;
private :
void initTabWidget ( ) ;
void setTabBarFlag ( TAB_FLAG flag) ;
void createTabMenu ( ) ;
private slots:
void on_newTab ( ) ;
void on_closeTab ( int index) ;
void onMenuShow ( const QPoint& pos) ;
void on_closeAllTab ( ) ;
signals:
void sig_close ( ) ;
private :
CTabTitleWidget* m_pRightWidget = nullptr ;
QMenu* m_pTabMenu = nullptr ;
} ;
# include "tabbrowser.h"
# include <QDebug>
# include <QPushButton>
# include <QHBoxLayout>
# include <QMessageBox>
# include <QTabBar>
QString qss0 = "QTabBar::tab{ \
font: 75 12pt Arial; \
text-align:left; \
width:184px; \
height:32; \
background:#FFFFFF; \
border:2px solid #FFFFFF; \
border-bottom-color:#FFFFFF; \
border-top-left-radius:4px; \
border-top-right-radius:4px; \
padding:2px; \
margin-top:0px; \
margin-right:1px; \
margin-left:1px; \
margin-bottom:0px;} \
QTabBar::tab:selected{ \
color:#333333; /*文字颜色*/ \
background-color:#FFFFFF;} \
QTabBar::tab:!selected{ \
color:#B2B2B2; \
border-color:#FFFFFF;} \
QTabBar::scroller{width: 0px;}" ;
QString qss1 = "QTabBar::tab{ \
font: 75 12pt Arial; \
text-align:left; \
width:184px; \
height:32; \
background:#FFFFFF; \
border:2px solid #FFFFFF; \
border-bottom-color:#FFFFFF; \
border-top-left-radius:4px; \
border-top-right-radius:4px; \
padding:2px; \
margin-top:0px; \
margin-right:1px; \
margin-left:1px; \
margin-bottom:0px;} \
QTabBar::tab:selected{ \
color:#333333; /*文字颜色*/ \
background-color:#FFFFFF;} \
QTabBar::tab:!selected{ \
color:#B2B2B2; \
border-color:#FFFFFF;} \
QTabBar::scroller{width: 36px;}" ;
CTabBrowser :: CTabBrowser ( QWidget * parent) : QTabWidget ( parent) {
this -> addTab ( new QWidget, u8"稻壳" ) ;
this -> setUsesScrollButtons ( true ) ;
this -> setTabsClosable ( true ) ;
this -> setMovable ( true ) ;
initTabWidget ( ) ;
setTabBarFlag ( NORMAL) ;
this -> setStyleSheet ( qss0) ;
connect ( this , & QTabWidget:: tabCloseRequested, this , & CTabBrowser:: on_closeTab) ;
}
void CTabBrowser :: resizeEvent ( QResizeEvent * e) {
setTabBarFlag ( NORMAL) ;
QTabWidget :: resizeEvent ( e) ;
}
void CTabBrowser :: createTabMenu ( ) {
m_pTabMenu = new QMenu ( this ) ;
QAction* pAcSave = new QAction ( QIcon ( ":/WPSDemo/resources/save.png" ) , u8"保存" , m_pTabMenu) ;
m_pTabMenu-> addAction ( pAcSave) ;
connect ( pAcSave, & QAction:: triggered, [ = ] {
QMessageBox :: information ( this , u8"提示" , u8"你点击了 保存" ) ;
} ) ;
QAction* pAcSaveAs = new QAction ( QString ( u8"另存为" ) , m_pTabMenu) ;
m_pTabMenu-> addAction ( pAcSaveAs) ;
m_pTabMenu-> addSeparator ( ) ;
QAction* pAcShareDoc = new QAction ( QIcon ( ":/WPSDemo/resources/share.png" ) , QString ( u8"分享文档" ) , m_pTabMenu) ;
m_pTabMenu-> addAction ( pAcShareDoc) ;
QAction* pAcSendToDevice = new QAction ( QString ( u8"发送到设备" ) , m_pTabMenu) ;
m_pTabMenu-> addAction ( pAcSendToDevice) ;
m_pTabMenu-> addSeparator ( ) ;
QAction* pAcNewName = new QAction ( QString ( u8"重命名" ) , m_pTabMenu) ;
m_pTabMenu-> addAction ( pAcNewName) ;
QAction* pAcSaveToWPSCloud = new QAction ( QString ( u8"保存到WPS云文档" ) , m_pTabMenu) ;
m_pTabMenu-> addAction ( pAcSaveToWPSCloud) ;
QAction* pAcCloseAll = new QAction ( QString ( u8"关闭所有文件" ) , m_pTabMenu) ;
m_pTabMenu-> addAction ( pAcCloseAll) ;
connect ( pAcCloseAll, & QAction:: triggered, this , & CTabBrowser:: on_closeAllTab) ;
}
void CTabBrowser :: setTabBarFlag ( TAB_FLAG flag) {
int w = this -> width ( ) ;
int tabsWidth = 0 ;
int tabsHeight = tabBar ( ) -> height ( ) ;
int tabs = this -> count ( ) ;
if ( flag == NEW || flag == NORMAL) {
for ( int i = 0 ; i < tabs; ++ i) {
tabsWidth += tabBar ( ) -> tabRect ( i) . width ( ) ;
}
} else {
for ( int i = 0 ; i < tabs - 1 ; ++ i) {
tabsWidth += tabBar ( ) -> tabRect ( i) . width ( ) ;
}
} if ( w > tabsWidth) {
m_pRightWidget-> setEmptyWidgetWidth ( w - tabsWidth - 32 * 5 - 15 ) ;
this -> setStyleSheet ( qss0) ;
} else {
m_pRightWidget-> setEmptyWidgetWidth ( 150 ) ;
this -> setStyleSheet ( qss1) ;
}
}
void CTabBrowser :: initTabWidget ( ) {
this -> setContextMenuPolicy ( Qt:: CustomContextMenu) ;
connect ( this , & QTabWidget:: customContextMenuRequested, this , & CTabBrowser:: onMenuShow) ;
createTabMenu ( ) ;
m_pRightWidget = new CTabTitleWidget ( this ) ;
this -> setCornerWidget ( m_pRightWidget, Qt:: TopRightCorner) ;
connect ( m_pRightWidget, & CTabTitleWidget:: sig_addtab, this , & CTabBrowser:: on_newTab) ;
connect ( m_pRightWidget, & CTabTitleWidget:: sig_close, this , & CTabBrowser:: sig_close) ;
}
void CTabBrowser :: on_newTab ( ) {
int nCount = count ( ) ;
QString title = QString :: number ( nCount) ;
title = "Page" + title;
this -> addTab ( new QWidget, title) ;
if ( ! tabsClosable ( ) ) {
setTabsClosable ( true ) ;
}
setTabBarFlag ( NEW) ;
}
void CTabBrowser :: on_closeTab ( int index) {
widget ( index) -> deleteLater ( ) ;
setTabBarFlag ( CLOSE) ;
if ( count ( ) == 1 ) {
setTabsClosable ( false ) ;
setTabBarFlag ( SPECIAL) ;
}
}
void CTabBrowser :: onMenuShow ( const QPoint& pos) {
int index = this -> tabBar ( ) -> tabAt ( pos) ;
# ifdef _DEBUG
qDebug ( ) << u8"当前tab为:" << QString :: number ( index) ;
this -> setCurrentIndex ( index) ;
# endif
if ( index != - 1 ) {
m_pTabMenu-> exec ( QCursor :: pos ( ) ) ;
}
}
void CTabBrowser :: on_closeAllTab ( ) { }