Qt侧边垂直导航菜单栏Demo

目录

1、最终效果展示

2、应用场景与实现原理

3、运行构建环境

4、源代码展示

5、 项目文件下载地址


1、最终效果展示

图1.结果展示

2、应用场景与实现原理

        Qt自带菜单栏方向是水平方向,在一些情况下需要用到侧边菜单导航栏,即垂直菜单栏,如上图所示的菜单栏。

        本示例使用到了鼠标钩子函数、QPushButton、QDialog、QMenu、QEvent事件过滤等,从无到有写了一个垂直菜单栏。

图2.代码文件

3、运行构建环境

         Win10 64Bit系统、VS2017、调试器MSVC2017 32bit

 图3.Qt Creator版本

4、源代码展示

cmousehook.h

#ifndef CMOUSEHOOK_H
#define CMOUSEHOOK_H
#include <windows.h>
#include <winuser.h>
#include <QObject>

class CMouseHook : public QObject
{
    Q_OBJECT
public:
    enum Model
    {
        eNull = 0,
        eKey = 1,
        eMouse = 2,
        eMouseKey = 3
    }mModel;
    static CMouseHook* instance();
    void installHook(Model model);
    void unInstallHook(Model model);

private:
    CMouseHook();
signals:
    void closeMenu();
};

#endif // CMOUSEHOOK_H

cmousehook.cpp

#include "cmousehook.h"

static HHOOK mouseHook = nullptr;
static CMouseHook *hookClass = nullptr;




LRESULT CALLBACK mouseProc(int nCode,WPARAM wParam,LPARAM lParam)
{
    if(!hookClass)
        return CallNextHookEx(mouseHook,nCode,wParam,lParam);
    if (WM_RBUTTONDOWN == wParam || WM_LBUTTONDOWN == wParam)
    {
        emit hookClass->closeMenu();
    }
    return CallNextHookEx(mouseHook,nCode,wParam,lParam);
}

CMouseHook::CMouseHook()
    :mModel(eNull)
{

}

CMouseHook *CMouseHook::instance()
{
    if(!hookClass)
        hookClass = new CMouseHook();
    return hookClass;
}

void CMouseHook::installHook(Model model)
{
    mModel = model;
    if(mModel == eMouse)
        mouseHook = SetWindowsHookEx(WH_MOUSE_LL,mouseProc,nullptr,0);
}

void CMouseHook::unInstallHook(Model model)
{

    if(model == eMouse)
        UnhookWindowsHookEx(mouseHook);
    mouseHook = nullptr;
    mModel = eNull;
}

 verticalmenunavigationbar.h

#ifndef VERTICALMENUNAVIGATIONBAR_H
#define VERTICALMENUNAVIGATIONBAR_H

#include <QObject>
#include <QWidget>
#include <QVBoxLayout>
#include <QDialog>
#include <QPushButton>
#include <QMenu>
#include <QEvent>

class VerticalMenuNavigationBar : public QWidget
{
    Q_OBJECT
public:
    VerticalMenuNavigationBar(QWidget *parent);
    QDialog *menuDialog;
    void hideAndRefresh();

protected:
    bool eventFilter(QObject *obj, QEvent *event);

private:
    QVBoxLayout *vLayout;
    QVBoxLayout *vLayoutDialog;
    QDialog *childDialog;
    QPushButton *titleButton;

    struct MenuBarListNode
    {
        QPushButton *pushbutton;
        QMenu *menu;
        QString titleStr;
        int secondCounts;
    };

    QList<MenuBarListNode*> menuBarList;

signals:
    void SendIndexToMain(QString index);

};

#endif // VERTICALMENUNAVIGATIONBAR_H

  verticalmenunavigationbar.cpp

#include "verticalmenunavigationbar.h"

