Неправильная высота форматированного текста (QTextDocument) в элементе, отображаемом пользовательским делегатом элемента [Qt]

У меня есть проблема с высотой текста QTextDocument в моем делегате элемента представлений дерева.

Мои методы paint() и sizeHint() практически одинаковы, но рассчитывают разную высоту текста (один и тот же текст).

Разница в высоте варьируется в зависимости от шрифта. Если все написано в одном размере, то высота верна, но если я использую разные размеры, высота не совпадает.

Я читал тему об использовании метрик шрифта или вычислении формы высоты шрифта paiter.boundingRect, но я не знаю, как использовать это в QTextDocument.

Я думал, что проблема со шрифтом, поэтому я изменил глобальный шрифт на один с кодом ниже. Это не помогло.

 //in main():
     QFont font("MS Shell Dlg 2",8.25,50);
     font.setPointSizeF(8.25);
     QApplication::setFont(font);

Мой код в моем пользовательском элементе Delegate:

 QSize MyItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
 {
    QStyleOptionViewItem options = option;
    initStyleOption(&options, index);

    int scrollBarrWidth = -2;
    if(scrollBarVisible){
    scrollBarrWidth = 10; //options.widget->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
    }
    int checkboxWidth = 0;
    if(checkboxesForConferenceActive){
        checkboxWidth = 18;
    }

    QRect rectLeft(checkboxWidth,0,26,26);
    QRect rectRight((options.widget->rect().right()-30-scrollBarrWidth),0,26,26); 
    QRect rectCenter((rectLeft.right()+5),-2,(options.widget->rect().width()-(rectLeft.width()+rectRight.width()+scrollBarrWidth+checkboxWidth+8+4)),26);  
    QRect boundingRect;

    QString nameText(index.data(Qt::UserRole).toString());
    QString extNoText(index.data(Qt::UserRole+1).toString());
    QString phoneText(index.data(Qt::UserRole+100).toString());

    QTextDocument textDoc;
    textDoc.setDefaultFont(options.font);
    textDoc.setTextWidth(rectCenter.width());
    textDoc.setDocumentMargin(0);

    QTextCursor textCursor(&textDoc);
    QString wholeText("");
    QImage statusIcon(*icoChooser->choseCustomStateImageForSubscriber(index.data(Qt::UserRole+12).toInt()));
    bool wczytajfote = !statusIcon.isNull();

    wholeText.append("<b>");
    wholeText.append(nameText);
    wholeText.append("</b>");
    textCursor.insertHtml(wholeText);
    if(wczytajfote){
    textCursor.movePosition(QTextCursor::EndOfLine, QTextCursor::MoveAnchor);
    textCursor.insertImage(statusIcon.scaledToWidth(12));
    textCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
    } else {
    textCursor.insertHtml("&nbsp");
    }
    wholeText.clear();
    if(!extNoText.isEmpty()){

        wholeText.append("<font color = #005c99>");
        wholeText.append(QString(" ("+extNoText+") "));
        wholeText.append("</font>");
        wholeText.append("<br><font style=\"font-size:10px; color: #6d6d78\">");
        wholeText.append(index.data(Qt::UserRole+4).toString());
        wholeText.append("</font>");
        textCursor.insertHtml(wholeText);

        if(textDoc.idealWidth() < rectCenter.width() ){
            QRect clip(0,0,textDoc.idealWidth(), textDoc.size().height());

            return QSize(textDoc.idealWidth(), textDoc.size().height()+4);
        } else {
            QRect clip(0,0,textDoc.idealWidth(), textDoc.size().height());

            return QSize(textDoc.idealWidth(), textDoc.size().height()+4);
        }
    } else {
        wholeText.append("<br>");
        wholeText.append("<font size = 2 color = #005c99>");
        wholeText.append(QString(" ("+phoneText+") "));
        wholeText.append("</font>");
        textCursor.insertHtml(wholeText);

        QRect clip(0,0,textDoc.idealWidth(), textDoc.size().height());

        return QSize(textDoc.idealWidth(), textDoc.size().height()+6);

    }
 }

и метод рисования практически точно такой же.

 void MyItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
 {      
    QStyleOptionViewItem options = option;
    initStyleOption(&options, index);

    painter->save();
    painter->setRenderHint(QPainter::Antialiasing, true);
    painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
    painter->setRenderHint(QPainter::TextAntialiasing, true);


    options.text = "";

    int scrollBarrWidth = -2;
    if(scrollBarVisible){

    scrollBarrWidth = 10;  //options.widget->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
    }
    int checkboxWidth = 0;
    if(checkboxesForConferenceActive){
        checkboxWidth = 18;
    }

    QRect rectLeft(checkboxWidth,0,26,26);
    QRect rectRight((options.widget->rect().right()-30-scrollBarrWidth),0,26,26); //obliczam na podstawie prostokąta, który jest przed nim i który ma dynamicznie ustawiane wymiary
    QRect rectCenter((rectLeft.right()+5),-2,(options.widget->rect().width()-(rectLeft.width()+rectRight.width()+scrollBarrWidth+checkboxWidth+8+4)),26);  //obliczam prostokąt na podstawie wcześniejszego prostokąta i prostokąta wymiarów okna
    QRect boundingRect;

    QString nameText(index.data(Qt::UserRole).toString());
    QString extNoText(index.data(Qt::UserRole+1).toString());
    QString phoneText(index.data(Qt::UserRole+100).toString());

    painter->translate(options.widget->rect().left(), options.rect.top());

            QTextDocument textDoc;
            textDoc.setTextWidth(rectCenter.width());

            QTextCursor textCursor(&textDoc);
            QString wholeText("");

            QImage statusIcon(*icoChooser->choseCustomStateImageForSubscriber(index.data(Qt::UserRole+12).toInt()));
            bool wczytajfote = !statusIcon.isNull();

            wholeText.append("<b>");
            wholeText.append(nameText);
            wholeText.append("</b>");
            textCursor.insertHtml(wholeText);
            if(wczytajfote){
            textCursor.movePosition(QTextCursor::EndOfLine, QTextCursor::MoveAnchor);
            textCursor.insertImage(statusIcon.scaledToWidth(12));
            textCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
            } else {
            textCursor.insertHtml("&nbsp");
            }
            wholeText.clear();
            if(!extNoText.isEmpty()){

                wholeText.append("<font size = 2 color = #005c99>");
                wholeText.append(QString(" ("+extNoText+") "));
                wholeText.append("</font>");
                wholeText.append("<br><font style=\"font-size:10px; color: #6d6d78\">");
                wholeText.append(index.data(Qt::UserRole+4).toString());
                wholeText.append("</font>");
            } else {
                wholeText.append("<br>");
                wholeText.append("<font size = 2 color = #005c99>");
                wholeText.append(QString(" ("+phoneText+") "));
                wholeText.append("</font>");
            }
            textCursor.insertHtml(wholeText);

            painter->translate(rectCenter.left(), rectCenter.top());

            QRect clip(0,0,textDoc.size().width(), textDoc.size().height());

            textDoc.drawContents(painter, clip);


    painter->restore();
}
}

Текст в sizeHint используется для определения высоты элемента, поэтому теперь он выглядит следующим образом:картина

Я использую 64-битную версию Qt 5.7.1 MSVC 2015 для Windows, но проблема все та же на Ubuntu 16.04 с gcc.

1 ответ

(Опубликовано от имени автора)

Это оказалось моей ошибкой все время.

Следующая строка отвечает в sizeHint() Метод отвечал:

textDoc.setDocumentMargin(0);
Другие вопросы по тегам