自定义QListWidget实现item被hover时改变图标样式(模仿网易云音乐选项列表)(方法一)

摘要:
本文中的实现方法:在项目悬停时更改图标样式:inheritQListWidgetItem+inheritQlistWidgetItem释放鼠标时选择:inherit QListWidget另一种实现方法:自定义QListWidet以实现在项目悬停后更改图标样式(方法2)TestListWidgetItem类继承自QListWidetItemTestListWidget项H文件:classTestListWidgetItem:publicQListWidgetItem{//Q_OBJECT//因为QListWidget Item没有QObject属性,Q_OBJCT需要注释掉public:显式TestListWidget Item;voisetUpIcon;QIconImg;QIconImg_hover;};TestListWidgetItem。C文件:voidTestListWidgetItem::TestListWidget Item:QListWidgetItem{}voidTestList WidgetItem::setUpIcon{Img=icon;Img_hover=icon_hover;setIcon;}2) TestListWidget类继承自QListWidgetTestListWidgetH文件:classTestListWidid:publicQListWidget{Q_OBJECTpublic:explicitTestListWidget;protected:voidmousePressEventoverride;voidmousReleaseEventoverride;voidMouseMoveEventoverrides;voidleaveEventoverrider;private:QPointstartPos;TestListWidgetItem*theHighlightItem=nullptr;TestListWidgetItem*oldHighlightItem=nullptr;TestListWidthItem*theSelectedItem=nullaptr;privatesslots:voidupdateSelectedIcon();};TestListWidget。C文件:TestListWidget::TestListWidget:QListWidget{//mouseMoveEvent需要此属性setMouseTracking;//当当前选定的项发生更改时,将触发项图标的更新以进行连接;}//处理鼠标悬停时,项目的图标需要更改为悬停状态voidTestListWidget::mouseMoveEvent{oldHighlightItem=theHighlightItem;theHighlightItem=static_cast<TestListWidgetItem*>;//旧悬停的项目图标返回原始状态。//如果(oldHighlightItem!

本文转载自https://blog.csdn.net/weixin_43742643/article/details/100187743

前半部分copy了博主的博文,后面是自己的实践和疑惑。

效果图:

 自定义QListWidget实现item被hover时改变图标样式(模仿网易云音乐选项列表)(方法一)第1张

这里需要说明一下:QListWidget是鼠标press时item就会被选中,自定义的TestListWidget类重写了mousePressEvent和mouseReleaseEvent使得item在鼠标release时才会被选中。至于为什么这样做,是因为Chrome浏览器的书签栏以及网易云音乐的选项列表都是在鼠标release时才会触发选中…

本文中实现方法:

  • item被hover时改变图标样式:继承QListWidgetItem + 继承QListWidget
  • item在鼠标release时选中:继承QListWidget

另一种实现方法:自定义QListWidget实现item被hover时改变图标样式(模仿网易云音乐选项列表)(方法二)

(1)TestListWidgetItem类继承自QListWidgetItem

  • TestListWidgetItem.h文件:
class TestListWidgetItem : public QListWidgetItem
{
    //Q_OBJECT  //由于QListWidgetItem没有QObject属性,所以Q_OBJECT需要注释掉
public:
    explicit TestListWidgetItem(QListWidget *view = nullptr);
    void setUpIcon(const QIcon &icon, const QIcon &icon_hover);

    QIcon Img;
    QIcon Img_hover;
};
  • TestListWidgetItem.c文件:
TestListWidgetItem::TestListWidgetItem(QListWidget *view) :
    QListWidgetItem(view)
{
}

void TestListWidgetItem::setUpIcon(const QIcon &icon, const QIcon &icon_hover)
{
    Img = icon;
    Img_hover = icon_hover;
    setIcon(Img);
}

2)TestListWidget类继承自QListWidget

  • TestListWidget.h文件:
