[Solved] QListWidget for displaying items in QTableView's cells
-
Hi,
I'm trying to use QListWidgets to display QStringLists in the cells of a QTableView. To do so, I subclassed QStyledItemDelegate and render the QListWidget in the paint() method. This works fine so far, the only problem I have is, that option.rect.topLeft() in paint(..., const QStyleOptionViewItem& option, ...) does not correspond to the top left corner of the corresponding cell. It seems to be off by the dimensions of the top left header cell, as this screenshot suggests:
!http://oi55.tinypic.com/2n0snf9.jpg(screenshot)!
So my question is: how do I get the right coordinates for correctly rendering the QListWidgets in QTableView's cells? Working example code is below.
Thanks,
FrankMultipleSelectDelegate.h:
@
#ifndef MULTIPLESELECTDELEGATE_H
#define MULTIPLESELECTDELEGATE_H#include <QStyledItemDelegate>
class MultipleSelectDelegate : public QStyledItemDelegate {
Q_OBJECTpublic:
MultipleSelectDelegate(QObject* parent = 0);void paint(QPainter* painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const;QSize sizeHint(const QStyleOptionViewItem& option,
const QModelIndex& index) const;
};#endif // MULTIPLESELECTDELEGATE_H
@MultipleSelectDelegate.cpp:
@
#include "MultipleSelectDelegate.h"
#include <QStyledItemDelegate>
#include <QListWidget>
#include <QStringList>MultipleSelectDelegate::MultipleSelectDelegate(QObject* parent)
: QStyledItemDelegate(parent) {}void MultipleSelectDelegate::paint(QPainter* painter,
const QStyleOptionViewItem& option, const QModelIndex& index) const {
QStringList list = index.data().toStringList();
QListWidget list_widget;
list_widget.addItems(list);
list_widget.render(painter, option.rect.topLeft());
}QSize MultipleSelectDelegate::sizeHint(const QStyleOptionViewItem& option,
const QModelIndex& index) const {
QStringList list = index.data().toStringList();
QListWidget list_widget;
list_widget.addItems(list);
return list_widget.sizeHint();
}
@TableModel.h:
@
#ifndef TABLEMODEL_H
#define TABLEMODEL_H#include <QAbstractTableModel>
#include <QModelIndex>
#include <QList>
#include <QObject>
#include <QVariant>class TableModel : public QAbstractTableModel {
Q_OBJECTpublic:
explicit TableModel(QObject* parent = 0);int rowCount(const QModelIndex&) const;
int columnCount(const QModelIndex&) const;
QVariant data(const QModelIndex& index, int role) const;
private:
QList<QVariant> data_;
};#endif // TABLEMODEL_H
@TableModel.cpp:
@
#include "TableModel.h"
#include <QStringList>TableModel::TableModel(QObject* parent) : QAbstractTableModel(parent) {
QStringList list1, list2;
list1 << "one" << "two" << "three" << "four";
list2 << "1111" << "2222" << "3333" << "4444";
data_ << list1 << list2;
}int TableModel::rowCount(const QModelIndex&) const {
return data_.size();
}int TableModel::columnCount(const QModelIndex&) const {
return 1;
}QVariant TableModel::data(const QModelIndex& index, int role) const {
if (!index.isValid())
return QVariant();if (index.row() >= data_.size())
return QVariant();if (role == Qt::DisplayRole) {
return data_.at(index.row());
}
return QVariant();
}
@main.cpp:
@
#include <QApplication>
#include <QTableView>
#include "MultipleSelectDelegate.h"
#include "TableModel.h"int main(int argc, char *argv[]) {
QApplication app(argc, argv);QTableView* table = new QTableView();
TableModel* model = new TableModel(table);
MultipleSelectDelegate* delegate = new MultipleSelectDelegate(table);
table->setModel(model);
table->setItemDelegate(delegate);
table->show();return app.exec();
}
@ -
Do you need the list widget for some functionality or do you just use it to "ease" the display of the string list? If you do the latter, there surely would be more elegant and efficient ways to do this.
As a first thought, I would try to change the data() method of your model and have it return a string for the Qt::DisplayRole:
@
QVariant MyModel::data(const QModelIndex &index, int role)
{
if(role == Qt::DisplayRole) {
return theStringList.join("\n");
} else {
// your other role code here....
}
}
@The standard delegates handle multiline text.
-
Just to explain why I've choosen a QListWidget for displaying a list of strings: My final goal is to implement an item delegate for multiple selection of objects in a list. If the list is displayed some items of it should be selected and when the user edits the cell it should be possible to select other items or deselect already selected items. I thought the easiest way to accomplish a multiple select delegate is to use a QListWidget for displaying and editing the selections.
-
I found a solution for my problem by looking again at the "Star Delegate Example":http://doc.qt.nokia.com/latest/itemviews-stardelegate.html. Instead of calling render(...) with option.rect.topLeft() as offset, translating painter with option.rect.topLeft() before calling render(...) fixes my problem:
@
list_widget.render(painter, option.rect.topLeft());
@@
painter->translate(option.rect.topLeft());
list_widget.render(painter);
@So apparently I didn't understand what the effect of calling "QWidget::render(...) with a targetOffset":http://doc.qt.nokia.com/latest/qwidget.html#render-2 means.
Thanks again for all your input.