1. 无边框窗口
1.1 主窗口实现
# pragma once # include <QtWidgets/QWidget>
# include "CTitleBar.h"
# include "CFrameLessWidgetBase.h"
class MainWidget : public CFrameLessWidgetBase { Q_OBJECTpublic : 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_OBJECTpublic : 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_OBJECTpublic : 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_OBJECTpublic : 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_OBJECTpublic : 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 ( ) { }