class TestListWidget : public QListWidget
{
    Q_OBJECT
public:
    explicit TestListWidget(QWidget *parent = nullptr);

protected:
    void mousePressEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void leaveEvent(QEvent *event) override;

private:
    QPoint startPos;
    TestListWidgetItem *theHighlightItem = nullptr;
    TestListWidgetItem *oldHighlightItem = nullptr;
    TestListWidgetItem *theSelectedItem = nullptr;
    TestListWidgetItem *oldSelectedItem = nullptr;

private slots:
    void updateSelectedIcon();
};
  • TestListWidget.c文件:
TestListWidget::TestListWidget(QWidget *parent) :
    QListWidget(parent)
{
    //mouseMoveEvent(QMouseEvent *event)需要该属性
    setMouseTracking(true);
    //当前被选中项发生变化时,触发item图标的更新
    connect(this, &TestListWidget::itemSelectionChanged, this, &TestListWidget::updateSelectedIcon);
}

//处理鼠标hover时,item的图标需要变成hover状态
void TestListWidget::mouseMoveEvent(QMouseEvent *event)
{
    oldHighlightItem = theHighlightItem;
    theHighlightItem = static_cast<TestListWidgetItem *>(itemAt(event->pos()));

    //旧的hover的item图标回复原状(条件是该item没有被选中)
    //新的hover的iten图标变成hover状态(条件是该item没有被选中)
    if(oldHighlightItem != theHighlightItem){
        if(oldHighlightItem && !oldHighlightItem->isSelected()) oldHighlightItem->setIcon(oldHighlightItem->Img);
        if(theHighlightItem && !theHighlightItem->isSelected()) theHighlightItem->setIcon(theHighlightItem->Img_hover);
    }
}

//鼠标按下时,startPos记录单击位置
void TestListWidget::mousePressEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton){
        startPos = event->pos();
    }
}

//释放鼠标时,item才会被选中
void TestListWidget::mouseReleaseEvent(QMouseEvent *event)
{
    //如果鼠标释放位置和单击位置相距超过5像素,则不会触发item选中
    if((event->pos() - startPos).manhattanLength() > 5) return;

    TestListWidgetItem *item = static_cast<TestListWidgetItem *>(itemAt(event->pos()));
    setCurrentItem(item);
}

//处理鼠标离开后,hover图标回复正常状态
void TestListWidget::leaveEvent(QEvent *event)
{
    Q_UNUSED(event);
    oldHighlightItem = theHighlightItem;
    if(oldHighlightItem && !oldHighlightItem->isSelected()) oldHighlightItem->setIcon(oldHighlightItem->Img);
    oldHighlightItem = theHighlightItem = nullptr;
}

//响应itemSelectionChanged()信号,处理item被选中后,图标变成并保持hover状态
void TestListWidget::updateSelectedIcon()
{
    oldSelectedItem = theSelectedItem;
    theSelectedItem = static_cast<TestListWidgetItem *>(currentItem());

    //之前被选中的item图标回复原样
    //新被选中的item图标变成hover状态
    if(oldSelectedItem != theSelectedItem){
        if(oldSelectedItem) oldSelectedItem->setIcon(oldSelectedItem->Img);
        if(theSelectedItem) theSelectedItem->setIcon(theSelectedItem->Img_hover);
    }
}

(3)使用TestListWidget和TestListWidgetItem

