В одном из моих проектов я использую QTableWidget
для того, чтобы отобразить некоторые сложные вычислительные результаты. Чтобы повысить удобочитаемость таблицы, мне нужно отобразить два выровненных значения внутри одной ячейки таблицы.
Позже я хочу настроить виджет еще больше, используя цвета или стрелки и т.д ..
Для этого я получил от QStyledItemDelegate
и я позвонил table ->setItemDelegate(new TwoNumbersDelegate)
на моем QTableWidget
пример.
По некоторым причинам QFrame
никогда не отображается. Я действительно все перепробовал. Странно, звонок в drawLine
дает некоторый результат, но только в левой ячейке сверху.
Моя идея заключается в том, что призвание mFrame->render(...)
это не правильный способ сделать это, но каков правильный путь?
Мой включаемый файл:
#pragma once
#include <QStyledItemDelegate>
class QLabel;
class TwoNumbersDelegate : public QStyledItemDelegate {
public:
TwoNumbersDelegate(QObject* parent = nullptr);
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
private:
QLabel* mLeft;
QLabel* mRight;
QFrame* mFrame;
};
мой cpp
-Файл это:
#include "TwoNumbersDelegate.h"#include <QLabel>
#include <QPainter>
#include <QHBoxLayout>
TwoNumbersDelegate::TwoNumbersDelegate(QObject* parent /*= nullptr*/) : QStyledItemDelegate(parent)
{
mLeft = new QLabel("%1");
mRight = new QLabel("%2");
mFrame = new QFrame;
mFrame->setLayout(new QHBoxLayout);
mFrame->layout()->addWidget(mLeft);
mFrame->layout()->addWidget(mRight);
}
void TwoNumbersDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
auto data=index.data(Qt::EditRole);
auto list=data.toList();
if (list.size() != 2) {
QStyledItemDelegate::paint(painter, option, index);
}
auto leftValue=list.at(0).toDouble();
auto rightValue=list.at(1).toDouble();
mLeft->setText(QString("%1").arg(leftValue));
mRight->setText(QString("%2").arg(rightValue));
mLeft->render(painter, QPoint(), option.rect);
painter->drawLine(4, 4, 7, 7); // Draws Line, but not in every cell of my table?
}
QSize TwoNumbersDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return mFrame->minimumSizeHint();
}
Несколько потенциальных проблем здесь:
Поскольку виджет невидим, компоновка не рассчитывается, поэтому вещи могут быть вычеркнуты, вызовы изменения размера игнорируются и т. Д.
Чтобы убедиться, что макет обновлен, в конструкторе добавьте
mFrame->setAttribute(Qt::WA_DontShowOnScreen, true);
mFrame->show();
Это заставляет виджет вести себя так, как будто он виден (что мы хотим), но не рисует ничего на экране напрямую.
Рисование с делегатом обрезается до ячейки, поэтому, если вы рисуете не в том месте, вы вообще ничего не увидите.
Границы ячейки задаются options.rect
и эти координаты в терминах qtableview. Таким образом, ваша команда drawline рисует только в верхней левой ячейке.
Это отсечение также означает, что вам не нужно беспокоиться о том, какую область виджета визуализировать, просто переведите рисовальщик в координаты ячейки и нарисуйте весь виджет.
painter->save();
painter->translate(option.rect.topLeft());
mFrame->render(painter, QPoint(), QRegion(), QWidget::DrawChildren );
painter->restore();
Все вместе, вот обновленный файл .cpp:
TwoNumbersDelegate::TwoNumbersDelegate(QObject* parent /*= nullptr*/) : QStyledItemDelegate(parent)
{
mLeft = new QLabel("%1");
mRight = new QLabel("%2");
mFrame = new QFrame;
mFrame->setLayout(new QHBoxLayout);
mFrame->layout()->addWidget(mLeft);
// you could add a spacer here maybe
mFrame->layout()->addWidget(mRight);
mFrame->setAttribute(Qt::WA_DontShowOnScreen, true);
mFrame->show();
}
void TwoNumbersDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
auto data=index.data(Qt::EditRole);
auto list=data.toList();
if (list.size() != 2) {
QStyledItemDelegate::paint(painter, option, index);
}
mLeft->setText(list.at(0).toString());
mRight->setText(list.at(1).toString());
mFrame->resize(opt.rect.size());
// if there are still layout problems maybe try adding:
// mFrame->layout()->invalidate();
// mFrame->layout()->activate();
painter->save();
painter->translate(option.rect.topLeft());
mFrame->render(painter, QPoint(), QRegion(), QWidget::DrawChildren );
// painter->drawLine(4, 4, 7, 7); // Draws Line in every cell now
painter->restore();
}
QSize TwoNumbersDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return mFrame->minimumSizeHint();
}
Дайте мне знать, если вам нужна дополнительная помощь. Кроме того, предупреждение: я не так много, чтобы запустить это через компилятор, поэтому дайте мне знать, если вам все еще нужна помощь, или если есть какие-то небольшие ошибки, чтобы исправить.
Других решений пока нет …