1.效果展示
这种菜单样式比较常用,实现的方法也有很多种,比如可以直接使用QTableWidget,也可以用QStackedWidget实现。这里我是用QToolButton和QWidget+QScrollArea实现的。这个可以在实例化时指定菜单按键数。
2.实现代码
2.1 菜单实现代码
2.1.1 头文件
#ifndef CBASECONFIG_H #define CBASECONFIG_H /************************************************************************ * 名称:上导航菜单栏界面 * 上边是导航按键,下面是对应的界面 * 作者:fens *************************************************************************/ #include <QWidget> #include <QToolButton> #include <QMap> namespace Ui { class CBaseConfig; } class CBaseConfig : public QWidget { Q_OBJECT public: explicit CBaseConfig(QWidget *parent = nullptr); ~CBaseConfig(); //设置菜单按键的最小宽度 void setMenuMiniWidth(int minw); //设置菜单按键的最小高度 void setMenuMiniHeight(int minh); //设置菜单按键的最大宽度 void setMenuMaxWidth(int maxw); //设置菜单按键的最大高度 void setMenuMaxHeight(int maxh); //用于设置按键属性,固定大小/缩放 void setMenuBtnSizePolicy(QSizePolicy val); //初始化生成菜单按键和对应界面 void initMenu(QVector<QPair<QString, QWidget*> >& listItem); signals: void clicked(int , bool ); //按键序号,从0开始, 状态-true选中;false-未选中 private slots: void onToolButtonClicked(); private: Ui::CBaseConfig *ui; QString m_bakebtnName; //备份当前显示的界面按键 QVector<QToolButton*>m_btnMap; //用于保存菜单按键 QMap<QString, QWidget*>m_widgetsMap; //用于保存菜单对应的界面 QSizePolicy m_btnQSizePolicy; }; #endif // CBASECONFIG_H
2.1.2 源文件
#include "cbaseconfig.h" #include "ui_cbaseconfig.h" #include <QDebug> CBaseConfig::CBaseConfig(QWidget *parent) : QWidget(parent), ui(new Ui::CBaseConfig) { ui->setupUi(this); this->setProperty("form", true); this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint); // m_btnQSizePolicy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_btnQSizePolicy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); } CBaseConfig::~CBaseConfig() { delete ui; } void CBaseConfig::setMenuMiniHeight(int minh) { ui->widgetSetMenu->setMinimumWidth(minh); } void CBaseConfig::setMenuMiniWidth(int minw) { ui->widgetSetMenu->setMinimumWidth(minw); } void CBaseConfig::setMenuMaxHeight(int maxh) { ui->widgetSetMenu->setMaximumHeight(maxh); } void CBaseConfig::setMenuMaxWidth(int maxw) { ui->widgetSetMenu->setMaximumWidth(maxw); } void CBaseConfig::setMenuBtnSizePolicy(QSizePolicy val) { m_btnQSizePolicy = val; } //根据传入的菜单名称和QWidget界面来生成菜单界面 void CBaseConfig::initMenu(QVector<QPair<QString, QWidget*> >& listItem) { m_btnMap.clear(); m_widgetsMap.clear(); QToolButton *ptbn = NULL; for (int i = 0; i < listItem.count(); i++) { ptbn = new QToolButton; ptbn->setObjectName(QString("tbSetMenu%1").arg(i)); ptbn->setText(listItem.at(i).first); ptbn->setSizePolicy(m_btnQSizePolicy); ptbn->setCheckable(true); connect(ptbn, &QToolButton::clicked, this, &CBaseConfig::onToolButtonClicked); ui->horizontalLayout->addWidget(ptbn); ui->mainLayout->addWidget(listItem.at(i).second); listItem.at(i).second->hide(); m_btnMap.push_back(ptbn); m_widgetsMap[listItem.at(i).first] = listItem.at(i).second; } m_btnMap.at(0)->setChecked(true); m_bakebtnName = listItem.at(0).first; listItem.at(0).second->show(); } void CBaseConfig::onToolButtonClicked() { QToolButton *b = (QToolButton *)sender(); QString name = b->text(); for ( int i = 0; i < m_btnMap.size(); i++ ) { if (m_btnMap.at(i) == b) { m_btnMap.at(i)->setChecked(true); emit clicked(i, true); } else { if( m_btnMap.at(i)->isChecked() ) emit clicked(i, false); m_btnMap.at(i)->setChecked(false); } } // qDebug()<<"in CBaseConfig::onToolButtonClicked, button "<<name<<", checked!"<<"last: "<<m_bakebtnName; m_widgetsMap[m_bakebtnName]->hide(); m_widgetsMap[name]->show(); m_bakebtnName = name; }
2.2 应用代码
使用代码源文件
#include "mainwindow.h" #include "ui_mainwindow.h" #include "cbaseconfig.h" #include <QLabel> #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); init(); //设置菜单键样式,实际应用时,建议写在单独的qss文件中 QStringList qss; qss.append("QToolButton{color:rgb(250, 250,250);font:14px;min-width:72px;min-height:37px;background-color: qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #0931B4,stop:1 #050A51);border:1px;border-right-color: rgb(20, 20, 20);border-left-color: rgb(20, 20, 20);/*border-radius控制圆角大小*/ }"); qss.append("QToolButton:pressed{background-color: qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #0931B4,stop:1 #050A51);}"); qss.append("QToolButton:checked{background-color: qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #420064,stop:1 #0D22DE);}"); this->setStyleSheet(qss.join("")); } MainWindow::~MainWindow() { delete ui; } void MainWindow::init() { int heigth = 76; CBaseConfig *baseConfig = new CBaseConfig; baseConfig->setMenuMiniHeight(heigth); baseConfig->setMenuMaxHeight(heigth); QVector<QPair<QString, QWidget*> > listItem; //基本设置 listItem.clear(); QWidget *pWidget; QGridLayout *playout ; QLabel *lab; //循环添加7个菜单按键 for (int i = 1; i <= 7; i++) { pWidget = new QWidget; playout = new QGridLayout; lab = new QLabel; lab->setText(QString("菜单%1").arg(i)); lab->setAlignment(Qt::AlignCenter); lab->setStyleSheet("font: 48px"); playout->addWidget(lab); pWidget->setLayout(playout); listItem.push_back(qMakePair(QString("菜单%1").arg(i),pWidget)); } connect(baseConfig, &CBaseConfig::clicked, this, [this](int no, bool flag){ if (flag ) qDebug()<<"no: "<<no<<" enter screen."; else qDebug()<<"no: "<<no<<" leave screen."; }); baseConfig->initMenu(listItem); //这里为什么要使用QScrollArea,这样菜单界面内容超出一页内容时,可以像网页一页向下滚动。 ui->scrollArea->setWidget(baseConfig); }
这里每个页面也可以再嵌入菜单;这个只是实现了一个简单的菜单框架,这个菜单可以再改进添加上菜单键的翻页,菜单键太多,就两边加上箭头,用于把隐藏的按键显示出来;还可以把按键改为竖着排放的。
示例代码下载:
码云:https://gitee.com/fensnote/demo_code