void test::initUi()
{
    TestListWidget *listwidget = new TestListWidget(this);
    listwidget->setIconSize(QSize(25, 25));  //设置item图标大小
    listwidget->setFocusPolicy(Qt::NoFocus);  //这样可禁用tab键和上下方向键并且除去复选框
    listwidget->setFixedHeight(320);
    listwidget->setFont(QFont("宋体", 10, QFont::DemiBold));
    listwidget->setStyleSheet(
                //"*{outline:0px;}"  //除去复选框
                "QListWidget{background:rgb(245, 245, 247); border:0px; margin:0px 0px 0px 0px;}"
                "QListWidget::Item{height:40px; border:0px; padding-left:14px; color:rgba(200, 40, 40, 255);}"
                "QListWidget::Item:hover{color:rgba(40, 40, 200, 255);}"
                "QListWidget::Item:selected{background:rgb(230, 231, 234); color:rgba(40, 40, 200, 255); border-left:4px solid rgb(180, 0, 0);}"
                //"QListWidget::Item:selected:active{background:rgb(230, 231, 234); color:rgba(40, 40, 200, 255); border-left:4px solid rgb(180, 0, 0);}");

    TestListWidgetItem *item1 = new TestListWidgetItem(listwidget);
    item1->setUpIcon(QIcon(":/listBar_Icon/1.png"), QIcon(":/listBar_Icon/1_hover.png"));
    item1->setText("发现音乐");

    TestListWidgetItem *item2 = new TestListWidgetItem(listwidget);
    item2->setUpIcon(QIcon(":/listBar_Icon/2.png"), QIcon(":/listBar_Icon/2_hover.png"));
    item2->setText("私人FM");

    TestListWidgetItem *item3 = new TestListWidgetItem(listwidget);
    item3->setUpIcon(QIcon(":/listBar_Icon/3.png"), QIcon(":/listBar_Icon/3_hover.png"));
    item3->setText("朋友");

    TestListWidgetItem *item4 = new TestListWidgetItem(listwidget);
    item4->setUpIcon(QIcon(":/listBar_Icon/4.png"), QIcon(":/listBar_Icon/4_hover.png"));
    item4->setText("MV");

    TestListWidgetItem *item5 = new TestListWidgetItem(listwidget);
    item5->setUpIcon(QIcon(":/listBar_Icon/5.png"), QIcon(":/listBar_Icon/5_hover.png"));
    item5->setText("本地音乐");

    TestListWidgetItem *item6 = new TestListWidgetItem(listwidget);
    item6->setUpIcon(QIcon(":/listBar_Icon/6.png"), QIcon(":/listBar_Icon/6_hover.png"));
    item6->setText("下载管理");

    TestListWidgetItem *item7 = new TestListWidgetItem(listwidget);
    item7->setUpIcon(QIcon(":/listBar_Icon/7.png"), QIcon(":/listBar_Icon/7_hover.png"));
    item7->setText("我的音乐云盘");

    TestListWidgetItem *item8 = new TestListWidgetItem(listwidget);
    item8->setUpIcon(QIcon(":/listBar_Icon/8.png"), QIcon(":/listBar_Icon/8_hover.png"));
    item8->setText("我的收藏");

    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->setSpacing(0);
    layout->addWidget(listwidget);
    layout->setContentsMargins(0, 0, 0, 0);
    setLayout(layout);
}

(4)继承QListWidget时其实也可以不需要重写leaveEvent(QEvent *event)和mouseMoveEvent(QMouseEvent *event)这两个函数,只需要重写event(QEvent *event)。

  • TestListWidget.h文件:
class TestListWidget : public QListWidget
{
    Q_OBJECT
public:
    explicit TestListWidget(QWidget *parent = nullptr);

protected:
    void mousePressEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    bool event(QEvent *event) override;

private:
    QPoint startPos;
    TestListWidgetItem *theHighlightItem = nullptr;
    TestListWidgetItem *oldHighlightItem = nullptr;
    TestListWidgetItem *theSelectedItem = nullptr;
    TestListWidgetItem *oldSelectedItem = nullptr;

private slots:
    void updateSelectedIcon();
};
  • TestListWidget.c文件:
TestListWidget::TestListWidget(QWidget *parent) :
    QListWidget(parent)
{
    //不重写mouseMoveEvent(QMouseEvent *event)的话,该属性可以不用设置
    //setMouseTracking(true);
    //当前被选中项发生变化时,触发item图标的更新
    connect(this, &TestListWidget::itemSelectionChanged, this, &TestListWidget::updateSelectedIcon);
}

//鼠标按下时,startPos记录单击位置
void TestListWidget::mousePressEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton){
        startPos = event->pos();
    }
}

