闲来无事,尝试用Qt来实现以下Ribbon效果,感觉还不错,拿出来分享给大家,希望大家多多指点。
平台:win10 64bit + VS2013 update5 + Qt5.6.0 64bit(色彩效果仿照windows的写字板,效果通过QSS实现)
新建一个Qt应用程序工程,删掉UI默认的菜单栏和工具栏。
添加一个widget和一个scrollArea到UI,两个控件采用垂直布局。widget中放置一个pushButton和一个TabWidget,widget采用水平布局,scrollArea中放置一个widget,采用水平布局(垂直布局也可),完成后效果如下:
怎么样,不错吧? 哈哈,开玩笑的哈!
说说我的思路吧!左上方的按钮打算做成一个文件菜单,里面有打开、保存、关于等按钮,tabwidget用来模仿Ribbon效果,下方的scrollArea就是配角而已,看着好看而已的,我们继续。。。
将主界面和上方widget的layout边距设为0,spacing也设为0,修改按钮和tabwidget的文字。设置scrollArea中的widget背景色为白色,固定一个合适的宽度,设置srollArea的背景色(ui.scrollArea->setBackgroundRole(QPalette::Mid);),完成后效果如下:
是不是有点感觉了?我们接着来。
我们需要把文件菜单放到主页的左边,然后主页这些标签依次向右移动。按钮放到tabwidget上面好办,绝对位置即可,可是tabwidge的标签怎么移动呢?这就要借助QSS了,代码如下:
按钮移动代码:
ui.pushButton_MenuFile->setParent(ui.tabWidget);
#tabWidget_Main::tab-bar { left: 65px; }
控制一下文件按钮的大小:
#pushButton_MenuFile{ min-width:50px; max-width:50px; min-height:22px; max-height:22px; }
控制一下tabbar大小:
#tabWidget_Main QTabBar::tab{ min-width:60px; max-width:60px; min-height:22px; max-height:22px; }
完成后效果如下:
#pushButton_MenuFile{ color:white; border: 1px solid #416ABD; border-top-left-radius: 2px; border-top-right-radius: 2px; background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #467FBD, stop:0.5 #2A5FAC,stop:0.51 #1A4088, stop:1 #419ACF); } #pushButton_MenuFile::hover{ background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #7BB2EB, stop:0.5 #477ECD,stop:0.51 #114ECF, stop:1 #80E1FF); } #pushButton_MenuFile::pressed{ background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #467BBB, stop:0.5 #2F63AE,stop:0.51 #1C438A, stop:1 #358BC9); }
设置tabbar的效果:
#tabWidget_Main QTabBar::tab { background: transparent; margin-left: 4px; margin-right: 4px; } #tabWidget_Main QTabBar::tab:selected, QTabBar::tab:hover { border-top-left-radius: 2px; border-top-right-radius: 2px; } #tabWidget_Main::tab-bar { border: 1px solid #BAC9DB; } #tabWidget_Main QTabBar::tab:selected{ border: 1px solid #BAC9DB; background: white; border-bottom-color: #FFFFFF; } #tabWidget_Main QTabBar::tab:hover:!selected{ border: 1px solid #ECBC3D; } #tabWidget_Main QTabBar::tab:!selected { margin-top: 1px; }
然后效果如下:
基本的效果已经出来了,下面我们设置文件菜单的效果,如果直接使用QMenu,设置效果有很多限制,好在Qt提供了QWidgetAction,可以将菜单做成Widget,再使用QSS,感觉棒棒哒!首先我们设置一个菜单的Widget的类:
class MenuItemWidget : public QWidget { Q_OBJECT public: MenuItemWidget(const QPixmap& icon, const QString& text, QWidget *parent = 0) { QLabel* label_Icon = new QLabel(this); label_Icon->setFixedSize(32, 32); label_Icon->setScaledContents(true); label_Icon->setPixmap(icon); QLabel* label_Text = new QLabel(text,this); QHBoxLayout* layout = new QHBoxLayout;
layout->setContentsMargins(20, 6, 50, 6); layout->setSpacing(10); layout->addWidget(label_Icon); layout->addWidget(label_Text);
setLayout(layout); setFixedWidth(240); } ~MenuItemWidget() {} protected: void paintEvent(QPaintEvent* e) Q_DECL_OVERRIDE{ QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } private: };
亲们注意了,如果自己继承QWidget,则需要向上面代码那样重写paintEvent函数,否则无法使用QSS,Qt助手上面说。
下面为文件按钮添加菜单:
QMenu* menu = new QMenu(this); ui.pushButton_MenuFile->setMenu(menu); QWidgetAction* actionNew = new QWidgetAction(this); actionNew->setDefaultWidget(new MenuItemWidget(QPixmap(":/png/file_new.png"), QString::fromStdWString(L"新建"), this)); menu->addAction(actionNew); QWidgetAction* actionOpen = new QWidgetAction(this); actionOpen->setDefaultWidget(new MenuItemWidget(QPixmap(":/png/file_open.png"), QString::fromStdWString(L"打开"), this)); menu->addAction(actionOpen); QWidgetAction* actionSave = new QWidgetAction(this); actionSave->setDefaultWidget(new MenuItemWidget(QPixmap(":/png/file_save.png"), QString::fromStdWString(L"保存"), this)); menu->addAction(actionSave); QWidgetAction* actionSaveAs = new QWidgetAction(this); actionSaveAs->setDefaultWidget(new MenuItemWidget(QPixmap(":/png/file_saveas.png"), QString::fromStdWString(L"另存为"), this)); menu->addAction(actionSaveAs); menu->addSeparator(); QWidgetAction* actioPrint = new QWidgetAction(this); actioPrint->setDefaultWidget(new MenuItemWidget(QPixmap(":/png/file_print.png"), QString::fromStdWString(L"打印"), this)); menu->addAction(actioPrint); menu->addSeparator(); QWidgetAction* actionAout= new QWidgetAction(this); actionAout->setDefaultWidget(new MenuItemWidget(QPixmap(":/png/about.png"), QString::fromStdWString(L"关于"), this)); menu->addAction(actionAout); QWidgetAction* actionExit = new QWidgetAction(this); actionExit->setDefaultWidget(new MenuItemWidget(QPixmap(":/png/exit.png"), QString::fromStdWString(L"退出"), this)); menu->addAction(actionExit); connect(actionExit, SIGNAL(triggered()), this, SLOT(close()));
设置菜单的QSS:
QMenu { background-color: #FCFCFC; border: 1px solid #8492A6; } QMenu::item { background-color: transparent; } MenuItemWidget::hover{ border: 1px solid #FFB700; background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1,stop:0 #FEF9F4, stop:0.38 #FDE0BD,stop:0.39 #FFCE69, stop:1 #FFFFE7); } QMenu::item:selected { background-color: #654321; }
实现后效果如下:
接下来设置tabwidget中的groubox的QSS:
#tabWidget_Main QGroupBox{ border-left: 1px solid gray; border-top: 0px solid gray; } #tabWidget_Main QGroupBox::title { color: #738399; subcontrol-position: bottom center; }
效果如下:
最后的美化:设置字体为微软雅黑,设置tabWidget背景色、隐藏文件按钮菜单小按钮,最终效果如下:
如果需要实现双击tab标签关闭tabwidget的面板,连接标签的doubleClicked信号:
connect(ui.tabWidget_Main, SIGNAL(tabBarDoubleClicked(int)), this, SLOT(hideOrShowTabWidget()));
hideOrShowTabWidget()函数实现如下:
void MainWindow::hideOrShowTabWidget() { static bool isTabWidgetHide = false; ui.widget_Top->setFixedHeight(isTabWidgetHide? 150:25); isTabWidgetHide = !isTabWidgetHide; }
好了,一个山寨的Ribbon就出来了!欢迎亲们多多指点!
工程源码已上传CSDN。。。。。
另外推荐大家看看某个大牛的QSS实现360安全卫士效果,百度:Qt 360 就出来了,叫一去二三里