Memory leak using StyleSheet
-
One more thing, I tried to add styles to qss file (for table they are style-properties starts with #, after comments)., but result is the same.
darkstyle.h
#ifndef DARKSTYLE_H #define DARKSTYLE_H #include <QApplication> #include <QFile> #include <QFont> #include <QPainter> #include <QProxyStyle> #include <QStyleFactory> #include <QWidget> class DarkStyle : public QProxyStyle { Q_OBJECT public: DarkStyle(); explicit DarkStyle(QStyle *style); QStyle *baseStyle() const; void polish(QPalette &palette) override; void polish(QApplication *app) override; private: QStyle *styleBase(QStyle *style = nullptr) const; }; #endif // DARKSTYLE_Hdarkstyle.cpp
#include "darkstyle.h" DarkStyle::DarkStyle() : DarkStyle(styleBase()) {} DarkStyle::DarkStyle(QStyle *style) : QProxyStyle(style) {} QStyle *DarkStyle::styleBase(QStyle *style) const { static QStyle *base = !style ? QStyleFactory::create(QStringLiteral("Fusion")) : style; return base; } QStyle *DarkStyle::baseStyle() const { return styleBase(); } void DarkStyle::polish(QPalette &palette) { // modify palette to dark palette.setColor(QPalette::Window, QColor(53, 53, 53)); palette.setColor(QPalette::WindowText, Qt::white); palette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127)); palette.setColor(QPalette::Base, QColor(42, 42, 42)); palette.setColor(QPalette::AlternateBase, QColor(66, 66, 66)); palette.setColor(QPalette::ToolTipBase, Qt::white); palette.setColor(QPalette::ToolTipText, QColor(53, 53, 53)); palette.setColor(QPalette::Text, Qt::white); palette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127)); palette.setColor(QPalette::Dark, QColor(35, 35, 35)); palette.setColor(QPalette::Shadow, QColor(20, 20, 20)); palette.setColor(QPalette::Button, QColor(53, 53, 53)); palette.setColor(QPalette::ButtonText, Qt::white); palette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127)); palette.setColor(QPalette::BrightText, Qt::red); palette.setColor(QPalette::Link, QColor(42, 130, 218)); palette.setColor(QPalette::Highlight, QColor(42, 130, 218)); palette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80)); palette.setColor(QPalette::HighlightedText, Qt::white); palette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(127, 127, 127)); } void DarkStyle::polish(QApplication *app) { if (!app) return; // increase font size for better reading, // setPointSize was reduced from +2 because when applied this way in Qt5, the // font is larger than intended for some reason QFont defaultFont = QApplication::font(); defaultFont.setPointSize(defaultFont.pointSize()); app->setFont(defaultFont); // loadstylesheet QFile qfDarkstyle(QStringLiteral(":/darkstyle/darkstyle.qss")); if (qfDarkstyle.open(QIODevice::ReadOnly | QIODevice::Text)) { // set stylesheet QString qsStylesheet = QString::fromLatin1(qfDarkstyle.readAll()); app->setStyleSheet(qsStylesheet); qfDarkstyle.close(); } }darkstyle.qss
QScrollBar::handle:horizontal:hover{ background-color:palette(highlight); } QScrollBar::add-line:horizontal{ background:none; width:0px; subcontrol-position:bottom; subcontrol-origin:margin; } QScrollBar::sub-line:horizontal{ background:none; width:0px; subcontrol-position:top; subcontrol-origin:margin; } QSlider::handle:horizontal{ border-radius:4px; border:1px solid rgba(25,25,25,255); background-color:palette(alternate-base); min-height:20px; margin:0 -4px; } QSlider::handle:horizontal:hover{ background:palette(highlight); } QSlider::add-page:horizontal{ background:palette(base); } QSlider::sub-page:horizontal{ background:palette(highlight); } QSlider::sub-page:horizontal:disabled{ background:rgb(80,80,80); } /* EditDigitalSignalTable */ /* Table cells */ QLabel#EditTableCells{ background-color:palette(base); border:1px solid palette(dark); border-top-style: none; border-left-style: none; padding-left:5px; padding-right:5px; } QPushButton#EditTableCells, QSpinBox#EditTableCells{ background-color:palette(base); } /* Table headers */ #EditTableHeaderTime, #EditTableHeaderDuration{ background:rgb(60,60,60); border-top:1px solid palette(dark); border-bottom:1px solid palette(dark); padding-left:5px; padding-right:5px; } #EditTableHeaderState{ background:rgb(60,60,60); border-top:1px solid palette(dark); border-right:1px solid palette(dark); border-bottom:1px solid palette(dark); padding-left:5px; padding-right:5px; } /* Table corner cell */ #EditTableHeaderNumber{ border:1px solid palette(dark); padding-left:5px; padding-right:5px; background:rgb(90,90,90); } QTableView QTableCornerButton::section{ background:rgb(75,75,75); } /* Table vertical header */ #EditTableCellNumber{ background:rgb(60,60,60); border:1px solid palette(dark); border-top-style: none; padding-left:5px; padding-right:5px; } /* Tab-widget that contains edit-table*/ #EditTabWidget{ background:rgb(53,53,53); } -
You don't have to re-implement the paint event.
Just instead of using stylesheets I would use a standard style shipped with Qt.
Depending on your operating system and window manager, a suitable default style will be chosen automatically.
Instead of callingsetStyleSheet()on your widget, you read its palette, set the respective brush and callwidget->setPalette()again. A paint event will then be posted and your widget gets painted without a style sheet string having to be interpreted.
Please read the documentation of QPalette, which I have linked in my previous post. Everything is explained there and you can also examine code examples. -
You don't have to re-implement the paint event.
Just instead of using stylesheets I would use a standard style shipped with Qt.
Depending on your operating system and window manager, a suitable default style will be chosen automatically.
Instead of callingsetStyleSheet()on your widget, you read its palette, set the respective brush and callwidget->setPalette()again. A paint event will then be posted and your widget gets painted without a style sheet string having to be interpreted.
Please read the documentation of QPalette, which I have linked in my previous post. Everything is explained there and you can also examine code examples.@Axel-Spoerl, yes, but how can I create border to widget with QPalette? As I understood reading doc, it works mostly with color, using roles. And one more thing, how to control paint-border for specific sides(not all 4), when I have table?
-
The code manually implements parts of QTableView, respectively QTableWidget. These classes have an out-of-the-box implementation for column headers and row numbers, which your code creates labels for. They also provide a visual grid, which can probably substitute drawing borders around every widget. Such grids can be styled and they are rendered more efficiently: Instead of drawing a rectangle around each widget, they consist of vertical and horizontal lines across the entire viewport. They get repainted only if necessary (e.g. due to resizing or scroll moves below grid size). And as a bycatch, your users will be able to navigate cells with cursor keys - if you allow it to happen.
In case you use QTableView, you can store your data in a QAbstractTableModel, define selection models, which gives you focus on data while leaving its visual representation (including drag & drop, sorting) to the system.
QTableWidget has a simpler API at the cost of less flexibility in data management.
-
The code manually implements parts of QTableView, respectively QTableWidget. These classes have an out-of-the-box implementation for column headers and row numbers, which your code creates labels for. They also provide a visual grid, which can probably substitute drawing borders around every widget. Such grids can be styled and they are rendered more efficiently: Instead of drawing a rectangle around each widget, they consist of vertical and horizontal lines across the entire viewport. They get repainted only if necessary (e.g. due to resizing or scroll moves below grid size). And as a bycatch, your users will be able to navigate cells with cursor keys - if you allow it to happen.
In case you use QTableView, you can store your data in a QAbstractTableModel, define selection models, which gives you focus on data while leaving its visual representation (including drag & drop, sorting) to the system.
QTableWidget has a simpler API at the cost of less flexibility in data management.
@Axel-Spoerl , Yes it does. But I have been working at this task for already 2 weeks and used: QTableWIdget(too much widgets and it doesnt work), QTableView + delegate (but delegates creates only after clicking on cells and it doesnt work immidiately, like QSpinBox and other widgets).
That's why I did this table by my own . And main question: Is re-paint, using paintEvent, best variant or can I use other paint things? -
Feel free to hate me - I am going to be blunt and honest: If heading to the wrong direction, change your way. Pushing, speeding and suspecting others won't get you anywhere. StyleSheets don't leak memory and QTableWidget rocks 30k items with no issue.
I'd call 2 weeks of research an investment in finding out that the hard way is eating memory and CPU as a snack between breakfast and lunch.
Read the documentation carefully and use the tools available for managing large matrices of widgets. If you struggle, this forum will help you.If you stick to your individual implementation, that's totally fine. A price is to be paid for parsing style sheet strings and/or drawing rectangles around each widget. It doesn't matter much, if it's done by generic paint events, or by an individual method that overrides
QWidget::paintEvent. I trust you understand that we can't be of much help in how to implement QTableWidget without QTableWidget. -
Feel free to hate me - I am going to be blunt and honest: If heading to the wrong direction, change your way. Pushing, speeding and suspecting others won't get you anywhere. StyleSheets don't leak memory and QTableWidget rocks 30k items with no issue.
I'd call 2 weeks of research an investment in finding out that the hard way is eating memory and CPU as a snack between breakfast and lunch.
Read the documentation carefully and use the tools available for managing large matrices of widgets. If you struggle, this forum will help you.If you stick to your individual implementation, that's totally fine. A price is to be paid for parsing style sheet strings and/or drawing rectangles around each widget. It doesn't matter much, if it's done by generic paint events, or by an individual method that overrides
QWidget::paintEvent. I trust you understand that we can't be of much help in how to implement QTableWidget without QTableWidget.@Axel-Spoerl No, thank you a lot for the help. I am new in Qt and learn all these stuff step by step. Okay, custom implementation will be the best, for my case, because QTableWidget is okay for less than 20'000 (if we have 3 buttons in row), after it it doesn't work. My project uses more than 100'000 points, so it is 3 * 100'000 widgets in general. But thank for your time.
And main rule: NOT use customStyle for table with a lot of rows
I've already written about it:
https://forum.qt.io/topic/137658/table-with-large-amount-of-widgets-100-000 -
Feel free to hate me - I am going to be blunt and honest: If heading to the wrong direction, change your way. Pushing, speeding and suspecting others won't get you anywhere. StyleSheets don't leak memory and QTableWidget rocks 30k items with no issue.
I'd call 2 weeks of research an investment in finding out that the hard way is eating memory and CPU as a snack between breakfast and lunch.
Read the documentation carefully and use the tools available for managing large matrices of widgets. If you struggle, this forum will help you.If you stick to your individual implementation, that's totally fine. A price is to be paid for parsing style sheet strings and/or drawing rectangles around each widget. It doesn't matter much, if it's done by generic paint events, or by an individual method that overrides
QWidget::paintEvent. I trust you understand that we can't be of much help in how to implement QTableWidget without QTableWidget.@Axel-Spoerl Just curious: you really create 30k items while they can not be displayed at the same time? Is there a way to display only some of them on demand while the data is stored in the model or somewhere? I will never want to create so many items in a table at the same time.
-
@Axel-Spoerl Just curious: you really create 30k items while they can not be displayed at the same time? Is there a way to display only some of them on demand while the data is stored in the model or somewhere? I will never want to create so many items in a table at the same time.
@JoeCFD It would be possible, however, not the most elegant way. QTableView offers rich possibilities to store data in a model and render only what is needed. That's what I would use for large data volumes.
-
@JoeCFD It would be possible, however, not the most elegant way. QTableView offers rich possibilities to store data in a model and render only what is needed. That's what I would use for large data volumes.
@Axel-Spoerl Got it. Thanks. I may have a peek into the source code and see how it is done.