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); }
-
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); } };
-
@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...
-
@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. -
@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; }
-
Hi
What does the stylesheet target?
margins and such can affect lots of stuff if not
target using names or concrete types as selectors -