Есть ли способ рассчитать высоту QStandardItem?

Я создал расширяемый 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, таким образом, я думаю, что это очень-очень болезненно.


person Bahramdun Adil    schedule 20.11.2018    source источник
comment
QStandardItem - это не визуальный элемент, а элемент, хранящий данные. Геометрическая задача зависит от делегата, у которого есть метод sizeHint, поэтому проблема в делегате. Чтобы дать вам решение, он показывает код делегата   -  person eyllanesc    schedule 20.11.2018
comment
@eyllanesc Прежде всего, спасибо за ответ! Я не нашел в Delegate ничего, что передавало бы ListView правильную высоту и ширину. Можете ли вы показать мне, как я могу передать высоту деталей в ListView, я могу вычислить высоту деталей, но нет способа установить высоту, чтобы получить ее обратно при нажатии элемента?   -  person Bahramdun Adil    schedule 20.11.2018
comment
@BahramdunAdil, я думал, тебе не нравится решение. Ответ остается непринятым, но вы используете мой код. Это не похоже на честную игру. Я создал расширяемый ListView звучит как святая правда.   -  person scopchanov    schedule 21.11.2018
comment
@scopchanov Проблема все еще остается нерешенной, поэтому, когда функция будет полностью реализована, я вернусь, спасибо и приму ответы, которые действительно решили проблему. Кстати, ваш ответ получил одобрение. А также ваше решение не было расширяемым представлением элементов. А также я не использовал ваш код ни одной строчки. Потому что я не хочу твоего решения. Спасибо!!   -  person Bahramdun Adil    schedule 21.11.2018
comment
@BahramdunAdil, какая проблема остается нерешенной? Вы задали вопрос и получили ответ с рабочим примером. Затем вы пожаловались, что это слишком сложно для вас. Хотя вы использовали мое решение и даже не упомянули (в своем текущем вопросе), откуда вы его взяли. С таким настроем вам не особо помогут. Но самое приятное то, что я знаю, как подогнать высоту развернутого элемента к тексту, потому что я написал код, а вы - нет.   -  person scopchanov    schedule 21.11.2018
comment
@scopchanov Помимо голосования, я также принял ваш ответ, теперь вы можете расслабиться. Кстати, спасибо за все ваши усилия!   -  person Bahramdun Adil    schedule 21.11.2018


Ответы (1)


Если вы хотите установить нестандартный размер, вы должны использовать метод 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();
}

введите здесь описание изображения

person eyllanesc    schedule 20.11.2018
comment
Спасибо за ответ, я попробовал ваше решение, но проблема не решена полностью. Теперь в sizeHint (), когда я указал правильную высоту, и после того, как я изменил ширину (до небольшого размера) окна, я потеряю значок расширения, затем, когда я изменю его на большую ширину, а затем на меньшую, Я тоже теряю Иконки. - person Bahramdun Adil; 21.11.2018
comment
@BahramdunAdil, если вы понимаете, что ваша проблема зависит от вашей реализации, и я могу помочь вам только тогда, когда вы предоставите минимальный воспроизводимый пример. - person eyllanesc; 21.11.2018
comment
Спасибо! @eeyllanesc! Хорошо, я постараюсь опубликовать код, потому что код такой длинный, не очень честно размещать здесь, что заставляет читать вопрос. - person Bahramdun Adil; 21.11.2018
comment
@eyllanesc, к сожалению, это пустая трата времени. OP не оценит ваши усилия. - person scopchanov; 21.11.2018
comment
@BahramdunAdil минимальный воспроизводимый пример не относится к коду вашего проекта, но если ваш код обширен, вы создаете другой проект, ориентированный на функциональность, например, мой код - это возможное начало, мой код фокусируется только на функциональности. - person eyllanesc; 21.11.2018
comment
@scopchanov Это решение OP, я не буду судить о ваших действиях, потому что здесь OP не оценивается (если он не нарушает правила), кроме того, ответ не только для OP, это для сообщества :-) - person eyllanesc; 21.11.2018
comment
@eyllanesc Большое спасибо, брат, ты лучший. - person Bahramdun Adil; 21.11.2018
comment
@BahramdunAdil Я рекомендую вам постараться и предоставить на раннем этапе минимальный воспроизводимый пример, помните, что хороший вопрос так же ценен, как хороший ответ. - person eyllanesc; 21.11.2018
comment
@eyllanesc Привет, сэр! Я пробовал много способов реализовать Qt ListView, но, к сожалению, он не работал, мне не удалось вычислить необходимую высоту для элемента, я отредактировал вопрос, вы можете взглянуть на него. Заранее спасибо!! - person Bahramdun Adil; 29.11.2018