QT实现自定义侧边导航栏

        侧边导航栏是网页或应用程序界面的一种常见布局,它通常位于页面或应用程序的侧边位置,用来展示导航菜单或功能链接,方便用户快速访问不同的页面或功能。

侧边导航栏一般具有以下特点:

  1. 布局紧凑:侧边导航栏通常采用垂直布局,将导航菜单以列表或图标的形式展示在侧边栏上,占用较小的页面空间。

  2. 导航菜单:侧边导航栏主要用于展示导航菜单,可以将不同的页面或功能按照层级结构排列,以便用户快速找到目标页面。

  3. 展开和收起:对于较大型的导航菜单,侧边导航栏通常支持展开和收起功能,用户可以通过点击菜单项或折叠按钮来展开或收起子菜单,以节省页面空间。

  4. 高亮当前页面:侧边导航栏通常会在当前页面的菜单项上应用一种视觉样式,如高亮或加粗显示,以帮助用户快速定位当前页面。

  5. 响应式设计:随着移动设备的普及,侧边导航栏在响应式设计中扮演重要角色,可以根据屏幕尺寸自动调整布局和样式,以提供更好的用户体验。

 一、简述

         在Qt中,可以通过继承QWidget类来实现自定义侧边导航栏。在paintEvent()函数中绘制自定义的导航栏样式。可以使用QPainter类的绘图功能来实现。为了实现与用户的交互,可以重写鼠标事件的处理函数,例如mouseMoveEvent()和mousePressEvent()。

二、 设计思路    
  1. 创建一个新的类QNavigationWidget,继承自QWidget类。在这个类中,我们可以添加需要的功能和样式
  2. 重写paintEvent()函数,绘制自定义的导航栏样式。使用QPainter类的绘图功能来实现。
  3. 重写鼠标事件的处理函数,mouseMoveEvent()和mousePressEvent(),实现与用户的交互。
  4. 通过判断鼠标的位置来确定用户是否点击了导航栏上导航项,发出相应的信号
三、效果 

 

四、核心代码  
1、头文件

       qnavigationwidget.h

#ifndef QNAVIGATIONWIDGET_H
#define QNAVIGATIONWIDGET_H

#include <QWidget>
#include <QMouseEvent>

class QNavigationWidget : public QWidget
{
    Q_OBJECT
    
public:
    QNavigationWidget(QWidget *parent=0);
    ~QNavigationWidget();

    void addItem(const QString &iconPath,const QString &title);
    void setWidth(const int &width);
    void setBackgroundColor(const QColor &color);
    void setSelectColor(const QColor &color);
    void setMouseInColor(const QColor &color);
    void setRowHeight(const int &height);

protected:
    void paintEvent(QPaintEvent *);
    void mouseMoveEvent(QMouseEvent *);
    void mousePressEvent(QMouseEvent *);
    void leaveEvent(QEvent *);

private:
    QList<QString> listIcons;
    QList<QString> listItems;
    QColor backgroundColor;
    QColor selectedColor;
    QColor mouseInColor;
    int rowHeight;
    int currentIndex;
    int mouseMoveIndex;

signals:
    void currentItemChanged(const int &index);
};

#endif
2、实现代码

qnavigationwidget.cpp

#include "qnavigationwidget.h"
#include <QPainter>
#include <QDebug>

QNavigationWidget::QNavigationWidget(QWidget *parent) : QWidget(parent)
{
    backgroundColor = "#E4E4E4";
    selectedColor = "#2CA7F8";
    mouseInColor = "#C4C4C4";
    rowHeight = 40;
    currentIndex = 0;
    mouseMoveIndex = -1;

    setMouseTracking(true);
    setFixedWidth(120);
}

QNavigationWidget::~QNavigationWidget()
{
}

void QNavigationWidget::addItem(const QString &iconPath,const QString &title)
{
    listIcons << iconPath;
    listItems << title;

    update();
}

void QNavigationWidget::setWidth(const int &width)
{
    setFixedWidth(width);
}

void QNavigationWidget::setBackgroundColor(const QColor &color)
{
    backgroundColor = color;

    update();
}

void QNavigationWidget::setSelectColor(const QColor &color)
{
    selectedColor = color;

    update();
}

