前言
在对于一些简单的项目时,我们可能会使用 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);
}