QListWidget 自定义 item的图标和文字的位置

文章探讨了在Qt环境下控制QListWidgetItem的icon和text在x轴位置的方法,包括使用自定义图片、setItemWidget接口、delegate等策略,并指出了各种方法的优缺点。思路五提到,通过设置QListWidgetItem的样式表可以直接达到预期效果。
摘要由CSDN通过智能技术生成

前言

楼主并没有完整的解决这个问题,如果你是着急寻找解决方案的就可以划走了,如果你对楼主的解决思路有兴趣,那么可以继续向下阅读。首先需求是可以控制QListWidgetItem的icon和text x轴的位置,但是同时保持icon在左text在右的基本布局,还要求styleSheet能够生效。

思路一

做一张两边透明中间显示的图片。这样就可以控制icon和text的位置了。楼主没有试过实际效果

思路二

使用QListWIdgetsetItemWIdget接口。
mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QListWidgetItem *item0 = new QListWidgetItem(ui->listWidget);   
    MyItemWidget *itemWidget = new MyItemWidget(QIcon(":/pic/rabbit.png"), QStringLiteral("兔子"), ui->listWidget);
    ui->listWidget->setItemWidget(item0, itemWidget);

    QListWidgetItem *item1 = new QListWidgetItem(ui->listWidget);
    item1->setIcon(QIcon(":/pic/tiger.png"));
    item1->setText(QStringLiteral("老虎"));

    ui->listWidget->addItem(item0);
    ui->listWidget->addItem(item1);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    QListWidgetItem *item = ui->listWidget->item(0);
    QModelIndex index = ui->listWidget->currentIndex();
    qDebug() << index.data(Qt::DisplayRole).toString();
}

MyItemWidget::MyItemWidget(const QIcon &icon, const QString &name, QWidget *parent)
{
    iconLabel = new QLabel;
    iconLabel->setPixmap(icon.pixmap(QSize(15, 15)));
    iconLabel->setFixedSize(QSize(15, 15));

    nameLabel = new QLabel(name);

    hSpaceItem = new QSpacerItem(10, 10, QSizePolicy::Fixed);
    hSpaceItem1 = new QSpacerItem(20, 10, QSizePolicy::Fixed);

    layout = new QHBoxLayout;
    layout->setMargin(0);

    layout->addItem(hSpaceItem);
    layout->addWidget(iconLabel);

    layout->addItem(hSpaceItem1);

    layout->addWidget(nameLabel);

    this->setLayout(layout);
}

MyItemWidget::~MyItemWidget()
{

}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QListWidget>
#include <QListWidgetItem>
#include <QIcon>
#include <QSpacerItem>
#include <QLabel>
#include <QHBoxLayout>
#include "mydelegate.h"

namespace Ui {
class MainWindow;
}

class MyItemWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MyItemWidget(const QIcon& icon, const QString& name, QWidget *parent = nullptr);
    ~MyItemWidget();
private:
    QLabel *iconLabel;
    QLabel *nameLabel;
    QSpacerItem *hSpaceItem;
    QSpacerItem *hSpaceItem1;
    QHBoxLayout *layout;
};

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

思路二缺陷

因为对于QListWidget QTableWidget等。如果在stylesheet中把为状态为selecteditem背景色设置为深色那么前景色(字体的颜色)会变成比较浅的颜色来做一个区分。如果使用思路二那么将没有这种效果。
在这里插入图片描述
如果你想通过QlistWidget点击某个item的信号来控制label的颜色,那么这是可行的。只是你可能会在遇到一个坑,那就是伪状态为:selected:!actived没有进行控制。

思路三

通过delegate控制,将用于画图的rectangle左边缩短一截。这样导致的问题是,item区域有部分rectangle没法使用样式表控制,且只能控制icon相对于左侧的位置。
MyDelegate.cpp

#include "mydelegate.h"
#include <QDebug>

MyDelegate::MyDelegate(QObject *parent) : QStyledItemDelegate(parent)
{

}

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//    QPixmap icon = index.data(Qt::DecorationRole).value<QIcon>().pixmap(15 , option.rect.height() - 5);
//    QString text = index.data(Qt::DisplayRole).toString();
//    QAbstractItemModel *model = (QAbstractItemModel*)index.model();
//    model->setData(index, QVariant::fromValue(QIcon()), Qt::DecorationRole);
//    model->setData(index, QVariant::fromValue(QString()), Qt::DisplayRole);

//    QStyleOptionViewItem op(option);
//    QStyledItemDelegate::paint(painter, op, index);
//    painter->drawPixmap(op.rect.x() + 5, op.rect.y() + 5, 15, op.rect.height() - 5, icon);
//    painter->drawText(op.rect.x() + 5 + 15 + 30, op.rect.height() / 2, text);

    QStyleOptionViewItem op(option);
    op.rect = QRect(op.rect.x() + 30, op.rect.y(), op.rect.width(), op.rect.height());
    QStyledItemDelegate::paint(painter, op, index);
}

思路四

通过delegate,让delegate不绘制icon和text。icon和text有自己来手动绘制。想法很美好但是现实根本行不通
MyDelegate.cpp

#include "mydelegate.h"
#include <QDebug>

MyDelegate::MyDelegate(QObject *parent) : QStyledItemDelegate(parent)
{

}

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    qDebug() << index.row();
    QPixmap icon = index.data(Qt::DecorationRole).value<QIcon>().pixmap(15 , option.rect.height() - 5);
    QString text = index.data(Qt::DisplayRole).toString();
    QAbstractItemModel *model = const_cast<QAbstractItemModel*>(index.model());
    model->setData(index, QVariant::fromValue(QIcon()), Qt::DecorationRole);
    model->setData(index, QVariant::fromValue(QString()), Qt::DisplayRole);

    QStyleOptionViewItem op(option);
    painter->drawPixmap(op.rect.x() + 5, op.rect.y() + 5, 15, op.rect.height() - 5, icon);
    painter->drawText(op.rect.x() + 5 + 15 + 30, op.rect.height() / 2, text);

    QStyledItemDelegate::paint(painter, op, index);
}

思路四效果
在这里插入图片描述
效果就是没有任何效果。跪求大佬解答为什么没有效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值