Planned maintenance: From Sunday 8th December 10:00 CET there will be changes to try and solve the caching issues that have been experienced. If anyone has a problem connecting after this period then please PM @AndyS or any of the moderators.

Draw a PE_IndicatorBranch in a QLabel



  • Hi,

    I'm trying to customise a QlistView row by having the first item in each row show an indicator branch such as that used in QTreeView.

    To accomplish this I add the following widget as the first item in each row. The label text is displayed correctly but I cannot get the indicator branch to display.

    I can get other primitive elements (eg down arrow) to display but not the indicator branch.

    Any ideas?

        class NodeWidget : public QLabel
        {
        public:
            NodeWidget(QWidget *parent = nullptr) :
                QLabel("this text is displayed", parent)
            {
            }
    
        private:
             void paintEvent(QPaintEvent *);
        };
    
        void NodeWidget::paintEvent(QPaintEvent *e)
        {
            QLabel::paintEvent(e);
            QPainter painter(this);
    
            QStyleOptionFocusRect option;
            option.initFrom(this);
            option.backgroundColor = palette().color(QPalette::Background);
            option.state = QStyle::State_Item | QStyle::State_Children;
            style()->drawPrimitive(QStyle::PE_IndicatorBranch, &option, &painter, this);
        }
    

  • Lifetime Qt Champion

    Hi
    I think it needs a rect also, but not sure its the only thing.

    class NodeWidget : public QLabel
    {
    public:
        NodeWidget(QWidget *parent = nullptr) :
            QLabel("this text is displayed", parent) { }
    private:
        void paintEvent(QPaintEvent *e)
        {
            
            QLabel::paintEvent(e);
            
            QStyleOption branchOption;
            QPainter painter(this);
            //painter.setBrush( Qt::white);
            //painter.drawRect(0, 0, width() - 1, height() - 1);
            branchOption.initFrom(this);
            branchOption.state = QStyle::State_Item | QStyle::State_Children;
            //  branchOption.state |= QStyle::State_Open; // if to draw open
            branchOption.rect = rect();// adjust this
            style()->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &painter, this);
    
        }
    };
    

    alt text
    alt text



  • @mrjj thanks

    When I read you reply I was in fact playing around setting the option.rect which you correctly identified as not having been sent, although I still haven't been able to display the indicator branch.

    I think it may have to do with the fact that the label is within a layout in a QListwidget row item. Just assigning the QLabel rect doesn't seem enough in my case.

    I'll keep on trying...


  • Lifetime Qt Champion

    @oberluz
    Hi
    well if you look at the test code, it seems that
    style()->drawPrimitive(QStyle::PE_IndicatorBranch draws the
    the indicator in the center of the rect given.
    It should not matter if inside a QListwidget but you might want to
    check the rect label.



  • @mrjj Yes I noticed that. I've replicated your test example and I can now get it to display in the row of a QListWidget. Thanks


  • Lifetime Qt Champion

    @oberluz
    You can simply calculate a new rect for the beginning of the text line and
    then ask QLabel to center text or similar.
    If you want complete control you should draw both text and PE_IndicatorBranch
    with painter.
    (and not call QLabel::paintEvent(e); )
    However, if you use rich text in Label or mutliple lines it is slightly more complicated.



  • @mrjj thanks. I was able to get it to work if the QListWidget was the central widget in the QApplicaiton as per your example. However if I add it to a dock widget they fail to draw:

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    
    namespace Ui {
        class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
        QWidget* createListWidget();
    
    private:
        Ui::MainWindow *ui;
    };
    
    #endif // MAINWINDOW_H
    
    #include "MainWindow.h"
    #include "ui_MainWindow.h"
    #include <QListWidget>
    #include <QLabel>
    #include <QPainter>
    #include <QHBoxLayout>
    #include <QApplication>
    #include <iostream>
    #include <QDockWidget>
    
    class NodeWidget : public QLabel
    {
    public:
        NodeWidget(QWidget *parent = NULL) :
            QLabel("", parent)
        {
        }
    
    private:
         void paintEvent(QPaintEvent *);
    };
    
    void NodeWidget::paintEvent(QPaintEvent *e)
    {
        QLabel::paintEvent(e);
        QPainter painter(this);
        QStyleOption option;
        option.initFrom(this);
        option.rect = rect();
        option.state = QStyle::State_Item | QStyle::State_Children;
        style()->drawPrimitive(QStyle::PE_IndicatorBranch, &option, &painter, this);
    }
    
    class RowWidget : public QWidget
    {
    public:
        RowWidget(const QString& text, QWidget *parent = NULL);
    };
    
    
    RowWidget::RowWidget(const QString &text, QWidget *parent) :
        QWidget(parent)
    {
        QHBoxLayout* layout = new QHBoxLayout(this);
        layout->setContentsMargins(0,0,0,0);
    
        layout->addWidget(new NodeWidget(this));
        layout->addWidget(new QLabel(text, this));
        layout->addWidget(new QLabel("text", this));
    
        setLayout(layout);
    }
    
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        layout()->setContentsMargins(0,0,0,0);
    
        QString styleSheet("QDockWidget::title { font: 75 11pt \"ubuntu\"; text-align: left; background: darkgray; }");
    
        QDockWidget* m_dockWidget;
        m_dockWidget = new QDockWidget(" Dock Window", this);
        m_dockWidget->setObjectName(QString::fromUtf8("DockWidget"));
        QSizePolicy sizePolicy6(QSizePolicy::Minimum, QSizePolicy::Minimum);
        sizePolicy6.setHorizontalStretch(0);
        sizePolicy6.setVerticalStretch(0);
        sizePolicy6.setHeightForWidth(m_dockWidget->sizePolicy().hasHeightForWidth());
        m_dockWidget->setSizePolicy(sizePolicy6);
        m_dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea|Qt::TopDockWidgetArea|Qt::BottomDockWidgetArea);
    
        m_dockWidget->layout()->setContentsMargins(0,0,0,0);
        m_dockWidget->setStyleSheet(styleSheet);
    
        addDockWidget(Qt::BottomDockWidgetArea, m_dockWidget);
    
        QWidget* list = createListWidget();
        m_dockWidget->setWidget(list);
    
        {
            QWidget* list = createListWidget();
            setCentralWidget(list);
        }
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    QWidget *MainWindow::createListWidget()
    {
        QListWidget* list = new QListWidget(this);
        list->setAlternatingRowColors(true);
    
        RowWidget* widget = new RowWidget("one", list);
        QListWidgetItem* item = new QListWidgetItem(list);
        item->setSizeHint(widget->minimumSizeHint());
        list->addItem(item);
        list->setItemWidget(item, widget);
    
        widget = new RowWidget("two", list);
        item = new QListWidgetItem(list);
        item->setSizeHint(widget->minimumSizeHint());
        list->addItem(item);
        list->setItemWidget(item, widget);
    
        widget = new RowWidget("three", list);
        item = new QListWidgetItem(list);
        item->setSizeHint(widget->minimumSizeHint());
        list->addItem(item);
        list->setItemWidget(item, widget);
    
        return list;
    }
    

    0_1561451749908_dockwidget.png



  • @oberluz said in Draw a PE_IndicatorBranch in a QLabel:

    drawPrimitive

    my bad: the style sheet is causing the issue. Can't see why that could cause it?


  • Lifetime Qt Champion

    Hi
    What does the stylesheet target?
    margins and such can affect lots of stuff if not
    target using names or concrete types as selectors



  • @mrjj I only intended it to darken the dock window title bar:

    QString styleSheet("QDockWidget::title { font: 75 11pt \"ubuntu\"; text-align: left; background: darkgray; }");
    

  • Lifetime Qt Champion

    @oberluz
    so if you do use styleSheet it looks as you expect?
    you are right, im not sure either how that should affect NodeWidget



  • @mrjj yes, without the stylesheet its fine:

    0_1561455516847_without_style.png

    Is its possible I need to get the current style sheet, then somehow add the title, and then set it ? I'm thinking that by just setting it rather than modifying it I might be deleting something


  • Lifetime Qt Champion

    @oberluz
    Hi
    Unless you manually set a stylesheet, its empty pr default.
    so if that is the ONLY stylesheet you set, i dont get it.



  • @mrjj its the only one, the example I posted is complete


  • Lifetime Qt Champion

    @oberluz
    Sorry, i really cant guess.
    It seems not very connected.
    and should only affect Title



  • @mrjj Maybe a bug.. I might raise one with this example


  • Lifetime Qt Champion

    @oberluz
    Could be.
    Please make a small sample that can reproduce it.
    Makes it far more likely we discover what it is. :)



  • @mrjj will do and I'll run it under 5.13 before submititng


  • Lifetime Qt Champion

    @oberluz
    Super.
    and please post link to bug here :)



  • @mrjj https://bugreports.qt.io/browse/QTBUG-76947
    as promised. reproduced it with 5.13.


Log in to reply