VerticalMenuNavigationBar::VerticalMenuNavigationBar(QWidget *parent) : QWidget(parent)
{
    vLayout = new QVBoxLayout(this);
    vLayout->setContentsMargins(0,0,0,0);

    menuDialog = new QDialog();
    menuDialog->setStyleSheet("background-color:rgb(0,0,64);");
    menuDialog->setWindowFlags(Qt::Tool|Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);

    childDialog = new QDialog();
    childDialog->setStyleSheet("background-color:rgb(0,0,64);");
    childDialog->setWindowFlags(Qt::Tool|Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);

    titleButton = new QPushButton();
    titleButton->setMinimumHeight(33);
    titleButton->setMinimumWidth(90);
    titleButton->setMaximumHeight(33);
    titleButton->setMaximumWidth(90);
    titleButton->setContentsMargins(0,0,0,0);
    titleButton->setStyleSheet("QPushButton{background-color:rgb(24,189,155);"
                               "border-image:url(:image/generic/dropdownbg-3.png);"
                               "color:rgb(255,255,255);"
                               "font:bold 14px;"
                               "text-align:left;"
                               "font-family:'Microsoft YaHei';}"
                               );

    vLayoutDialog = new QVBoxLayout();
    vLayoutDialog->setContentsMargins(0,0,0,0);
    vLayoutDialog->addWidget(titleButton);
    vLayoutDialog->addWidget(childDialog);
    vLayoutDialog->setSpacing(0);
    menuDialog->setLayout(vLayoutDialog);

    for(int i=0;i<4;i++)
    {
        QPushButton *button = new QPushButton();
        button->setStyleSheet("QPushButton{"
                              "color:rgb(255,255,255);"
                              "}");
        button->setText(QString("%1").arg(i));
        button->setFixedSize(33,33);
        vLayout->setSpacing(0);
        vLayout->addWidget(button,Qt::AlignLeft);

        button->installEventFilter(this);

        QMenu *menu = new QMenu();
        menu->setMinimumWidth(90);
        menu->setStyleSheet(
        "QMenu{"
             "background-color:rgb(0,0,64);"
             "margin:0px;"
        "}"
        "QMenu::item "
        "{"
             "font-size:12px;"
             "color:rgb(255,225,255);"
             "font-family:Microsoft YaHei;"
             "background-color:rgb(52,73,94,20);"
             "padding:5px 5px; "
             "margin:0px 0px;"
             "border-bottom:1px solid rgb(52,73,94,180);"
        "}"


        "QMenu::item:selected "
        "{"
             "background-color: rgb(24,189,155);"
             "font-size:12px;"
             "color:rgb(0,0,0);"
             "font-family:Microsoft YaHei;"
        "}"

         "QMenu::item:hover "
         "{"
             "font-size:12px;"
             "color:rgb(0,0,0);"
             "background-color: rgb(155,189,155);"
             "font-family:Microsoft YaHei;"
         "}");
        menu->setParent(childDialog);

        MenuBarListNode *menuBarListNode = new MenuBarListNode();
        menuBarListNode->pushbutton = button;
        menuBarListNode->titleStr = QString("%1").arg(i);
        menuBarListNode->menu = menu;

        if(i == 0 || i == 2)
        {
            menuBarListNode->secondCounts = 2;
            for(int j=0;j<2;j++)
            {
                menu->addAction("ShowPag" + QString("%1").arg(i) + QString("%1").arg(j) ,[=]{
                    emit SendIndexToMain(QString("%1").arg(i) + QString("%1").arg(j));
                    hideAndRefresh();
                });
            }
        }
        else
        {
            menuBarListNode->secondCounts = 0;
            connect(button,&QPushButton::clicked,[=]{
                emit SendIndexToMain(QString("%1").arg(i));
                hideAndRefresh();
            });
        }

        menuBarList << menuBarListNode;

    }
}

void VerticalMenuNavigationBar::hideAndRefresh()
{
    for(int i=0;i<menuBarList.length();i++)
    {
        menuBarList.at(i)->pushbutton->setStyleSheet("QPushButton{"
                                                                           "color:rgb(255,255,255);"
                                                                           "}");

    }

    menuDialog->hide();
}

