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

环境配置 :MinGW + QT 5.12
效果图:

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


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


本文中实现方法:

  • item被hover时改变图标样式:继承QListWidgetItem + 继承QStyledItemDelegate
  • 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;

private:
    QPoint startPos;
};
  • TestListWidget.c文件:
TestListWidget::TestListWidget(QWidget *parent) :
    QListWidget(parent)
{
}

//鼠标按下时,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);
}

(3)TestItemDelegate类继承自QStyledItemDelegate

  • TestItemDelegate.h文件:
class TestItemDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    TestItemDelegate(QObject *parent = nullptr);

protected:
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
  • TestItemDelegate.c文件:
void TestItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
    TestListWidget *listWidget = qobject_cast<TestListWidget *>(option.styleObject);

    QRect rect = option.rect;

    painter->setRenderHint(QPainter::Antialiasing, true);
    painter->setPen(Qt::NoPen);

    if(option.state & (QStyle::State_MouseOver | QStyle::State_Selected)){

        TestListWidgetItem *item = static_cast<TestListWidgetItem *>(listWidget->item(index.row()));
        item->setIcon(item->Img_hover);

        if(option.state & QStyle::State_MouseOver){
        }
        if(option.state & QStyle::State_Selected){
            painter->setBrush(QColor(180, 0, 0));
            painter->drawRect(rect.topLeft().x(), rect.topLeft().y(), 4, rect.height());

            painter->setBrush(QColor(230, 231, 234));
            painter->drawRect(rect.topLeft().x() + 4, rect.topLeft().y(), rect.width() - 4, rect.height());
        }
    }else{
        TestListWidgetItem *item = static_cast<TestListWidgetItem *>(listWidget->item(index.row()));
        item->setIcon(item->Img);
    }
    QStyledItemDelegate::paint(painter, option, index);
}

(4)使用TestListWidget、TestListWidgetItem以及TestItemDelegate

void test::initUi()
{
    setFixedSize(250, 600);

    TestListWidget *listwidget = new TestListWidget(this);
    listwidget->setIconSize(QSize(25, 25));
    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); padding-left:14px;}"
                "QListWidget::Item:selected{color:rgba(40, 40, 200, 255); padding-left:15px;}"
                //"QListWidget::Item:selected:active{/*color:rgba(40, 40, 200, 255);*/ padding-left:14px;}"
                );

    TestItemDelegate *delegate = new TestItemDelegate();
    listwidget->setItemDelegate(delegate);

    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);
}

环境配置 :MinGW + QT 5.12

你可能感兴趣的:(Qt学习笔记,QListWidget,QListWidgetItem,图标,代理/委托)