Прямоугольник на старом выбранном элементе должен перейти к текущему выбранному элементу, когда выбор был изменен. Я сделал это, но у меня есть проблемы.
- Использование SelectWidget дочерний виджет ListView. Прямоугольник, нарисованный в paintEvent из SelectWidget . Я изменяю геометрию (ось Y) на Выберите виджет , чтобы переместить его. Проблема заключается в том, что SelectWidget перекрывает текст элемента.
- Для решения проблемы # 1 я рисую прямоугольник в paint () функции ListItemDelegate , когда анимация закончена. Момент переключения между SelectWidget и stati c прямоугольник выбора элемента.
Как решить проблему № 1 и не получить проблему № 2.
Источник код:
listview.h
...
class SelectWidget;
class ListView : public QListView {
Q_OBJECT
Q_PROPERTY(int offset READ offset WRITE setOffset)
public:
ListView(QWidget* parent = nullptr);
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override;
int offset();
void setOffset(int off);
void animationFinished();
bool canDrawSelected() const {
return m_drawSelected;
}
private:
QPropertyAnimation* m_anim = nullptr;
SelectWidget* m_selectWidget = nullptr;
bool m_drawSelected = true;
};
class SelectWidget : public QWidget {
public:
SelectWidget(QWidget* parent)
: QWidget(parent)
{
}
void paintEvent(QPaintEvent *event) override {
if (!m_draw) return;
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::NoPen);
painter.setOpacity(0.5);
painter.setBrush(QColor(47, 74, 90));
painter.drawRect(QRectF(0, 0, width(), height()));
QRectF lineRect(0, 0, 5, height());
painter.setOpacity(1.0);
painter.setBrush(QColor(0, 123, 255));
painter.drawRect(lineRect);
}
public:
bool m_draw = true;
};
listview. cpp
...
ListView::ListView(QWidget *parent)
: QListView(parent)
{
setItemDelegate(new ListItemDelegate(this));
m_selectWidget = new SelectWidget(this);
m_anim = new QPropertyAnimation(this, "offset", this);
connect(m_anim, &QPropertyAnimation::finished, this, &ListView::animationFinished);
}
void ListView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
m_selectWidget->m_draw = (selected.size() != 0);
if (deselected.size() == 0) {
if (selected.size() > 0) {
setOffset(selected.indexes().begin()->row() *
itemDelegate(*selected.indexes().begin())->sizeHint(QStyleOptionViewItem(), QModelIndex()).height());
}
m_selectWidget->m_draw = false;
return;
}
if (selected.size() > 0) {
auto geom = m_selectWidget->geometry();
geom.setWidth(visualRect(*selected.indexes().begin()).width());
geom.setHeight(itemDelegate()->sizeHint(QStyleOptionViewItem(), QModelIndex()).height());
m_selectWidget->setGeometry(geom);
}
if (deselected.indexes().begin()->row() == selected.indexes().begin()->row()) return;
//move from deselected to selected
int deselectedIndex = deselected.indexes().begin()->row();
int selectedIndex = selected.indexes().begin()->row();
m_anim->setStartValue(offset());
m_anim->setEndValue(selectedIndex * itemDelegate(*selected.indexes().begin())->sizeHint(QStyleOptionViewItem(), QModelIndex()).height());
m_anim->setDuration(100);
m_anim->start();
m_drawSelected = false;
}
int ListView::offset()
{
return m_selectWidget->geometry().y();
}
void ListView::setOffset(int off)
{
auto geometry = m_selectWidget->geometry();
m_selectWidget->setGeometry(geometry.x(), off, geometry.width(), geometry.height());
m_selectWidget->update();
}
void ListView::animationFinished()
{
m_selectWidget->m_draw = false;
m_drawSelected = true;
m_selectWidget->update();
update();
}
listitemdelegate . cpp
/* inherit QItemDelegate */
QSize ListItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &) const
{
QSize itemSize(option.rect.size());
itemSize.setHeight(35);
return itemSize;
}
void ListItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (index.column() != 0) {
QItemDelegate::paint(painter, option, index);
return;
}
QString text;
QColor textColor = option.state & QStyle::State_Selected ? QColor(255, 255, 255) : QColor(255, 255, 255, 150);
ListView* parentW = qobject_cast<ListView*>(parent());
if (parentW->model()) {
text = parentW->model()->data(index).toString();
}
painter->setRenderHint(QPainter::Antialiasing);
if (option.state & QStyle::State_Selected) {
if (parentW->canDrawSelected()) {
painter->save();
painter->fillRect(option.rect, QBrush(option.state & QStyle::State_MouseOver ? QColor(51, 82, 99) : QColor(47, 74, 90, 0.5 * 255)));
QRectF lineRect;
lineRect.setX(option.rect.x());
lineRect.setY(option.rect.y());
lineRect.setWidth(5);
lineRect.setHeight(option.rect.height());
painter->fillRect(lineRect, QBrush(QColor(0, 123, 255)));
painter->restore();
}
}
else if (option.state & QStyle::State_MouseOver) {
painter->save();
painter->fillRect(option.rect, QBrush(QColor(40, 60, 71)));
painter->restore();
}
painter->save();
painter->setPen(textColor);
QRectF textRect(option.rect);
textRect.setX(textRect.x() + 15);
painter->drawText(textRect, Qt::AlignVCenter, text);
painter->restore();
}