void QNavigationWidget::setMouseInColor(const QColor &color)
{
    mouseInColor = color;

    update();
}

void QNavigationWidget::setRowHeight(const int &height)
{
    rowHeight = height;

    update();
}

void QNavigationWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);

    // Draw background color.
    painter.setPen(Qt::NoPen);
    painter.setBrush(backgroundColor);
    painter.drawRect(rect());

    // Draw Items
    int count = 0;
    for (const QString &str : listItems)
    {
        QPainterPath itemPath;
        itemPath.addRect(QRect(0, count * rowHeight, width(), rowHeight));

        if (currentIndex == count)
        {
            painter.setPen("#FFFFFF");
            painter.fillPath(itemPath, selectedColor);
        }
        else if(mouseMoveIndex == count)
        {
            painter.setPen("#FFFFFF");
            painter.fillPath(itemPath, mouseInColor);
        }
        else
        {
            painter.setPen("#202020");
            painter.fillPath(itemPath, backgroundColor);
        }

        //painter.drawText(QRect(40, count * rowHeight, width()-40, rowHeight), Qt::AlignVCenter | Qt::AlignHCenter, str);
        painter.drawPixmap(QRect(20, (count * rowHeight+(rowHeight-20)/2), 20, 20),QPixmap(listIcons[count]));
        painter.drawText(QRect(45, count * rowHeight, width()-40, rowHeight), Qt::AlignVCenter, str);

        ++count;
    }
}

void QNavigationWidget::mouseMoveEvent(QMouseEvent *e)
{
    if (e->y() / rowHeight < listItems.count())
    {
        mouseMoveIndex = e->y() / rowHeight;
    }
    else
    {
        mouseMoveIndex = -1;
    }

    update();
}

void QNavigationWidget::mousePressEvent(QMouseEvent *e)
{
    if (e->y() / rowHeight < listItems.count())
    {
        currentIndex = e->y() / rowHeight;
        emit currentItemChanged(currentIndex);
        update();
    }
}

void QNavigationWidget::leaveEvent(QEvent *)
{
    if(mouseMoveIndex !=-1 )
    {
        mouseMoveIndex = -1;
        update();
    }
}
五、使用示例

以下是一个简单的示例代码,演示了如何在Qt中使用此控件:

#include "mainwindow.h"
#include <QHBoxLayout>
#include <QLabel>
#include "qnavigationwidget.h"

MainWindow::MainWindow(QMainWindow *parent) : QMainWindow(parent)
{
    resize(600, 400);

    QWidget *mainWidget = new QWidget;
    QWidget *rightWidget = new QWidget;
    QVBoxLayout *rightLayout = new QVBoxLayout(rightWidget);
    QHBoxLayout *mainLayout = new QHBoxLayout(mainWidget);
    QNavigationWidget *navigationWidget = new QNavigationWidget;
    QLabel *tipsLabel = new QLabel("Item: 0");

    navigationWidget->setRowHeight(50);
    navigationWidget->addItem(":/res/contents.png","常规");
    navigationWidget->addItem(":/res/editclear.png","消息");
    navigationWidget->addItem(":/res/editcopy.png","字幕");
    navigationWidget->addItem(":/res/filenew.png","下载");
    navigationWidget->addItem(":/res/fileopen.png","会员");
    navigationWidget->addItem(":/res/filesave.png","关于");

    rightLayout->addWidget(tipsLabel, 0, Qt::AlignCenter);
    
    mainLayout->setContentsMargins(0, 0, 0, 0);
    mainLayout->addWidget(navigationWidget);
    mainLayout->addWidget(rightWidget);
    
    setCentralWidget(mainWidget);

    connect(navigationWidget, &QNavigationWidget::currentItemChanged, this, [=](const int &current){
        tipsLabel->setText("Item: " + QString::number(current));
    });
}

MainWindow::~MainWindow()
{
}

        侧边导航栏可以为用户提供方便快捷的导航方式,使用户能够更轻松地浏览和使用网页或应用程序的各个功能和内容。在设计侧边导航栏时,需要考虑页面结构、用户需求和界面美感等因素,以提供更好的使用体验。

        谢谢您的关注和阅读。如果您还有其他问题或需要进一步的帮助,请随时联系我。祝您一切顺利!

六、源代码下载

 

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值