【问题标题】:Is there a way to calculate the height of the QStandardItem?有没有办法计算 QStandardItem 的高度?
【发布时间】:2018-11-20 16:23:22
【问题描述】:

我创建了一个从 QListView 扩展的可扩展 ListView,当我只想显示标题数据(未扩展的项目)时一切正常,因为我给它一个硬编码的高度,即 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
        }

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

结果:

编辑:

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的问题,这样一来,我觉得是非常非常痛苦的。

【问题讨论】:

  • QStandardItem 不是视觉元素,而是保存数据的元素。几何任务取决于具有 sizeHint 方法的委托,因此问题出在委托中。为了给你一个解决方案,它显示了委托的代码
  • @eyllanesc 首先感谢您的回复!我在 Delegate 中没有找到任何将正确的高度和宽度传递给 ListView 的东西。你能告诉我如何将细节的高度传递给 ListView,我可以计算细节的高度,但是没有办法设置高度以在单击项目时将其取回?
  • @BahramdunAdil,我以为你不喜欢这个解决方案。 The answer 未被接受,但您正在使用我的代码。这似乎不是一场公平的比赛。 我创建了一个可扩展的 ListView 听起来很神圣。
  • @scopchanov 问题仍然没有解决,所以当功能完全实现时,我会回来,谢谢并接受真正解决问题的答案。顺便说一句,您的答案已获得投票。而且您的解决方案也不是可扩展的项目视图。而且我连一行都没有使用你的代码。因为你的解决方案不是我想要的。谢谢!!
  • @BahramdunAdil,哪个问题仍未解决?您提出了一个问题并通过工作示例得到了答案。然后你抱怨它对你来说太复杂了。不过,您使用了我的解决方案,甚至没有提及(在您当前的问题中)您从哪里得到它。有了这样的态度,你不会得到太多帮助。但最好的部分是,我知道如何使展开项的高度适合文本,因为我已经编写了代码,而你没有。

标签: c++ qt qt5 qlistview qstandarditem


【解决方案1】:

如果要设置自定义尺寸,应该使用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();
}

【讨论】:

  • 感谢您的回复,我已经尝试过您的解决方案,但问题并没有完全解决。现在在 sizeHint() 中,当我给出正确的高度,当我改变窗口的宽度(小尺寸)之后,我失去了展开图标,然后当我把它改成更大的宽度,然后再变小,我也失去了图标。
  • @BahramdunAdil 如果您意识到您的问题取决于您的实施,我只能在您提供minimal reproducible example 时为您提供帮助。
  • @BahramdunAdil A minimal reproducible example 不是指您项目的代码,但如果您的代码很广泛,那么您创建另一个专注于功能的项目,例如我的代码是一个可能的开始,我的代码只关注功能。
  • @scopchanov 那是 OP 的决定,我不会评判你的行为,因为这里的 OP 不被评判(除非它违反规则),除了答案不仅适用于 OP,它是为社区服务的:-)
  • @BahramdunAdil 我建议您努力并尽早提供minimal reproducible example,请记住,一个好的问题与一个好的答案一样有价值。
猜你喜欢
  • 2012-05-22
  • 1970-01-01
  • 2021-10-17
  • 2015-09-24
  • 1970-01-01
  • 2021-12-06
  • 2018-02-24
  • 2011-01-09
  • 1970-01-01
相关资源
最近更新 更多