有没有一种方法可以计算QStandardItem的高度?

时间:2018-11-20 16:23:23

标签: c++ qt qt5 qlistview qstandarditem

我创建了一个从QListView扩展的可扩展ListView,当我只想显示Header数据(未扩展的项目)时,一切工作都很好,因为我给它设置了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
        }

现在的问题是:项目展开时如何计算高度?

结果:

enter image description here

编辑:

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问题,这样,我认为这非常痛苦。

1 个答案:

答案 0 :(得分:2)

如果要设置自定义大小,则应使用QStyledItemDelegate的sizeHint方法,例如:

#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();
}

enter image description here