//释放鼠标时,item才会被选中
void TestListWidget::mouseReleaseEvent(QMouseEvent *event)
{
    //如果鼠标释放位置和单击位置相距超过5像素,则不会触发item选中
    if((event->pos() - startPos).manhattanLength() > 5) return;
    //由于TestListWidgetItem没有QObject属性,所以这里使用static_cast而非qobject_cast
    TestListWidgetItem *item = static_cast<TestListWidgetItem *>(itemAt(event->pos()));
    setCurrentItem(item);
}

bool TestListWidget::event(QEvent *event)
{
    switch (event->type()) {
    //处理鼠标hover时,item的图标需要变成hover状态
    case QEvent::HoverMove:
        oldHighlightItem = theHighlightItem;
        //由于TestListWidgetItem没有QObject属性,所以这里使用static_cast而非qobject_cast
        theHighlightItem = static_cast<TestListWidgetItem *>(itemAt(mapFromGlobal(QCursor::pos())));

        //旧的hover的item图标回复原状(条件是该item没有被选中)
        //新的hover的iten图标变成hover状态(条件是该item没有被选中)
        if(oldHighlightItem != theHighlightItem){
            if(oldHighlightItem && !oldHighlightItem->isSelected()) oldHighlightItem->setIcon(oldHighlightItem->Img);
            if(theHighlightItem && !theHighlightItem->isSelected()) theHighlightItem->setIcon(theHighlightItem->Img_hover);
        }
        break;
    //处理鼠标离开后,hover图标回复正常状态
    case QEvent::HoverLeave:
        oldHighlightItem = theHighlightItem;
        if(oldHighlightItem && !oldHighlightItem->isSelected()) oldHighlightItem->setIcon(oldHighlightItem->Img);
        oldHighlightItem = theHighlightItem = nullptr;
        break;
    default:
        break;
    }
    return QListWidget::event(event);
}

//响应itemSelectionChanged()信号,处理item被选中后,图标变成并保持hover状态
void TestListWidget::updateSelectedIcon()
{
    oldSelectedItem = theSelectedItem;
    //由于TestListWidgetItem没有QObject属性,所以这里使用static_cast而非qobject_cast
    theSelectedItem = static_cast<TestListWidgetItem *>(currentItem());

    //之前被选中的item图标回复原样
    //新被选中的item图标变成hover状态
    if(oldSelectedItem != theSelectedItem){
        if(oldSelectedItem) oldSelectedItem->setIcon(oldSelectedItem->Img);
        if(theSelectedItem) theSelectedItem->setIcon(theSelectedItem->Img_hover);
    }
}

这一部分是自己稍加改进的代码,运行无误。还是用的重写事件的方法。

#include "testlistwidgetitem.h"
#include <QApplication>
#include "testlistwidgetitem.h"
#include "testlistwidget.h"
#include <QVBoxLayout>
#include  <QHBoxLayout>
#include <QWidget>
#include<QListWidget>
#include <QMainWindow>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    TestListWidget *listwidget = new TestListWidget();
    listwidget->setIconSize(QSize(25, 25));  //设置item图标大小
    listwidget->setFocusPolicy(Qt::NoFocus);  //这样可禁用tab键和上下方向键并且除去复选框
    listwidget->setFixedHeight(320);
    listwidget->setFont(QFont("宋体", 10, QFont::DemiBold));
    listwidget->setStyleSheet(
        "*{outline:0px;}"  //除去复选框
        "QListWidget{background:rgb(245, 245, 247); border:0px; margin:0px 0px 0px 0px;}"
        "QListWidget::Item{height:40px; border:0px; padding-left:14px; color:rgba(200, 40, 40, 255);}"
        "QListWidget::Item:hover{color:rgba(40, 40, 200, 255);}"
        "QListWidget::Item:selected{background:rgb(230, 231, 234); color:rgba(40, 40, 200, 255); border-left:4px solid rgb(180, 0, 0);}"
        "QListWidget::Item:selected:active{background:rgb(230, 231, 234); color:rgba(40, 40, 200, 255); border-left:4px solid rgb(180, 0, 0);}");

    TestListWidgetItem *item1 = new TestListWidgetItem(listwidget);
    item1->setUpIcon(QIcon(":/normal.jpg"), QIcon(":/pressed.jpg"));
    item1->setText("数据查询");

    TestListWidgetItem *item2 = new TestListWidgetItem(listwidget);
    item2->setUpIcon(QIcon(":/normal1.jpg"), QIcon(":/pressed1.jpg"));
    item2->setText("曲线查询");

    QVBoxLayout *layout = new QVBoxLayout();
    //QHBoxLayout *layout = new QHBoxLayout();
    layout->setSpacing(0);
    layout->addWidget(listwidget);
    layout->setContentsMargins(0, 0, 0, 0);
    //listwidget->setLayout(layout);  //不注掉这一句的话不显示窗体,很奇怪
    listwidget->show();

    return a.exec();
}

