文章目录


1.效果展示

Qt实现的多菜单选择界面_头文件

这种菜单样式比较常用,实现的方法也有很多种,比如可以直接使用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);
}

这里每个页面也可以再嵌入菜单;这个只是实现了一个简单的菜单框架,这个菜单可以再改进添加上菜单键的翻页,菜单键太多,就两边加上箭头,用于把隐藏的按键显示出来;还可以把按键改为竖着排放的。