QListWidget使用setItemWidget导致的问题以及解决

前言

在对于一些简单的项目时,我们可能会使用 setItemWidget 通过自定义的 widget来设置listwidget的子项。但是这样往往会导致一些问题。下面探讨这些问题,并且提供自己的解决方案。

无法很好的控制listwidget 子项的外观

在这里插入图片描述
这里使用自定义 widget作为listwidget的子项。效果如下
在这里插入图片描述
可以看到 widget背景变得透明了,出现的原因是作为 listwidget的子项那么它的样式表应该是由listwidget决定的。让我们修改listwidget的样式表看看。

QListView::item{
	background-color:#ffffbf;
}
QListView::item:selected{
	background-color:#0078d7;
}

效果如下
在这里插入图片描述
这样导致的问题是 project two这几个字并没有变色。选中时通常背景是深色,字体颜色是白色。也就是说虽然能够控制整体背景但是对于自定义widget上的控件的样式却不能够控制。

解决方案

关键思路就是,[signal] void QListWidget::currentRowChanged(int currentRow)即使 listwidget的子项是使用的 自定义的widget在点击后任然可以触发该信号,那么我们就可以为自定义的 widget 设置一个是否被选中的属性通过该属性来控制 widget的外观。具体代码如下。
myWidget
myWidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>
#include <QMouseEvent>

namespace Ui {
class myWidget;
}

class myWidget : public QWidget
{
    Q_OBJECT
    //自定义属性,写完该部分可以使用alt + enter 快捷键自动补全
    Q_PROPERTY(bool isSelected READ getIsSelected WRITE setIsSelected NOTIFY isSelectedChanged)

public:
    explicit myWidget(QWidget *parent = nullptr);
    ~myWidget();
    void setName(const QString& name);

    bool getIsSelected() const
    {
        return m_isSelected;
    }

public slots:
    void slot_isSelectedChanged(bool isSelected);
    void setIsSelected(bool isSelected)
    {
        if (m_isSelected == isSelected)
            return;

        m_isSelected = isSelected;
        emit isSelectedChanged(m_isSelected);
    }

signals:
    void isSelectedChanged(bool isSelected);
private:
    Ui::myWidget *ui;
    bool m_isSelected;
};

#endif // MYWIDGET_H

myWidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QDebug>

myWidget::myWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::myWidget)
{
    ui->setupUi(this);
    connect(this, &myWidget::isSelectedChanged, this, &myWidget::slot_isSelectedChanged);
}

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

void myWidget::setName(const QString &name)
{
    ui->label_2->setText(name);
}

void myWidget::slot_isSelectedChanged(bool isSelected)
{
    if(isSelected)
    {
        ui->frame->setStyleSheet("QFrame#frame{background-color:#0078d7}");
        ui->label_2->setStyleSheet("QLabel{color:#ffffff}");
        ui->comboBox->setStyleSheet("QComboBox{color:#ffffff;background-color:transparent}"
                                    "QComboBox QAbstarctItemView{background:white}");
    }
    else
    {
        ui->frame->setStyleSheet("QFrame#frame{background-color:#ffffbf}");
        ui->label_2->setStyleSheet("QLabel{color:#000000}");
        ui->comboBox->setStyleSheet("QComboBox{color:#000000;background-color:transparent}"
                                    "QComboBox QAbstarctItemView{background:white}");
    }
}

思考

这里还有一个问题,就是点击 listwidget的子项的combox,虽然可以对combobox进行操作但是发现,listwidget的当前选中项并没有被改变,我们希望的效果是。点击combobox进行操作同时,listwidget的当前选中项移动到该子项上来。因为combobox会对mouseEvent进行响应所以鼠标事件并不会传递到listwidget的子项上。所以该项不能够被选中。

解决方案

自定义一个combobox重写mousePressEvent,new一个mouseEvent将它发送给listwidget即可。以下是示例代码。

#include "mycombobox.h"

myComboBox::myComboBox(QWidget *parent) : QComboBox(parent)
{

}

void myComboBox::mousePressEvent(QMouseEvent *event)
{
    if(this->parentWidget())
    {
        //将相对于combobox的坐标映射到 mywidget上
        QPoint point = this->mapTo(this->parentWidget(), event->pos());
        //new 一个QMouseEvent对象
        QMouseEvent *mouseEvent = new QMouseEvent(event->type(), point, event->button(), event->buttons(), event->modifiers());
        //将这个事件发送给 mywidget
        QApplication::postEvent(this->parentWidget(), mouseEvent);
    }
    QComboBox::mousePressEvent(event);
}

效果图

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值