自定义QListWidget实现item被hover时改变图标样式(模仿网易云音乐选项列表)(方法一)第2张自定义QListWidget实现item被hover时改变图标样式(模仿网易云音乐选项列表)(方法一)第3张自定义QListWidget实现item被hover时改变图标样式(模仿网易云音乐选项列表)(方法一)第4张

免责声明:文章转载自《自定义QListWidget实现item被hover时改变图标样式(模仿网易云音乐选项列表)(方法一)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇nginx基本配置ORA-14402: 更新分区关键字列将导致分区的更改下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

关于圆角的实现以及鼠标移入显示二级菜单的兼容处理!

在这时碰到了一个圆角边框的问题,以前的代码是在每个页面写一个固定结构的div,使用背景图片来实现圆角边框。代码结构大致如下: .top_border{background:url(topborder.png);} .left_border{background:url(leftborder.png);} .right_border{background:u...

CSS 属性选择器的深入挖掘

CSS 属性选择器,可以通过已经存在的属性名或属性值匹配元素。 属性选择器是在 CSS2 中引入的并且在 CSS3 中得到了很好拓展。本文将会比较全面的介绍属性选择器,尽可能的去挖掘这个选择器在不同场景下的不同用法。 简单的语法介绍 [attr]:该选择器选择包含 attr 属性的所有元素,不论 attr 的值为何。 [attr=val]:该选择器仅选...

【转】bootstrap popover 如何在hover状态移动到弹出上不消失

$(".pop").popover({ trigger: "manual" , html: true, animation:false}) .on("mouseenter", function () { var _this = this; // 这里的this触发的dom,需要存起来 否则在下面 .popover的逻辑中th...

QComboBox实现复选功能(三种方法:嵌套QListWidget, 设置QStandardItemModel, 设置Delegate)

今天介绍一下一个小东西 — 如何让QComboBox实现复选功能? 需求: 下拉列表有复选功能 不可编辑 显示所有选中项 关于QComboBox的复选功能有几种方案: QStandardItemModel + QStandardItem QListWidget +QListWidgetItem Model/View + QItemDelegate...

不可思议的纯 CSS 实现鼠标跟随效果

直接进入正题,鼠标跟随,顾名思义,就是元素会跟随着鼠标的移动而作出相应的运动。大概类似于这样: 通常而言,CSS 负责表现,JavaScript 负责行为。而鼠标跟随这种效果属于行为,要实现通常都需要借助 JS。 当然,本文的重点,就是介绍如何在不借助 JS 的情况下使用 CSS 来模拟实现一些鼠标跟随的行为动画效果。 原理 以上面的 Demo 为例子...

HTML 最简单的tips 怎么支持指定DIV显示提示信息

<body> <style type="text/css"> a.link{position:relative;} a.link div.tips{ border:1px solid #333; padding:10px; background-color:#ff0; position:absolute; top:16px; le...