Qt: QTreeView: центральная иконка в заголовке

Для некоторых столбцов из виджета QTreeView я использую значок. Значок установлен на

QVariant headerData (int section, Qt::Orientation orientation, int role) const{
    if(role ==  Qt::DecorationRole)
    {
        QIcon icon;
        if (section == 0) {
            icon.addFile(":/icon1");
        } else if (section == 1){
            icon.addFile(":/icon2");
        }
    }

    if(role ==  Qt::TextAlignmentRole)
    {
        return (Qt::AlignLeft + Qt::AlignVCenter);
    }

Заголовок выглядит так:

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

Я хочу выровнять значки с текстом. TextAlignmentRole работает только для текста, но не для значков. Как я могу это сделать?

Я также попытался установить выравнивание по умолчанию:

m_treeview->header()->setDefaultAlignment(Qt::AlignCenter); но не повезло.


person laurapons    schedule 06.11.2017    source источник


Ответы (1)


Чтобы центрировать значок с текстом, вам придется реализовать свой собственный прокси-стиль для создания этого конкретного стиля поведения.

#include <QProxyStyle>
#include <QPainter>

class HeaderProxyStyle : public QProxyStyle
{
public:
    void drawControl(ControlElement oCtrElement, const QStyleOption * poStylrOptionption, QPainter * poPainter, const QWidget * poWidget = 0) const;

};

Значок центра с текстовой реализацией

    void HeaderProxyStyle::drawControl(ControlElement oCtrElement, const QStyleOption *poStylrOptionption, QPainter *poPainter, const QWidget *poWidget) const
    {
        // Header label?
        if (oCtrElement == CE_HeaderLabel) {
            // YES - Allocate style option header
            QStyleOptionHeader *poStyleOptionHeader =
                    (QStyleOptionHeader *) poStylrOptionption;

            // Get header icon
            QIcon oIcon = qvariant_cast<QIcon>(poStyleOptionHeader->icon);

            // Icon is valid?
            if(oIcon.isNull()){
                // No - Draw text header
                QProxyStyle::drawControl(oCtrElement, poStylrOptionption, poPainter, poWidget);
                return;
            }

            // Set icon size 16x16
            QSize oIconSize = QSize(16,16);

            // Get header section rect
            QRect oRect = poStyleOptionHeader->rect;

            // Create header icon pixmap
            QPixmap oIconPixmap = oIcon.pixmap(oIconSize.width(),oIconSize.height());

            // Calculate header text width
            int iTextWidth = poStyleOptionHeader->fontMetrics.width(poStyleOptionHeader->text);

            QRect oCenterRec = QRect(oRect.left(),
                                    oRect.top() + (oRect.height - iTextSize)/2,
                                    oIconPixmap.width(),oIconPixmap.height());


            QRect oTextRect = QRect(oCenterRec.left()+ oIconSize.width(),
                              oCenterRec.top(), oCenterRec.width() + iTextWidth, oCenterRec.height());
            // Draw icon
            poPainter->drawPixmap(oCenterRec, oIconPixmap);
            // Draw text
            poPainter->drawText(oTextRect, poStyleOptionHeader->text);
            return;
        }
        QProxyStyle::drawControl(oCtrElement, poStylrOptionption, poPainter, poWidget);

    }

Затем примените этот стиль заголовка в древовидном представлении.

// Set header style
m_treeview->header()->setStyle(&m_oHeaderStyle);
person Simon    schedule 07.11.2017
comment
@laurapons: тебе нужна еще помощь с этим вопросом? - person Simon; 08.11.2017
comment
Я не знаю, как интегрировать это в код (виджет, унаследованный от qtreewidget, уже использует модели/делегаты и прокси), я получу ответ как можно скорее, спасибо за быстрый ответ! - person laurapons; 08.11.2017
comment
Я также использовал структуру представления модели в своем проекте, и я попробовал ее, и она работает, поэтому для интеграции просто создайте отдельный класс HeaderProxyStyle, затем добавьте частный член «HeaderProxyStyle m_oHeaderStyle» в область, где вы используете m_treeview, и установите стиль для заголовка m_treeview->header()->setStyle(&m_oHeaderStyle); он должен работать. вы также можете опубликовать больше кода, я могу вам помочь. - person Simon; 09.11.2017
comment
Итак, я интегрировал (спасибо за вашу помощь!). Теперь, даже если я установлю для TextAlignmentRole в headerData() значение (Qt::AlignLeft + Qt::AlignVCenter), все заголовки со значком выравниваются по верхнему центру (заголовки без значков выравниваются правильно). - person laurapons; 09.11.2017
comment
Итак, я изменил точку oCenterRec с oRect.top() на oRect.top() + (oRect.height() - iTextSize)/2, где iTextSize = poStyleOptionHeader-›fontMetrics.height(); и теперь он центрирован по вертикали, но мне все еще нужно выровнять по левому краю, а не по центру по горизонтали. - person laurapons; 09.11.2017
comment
Последнее изменение, которое помогло: изменить точку oCenterRec x с oRect.left() + (oRect.width() / 2) - ( (iTextWidth + 16) / 2) на oRect.left(). Спасибо, работает отлично! - person laurapons; 09.11.2017
comment
@laurapons, я рад, что смог помочь, я отредактировал свой ответ с вашими комментариями. Благодарю. - person Simon; 12.11.2017