bool VerticalMenuNavigationBar::eventFilter(QObject *obj, QEvent *event)
{
    for(int i=0;i<menuBarList.length();i++)
    {
        if(obj == menuBarList.at(i)->pushbutton && (event->type() == QEvent::Enter || event->type() == QEvent::MouseButtonPress))
        {
            menuDialog->show();

            menuBarList.at(i)->pushbutton->setStyleSheet("QPushButton{"
                                                         "color:rgb(255,255,255);"
                                                         "background-color: rgb(24,189,155);"
                                                         "}");
            for(int j=0;j<menuBarList.length();j++)
            {
                if(i==j)
                {
                    titleButton->setText(menuBarList.at(j)->titleStr);
                    menuBarList.at(j)->menu->show();
                }
                else
                {
                    menuBarList.at(j)->menu->hide();
                    menuBarList.at(j)->pushbutton->setStyleSheet("QPushButton{"
                                                                 "color:rgb(255,255,255);"
                                                                 "}");
                }
            }
            childDialog->resize(90,menuBarList.at(i)->menu->rect().height());
            menuDialog->resize(90,titleButton->minimumHeight() + menuBarList.at(i)->menu->rect().height());
            QPoint p = menuBarList.at(i)->pushbutton->mapToGlobal(QPoint(0, 0));
            menuDialog->move(QPoint(p.x()+menuBarList.at(i)->pushbutton->width(), p.y()));
            if(menuBarList.at(i)->secondCounts > 1)
                return true;
            else
                return false;
        }
    }
    return QObject::eventFilter(obj, event);
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "verticalmenunavigationbar.h"
#include "cmousehook.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    VerticalMenuNavigationBar *menuNavigationBar;

public slots:
    void receiveIndex(QString index);
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->widget->setContentsMargins(0,0,0,0);
    menuNavigationBar = new VerticalMenuNavigationBar(ui->widget);
    connect(menuNavigationBar,&VerticalMenuNavigationBar::SendIndexToMain,this,&MainWindow::receiveIndex);
    CMouseHook::instance()->installHook(CMouseHook::eMouse);
    connect(CMouseHook::instance(),&CMouseHook::closeMenu,[=](){
        if(!menuNavigationBar->menuDialog->isHidden()  && ((QCursor::pos().x() < menuNavigationBar->menuDialog->mapToGlobal(QPoint(0,0)).x() || QCursor::pos().x() > menuNavigationBar->menuDialog->mapToGlobal(QPoint(0,0)).x() + menuNavigationBar->menuDialog->rect().width() ) || (QCursor::pos().y() < menuNavigationBar->menuDialog->mapToGlobal(QPoint(0,0)).y() || QCursor::pos().y() > menuNavigationBar->menuDialog->mapToGlobal(QPoint(0,0)).y() + menuNavigationBar->menuDialog->rect().height())))
            menuNavigationBar->hideAndRefresh();
    });
}

MainWindow::~MainWindow()
{
    CMouseHook::instance()->unInstallHook(CMouseHook::eMouse);
    delete ui;
}

void MainWindow::receiveIndex(QString index)
{
   if(index == "00")
       ui->stackedWidget->setCurrentWidget(ui->page);
   else if(index == "01")
       ui->stackedWidget->setCurrentWidget(ui->page_2);
   else if(index == "1")
       ui->stackedWidget->setCurrentWidget(ui->page_3);
   else if(index == "20")
       ui->stackedWidget->setCurrentWidget(ui->page_4);
   else if(index == "21")
       ui->stackedWidget->setCurrentWidget(ui->page_5);
   else
       ui->stackedWidget->setCurrentWidget(ui->page_6);
}

        LeftMenuNavigationBar.pro文件中添加:

LIBS += $$quote(C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Lib\User32.Lib)

5、 项目文件下载地址

https://download.csdn.net/download/weixin_44322043/81136586

  • 1
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
Qt是一个跨平台的C++开发框架,它提供了丰富的图形用户界面(GUI)组件,可以轻松地创建各种菜单并将其集成到应用程序中。 Qt提供了Qt Widgets模块,其中包含了各种用于创建用户界面的类。其中之一是QMenuBar类,它可以用于创建菜单栏,包括水平菜单和垂直菜单。 对于垂直菜单,可以使用QMenu类来创建。首先,我们需要创建一个QMenu对象,并使用addMenu()方法将它添加到菜单栏或其他菜单中。然后,我们可以使用addAction()方法来添加菜单项。每个菜单项都可以关联一个动作(QAction),并在用户选择该菜单项时执行相应的操作。 可以使用QAction类创建动作对象。动作对象可以设置图标、文本、快捷键等属性,还可以关联一个槽函数,该函数在动作被触发时执行相应的操作。 在创建垂直菜单时,可以使用QVBoxLayout布局来安排菜单项的位置。QVBoxLayout可以通过addWidget()方法来添加QMenu对象,并使用addSpacing()方法来添加间距或分隔符。最后,将QVBoxLayout设置给QWidget或QMainWindow的布局管理器,将垂直菜单添加到对应的界面中显示出来。 总结,Qt提供了丰富的组件和类来创建侧边垂直菜单。通过使用QMenu、QAction、QVBoxLayout等类和方法,可以轻松创建垂直菜单,并将其集成到Qt应用程序中。这样的侧边垂直菜单可以提供更好的用户体验和界面交互。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

99.999...%

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值