Я создал расширяемый ListView, который расширяется от QListView, все работает хорошо, когда я просто хочу показать данные заголовка (элемент, который не раскрывается), потому что я дал ему жестко запрограммированную высоту, которая равна 64, детали появляются при расширении вещь. Но проблема в том, что я не знаю точную высоту деталей, потому что детали могут состоять из одной строки или более, я хочу подогнать высоту предмета в соответствии с содержанием предмета.
Вот код, который обрабатывает прослушиватель кликов, когда элемент разворачивается или разворачивается:
LogListItemDelegate *delegate = static_cast<LogListItemDelegate *>(itemDelegate());
QStandardItem *item = static_cast<QStandardItemModel *>(model())->itemFromIndex(index);
bool expand = delegate->isExpandable() && mapFromGlobal(QCursor::pos()).x() >= visualRect(index).width() - 48;
bool expanded = index.data(LogListItemDelegate::DT_Expanded).toBool();
// here the height returned is header height, no containing the details which it is in expanding mode
int height = item->sizeHint().height();
if (!expanded) {
item->setData(true, LogListItemDelegate::DT_Expanded);
item->setSizeHint(QSize(0, 150)); // 150 here must be dynamically calculated
} else {
item->setData(false, LogListItemDelegate::DT_Expanded);
item->setSizeHint(QSize(0, 64)); // 64 is the header height, no prolem
}
Теперь вопрос: Как рассчитать высоту при раскрытии предмета?
Результат:
Редактировать:
It is when I want to add the message to the list
void LogListView::addMessage(const QJsonObject &msg, const bool append)
{
static int id = 1; // unique id for log items
auto *item = new QStandardItem();
item->setEditable(false);
item->setData(QString("%1").arg(id++, 5, 10, QChar('0')), LogListItemDelegate::DT_Id);
item->setData(msg["icon"], LogListItemDelegate::DT_ICON);
item->setData(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"), LogListItemDelegate::DT_Timestamp);
item->setData(msg["title"], LogListItemDelegate::DT_Title);
item->setData(msg["subtitle"], LogListItemDelegate::DT_Subtitle);
item->setData(msg["details"], LogListItemDelegate::DT_Details);
item->setData(false, LogListItemDelegate::DT_Expanded);
// here I am unable to calculate the height, because the details does not have a specific height to set here,
// so when append the item to the list it is unvisible. If set the height 64, it is the exact height of the item without details, which is good
//item->setSizeHint(QSize(0, 64));
static_cast<QStandardItemModel *>(model())->appendRow(item);
scrollToBottom();
}
Это код в sizeHint ()
QSize LogListItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
bool expanded = index.data(DT_Expanded).toBool();
QFont fntDetials = option.font;
fntDetials.setPointSize(12);
QRect r = option.rect;
QFontMetrics fm(fntDetials);
QString details = index.data(DT_Details).toString();
QRect br = fm.boundingRect(r, Qt::TextWordWrap, details);
return QSize(option.rect.width(), br.height()+64);
}
К сожалению, не работает …, я думаю, что Qt может посмотреть Android ListView и его функциональность по переработке для решения проблемы ListView, таким образом, я думаю, что это очень и очень больно.
Если вы хотите установить нестандартный размер, вы должны использовать метод sizeHint из QStyledItemDelegate, например:
#include <QApplication>
#include <QStyledItemDelegate>
#include <QListView>
#include <QStandardItemModel>
class HeightDelegate: public QStyledItemDelegate
{
public:
using QStyledItemDelegate::QStyledItemDelegate;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override{
QSize s = QStyledItemDelegate::sizeHint(option, index);
// some calculation
int h = (index.row()+1)*20;
s.setHeight(h);
return s;
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QListView w;
QStandardItemModel model;
HeightDelegate delegate;
w.setItemDelegate(&delegate);
w.setModel(&model);
for(int i=0; i<8; i++){
QStandardItem *it = new QStandardItem(QString::number(i));
it->setBackground(QBrush(QColor(qrand()%255, qrand()%255, qrand()%255)));
model.appendRow(it);
}
w.show();
return a.exec();
}
Других решений пока нет …