Qt5 Подклассы QStyledItemDelegate Форматирование
Я разрабатываю графический интерфейс для базы данных SQLite в Qt5. я использую QSqlQueryModel
а также QTableView
для хранения и отображения данных.
Затем я создал пользовательский делегат для замены числовых значений некоторых столбцов их литералами в табличном представлении (например, 1 = "Hello", 2 = "World") с помощью оператора switch.
Делегат отображает данные так, как должен, и работает функционально. Однако столбцы, которые закрашивает пользовательский делегат, имеют другой формат по сравнению с методом рисования по умолчанию: QStyledItemDelegate
, Значения находятся в верхнем левом углу, а не в центре слева, измененный столбец больше не расширяет столбец автоматически, чтобы отобразить полные значения, а ячейки в столбце не становятся синими или имеют пунктирный контур при выборе.
Я создал этот пример программы:
#include <QApplication>
#include <QModelIndex>
#include <QPainter>
#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include <QTableView>
class TestDelegate: public QStyledItemDelegate {
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index)
const Q_DECL_OVERRIDE
{
if (index.column() == 0) {
int value = index.model()->data(index, Qt::DisplayRole).toInt();
QString str;
switch (value) {
case 1:
str = "Hello0000";
break;
case 2:
str = "World0000";
break;
}
if (option.state.testFlag (QStyle::State_Selected)) {
painter->fillRect(option.rect, option.palette.highlight());
qApp->style()->drawItemText(painter, option.rect, option.displayAlignment, option.palette, true, str, QPalette::HighlightedText);
} else {
painter->drawText(option.rect, option.displayAlignment, str);
}
} else {
return QStyledItemDelegate::paint(painter, option, index);
}
}
};
int main(int argc, char **argv) {
QApplication app(argc, argv);
QStandardItemModel model(2, 2);
model.setHorizontalHeaderItem(0, new QStandardItem(QString("A")));
model.setHorizontalHeaderItem(1, new QStandardItem(QString("B")));
model.setData(model.index(0, 0, QModelIndex()), 1);
model.setData(model.index(1, 0, QModelIndex()), 2);
model.setItem(0, 1, new QStandardItem(QString("Hello")));
model.setItem(1, 1, new QStandardItem(QString("World0000")));
QTableView view;
view.setItemDelegate(new TestDelegate);
view.setModel(&model);
view.resizeColumnsToContents();
view.show();
app.exec();
}
Это исправляет выравнивание текста, добавляя options.displayAlignment
в painter->drawText()
; Я также добавил дополнительный код в if(option.state & QStyle::State_Selected)
утверждение, что рисует ячейку в соответствии с ее состоянием выбора. Поэтому, если он не выбран, текст будет черным, если текст станет белым, а фон - синим. Однако я все еще не могу заставить столбцы расширяться, чтобы соответствовать содержимому ячеек или добавить пунктирную линию вокруг внешней части ячейки, как это происходит со стандартным делегатом.
Есть ли простой способ сохранить стиль таблицы по умолчанию при использовании моего пользовательского метода рисования?
1 ответ
Делегат - довольно обходной и ненужный способ сделать это. У нас уже есть представление о том, что элементы прекрасно рисуются, нет необходимости переделывать это. Нам нужно только передать измененные данные в представление. Таким образом, мы вставляем QIdentityProxyModel
viewmodel между источником и представлением.
// https://github.com/KubaO/stackrun/tree/master/questions/proxy-reformat-39244309
#include <QtWidgets>
class RewriteProxy : public QIdentityProxyModel {
QMap<QVariant, QVariant> m_read, m_write;
int m_column;
public:
RewriteProxy(int column, QObject * parent = nullptr) :
QIdentityProxyModel{parent}, m_column{column} {}
void addReadMapping(const QVariant & from, const QVariant & to) {
m_read.insert(from, to);
m_write.insert(to, from);
}
QVariant data(const QModelIndex & index, int role) const override {
auto val = QIdentityProxyModel::data(index, role);
if (index.column() != m_column) return val;
auto it = m_read.find(val);
return it != m_read.end() ? it.value() : val;
}
bool setData(const QModelIndex & index, const QVariant & value, int role) override {
auto val = value;
if (index.column() == m_column) {
auto it = m_write.find(value);
if (it != m_write.end()) val = it.value();
}
return QIdentityProxyModel::setData(index, val, role);
}
};
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QStandardItemModel model{2,2};
model.setData(model.index(0, 0), 1);
model.setData(model.index(1, 0), 2);
model.setData(model.index(0, 1), "Zaphod");
model.setData(model.index(1, 1), "Beeblebrox");
RewriteProxy proxy{0};
proxy.setSourceModel(&model);
proxy.addReadMapping(1, "Hello");
proxy.addReadMapping(2, "World");
QTableView ui;
ui.setModel(&proxy);
ui.show();
return app.exec();
}