How to remove weird graphic effects from widget?
-
Here in the
.png
I've pinpointed some of these effects:Holes, vertical/horizontal lines appear as I resize widgets in
QSplitter
. As soon as theMainWindow
loses focus, those weird effects goes away! Here in the animation see each time I resized those widgets, weird effects appeared and after that I clicked somewhere else, not on the window, those weird effects vanished:Here's the code for the
RoundWidget
, all child widgets inherits it and add contents via those functions:RoundWidget::RoundWidget(QWidget *parent) : QWidget(parent){ layout = new QVBoxLayout(this); toolbar = new QHBoxLayout; layout->addLayout(toolbar); header = new QLabel(this); header->setFont(QFont(header->font().family(), -1, QFont::Bold, false)); auto spacer = new QWidget(this); spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); toolbar->addWidget(header); toolbar->addWidget(spacer); auto separator = new QFrame; separator->setFrameShape(QFrame::HLine); separator->setFrameShadow(QFrame::Sunken); layout->addWidget(separator); setPalette(QPalette(Qt::white)); setAutoFillBackground(true); setLayout(layout); } void RoundWidget::addAction(QWidget * action) { toolbar->addWidget(action); } void RoundWidget::addContent(QWidget * content) { layout->addWidget(content); } void RoundWidget::setHeader(const QString & text) { header->setText(text); } void RoundWidget::resizeEvent(QResizeEvent*){ int radius = 10; QPainterPath path; path.addRoundedRect(rect(), radius, radius); setMask(QRegion(path.toFillPolygon().toPolygon())); }
in the top-level widget, these are the lines for graphics effect:
auto effect = new QGraphicsDropShadowEffect; effect->setBlurRadius(15); effect->setColor(Qt::black); effect->setOffset(0,0); setGraphicsEffect(effect);
How to fix?
EDIT
Same sharp edge problem for frameless rounded corner window:and black border isn't visible on corners.
-
#define ShadowWidth 20 class RoundedWidget : public QWidget { public: RoundedWidget(QWidget *parent=nullptr) : QWidget(parent) { setAutoFillBackground(false); setContentsMargins(ShadowWidth,ShadowWidth,ShadowWidth,ShadowWidth); auto borderEffect = new QGraphicsDropShadowEffect; borderEffect->setBlurRadius(ShadowWidth); borderEffect->setColor(QColor(0,0,0,150)); borderEffect->setOffset(0,0); setGraphicsEffect(borderEffect); } protected: void paintEvent(QPaintEvent* ev) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); const QPalette& palette=this->palette(); QColor backgroundColor=palette.color(QPalette::Window); QPainterPath path; path.addRoundedRect(contentsRect(), 10,10); painter.fillPath(path,backgroundColor); } }; Widget::Widget(QWidget *parent) : QWidget(parent) { setWindowFlags(Qt::FramelessWindowHint|Qt::NoDropShadowWindowHint|Qt::Popup); setAttribute(Qt::WA_TranslucentBackground); // layout for InnerWidget auto vLayout=new QVBoxLayout; vLayout->setContentsMargins(0,0,0,0); setLayout(vLayout); // InnerWidget auto innerWidget=new RoundedWidget; vLayout->addWidget(innerWidget); // layout for splitter auto iLayout=new QVBoxLayout; iLayout->setContentsMargins(ShadowWidth,ShadowWidth,ShadowWidth,ShadowWidth); innerWidget-> setLayout(iLayout); // add splitter auto splitter=new QSplitter(Qt::Horizontal); splitter->setHandleWidth(14); iLayout->addWidget(splitter); // add widgets to splitter QTreeView *treeview = new QTreeView; QTextEdit *textedit = new QTextEdit; textedit->setText("Note: This function will apply the effect on itself and all its children."); splitter->addWidget(textedit); splitter->addWidget(treeview); // effect for splitter auto effect = new QGraphicsDropShadowEffect; effect->setBlurRadius(6); effect->setColor(QColor(0,0,0,150)); effect->setOffset(1,1); splitter->setGraphicsEffect(effect); }
No gliches :)
Note: tested on MacOs only Qt 5.12 -
After some tests, the gliches appear when the effect is applied to the top level widget, disappear when applied to the splitter.
For the frameless window, you need to set a contentsMargins for the shadow to draw correctly.
See https://forum.qt.io/topic/98385/does-qt-support-mac-style-pop-out-widgets/4 -
@mpergand, with that change, a solid line keeps blinking (in between Query/Log and Result sections) as I resize and when I release mouse solid black line remains there if I release it timely:
do you also get that blinking line/shadow?
In the
resizeEvent
of bothRoundWidget
and toplevel round window I've these now:void RoundWidget::resizeEvent(QResizeEvent*){ int radius = 10; QBitmap b(width(), height()); b.fill(QColor(Qt::color0)); QPainter painter(&b); painter.setRenderHint(QPainter::Antialiasing); painter.setBrush(Qt::color1); painter.drawRoundedRect(rect(), radius, radius); setMask(b); // QPainterPath path; // path.addRoundedRect(rect(), radius, radius); // setMask(QRegion(path.toFillPolygon().toPolygon())); }
I can see the black outer border around the top level window/widget BUT all those inner/outer rounded edges are still pixelated.
-
#define ShadowWidth 20 class RoundedWidget : public QWidget { public: RoundedWidget(QWidget *parent=nullptr) : QWidget(parent) { setAutoFillBackground(false); setContentsMargins(ShadowWidth,ShadowWidth,ShadowWidth,ShadowWidth); auto borderEffect = new QGraphicsDropShadowEffect; borderEffect->setBlurRadius(ShadowWidth); borderEffect->setColor(QColor(0,0,0,150)); borderEffect->setOffset(0,0); setGraphicsEffect(borderEffect); } protected: void paintEvent(QPaintEvent* ev) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); const QPalette& palette=this->palette(); QColor backgroundColor=palette.color(QPalette::Window); QPainterPath path; path.addRoundedRect(contentsRect(), 10,10); painter.fillPath(path,backgroundColor); } }; Widget::Widget(QWidget *parent) : QWidget(parent) { setWindowFlags(Qt::FramelessWindowHint|Qt::NoDropShadowWindowHint|Qt::Popup); setAttribute(Qt::WA_TranslucentBackground); // layout for InnerWidget auto vLayout=new QVBoxLayout; vLayout->setContentsMargins(0,0,0,0); setLayout(vLayout); // InnerWidget auto innerWidget=new RoundedWidget; vLayout->addWidget(innerWidget); // layout for splitter auto iLayout=new QVBoxLayout; iLayout->setContentsMargins(ShadowWidth,ShadowWidth,ShadowWidth,ShadowWidth); innerWidget-> setLayout(iLayout); // add splitter auto splitter=new QSplitter(Qt::Horizontal); splitter->setHandleWidth(14); iLayout->addWidget(splitter); // add widgets to splitter QTreeView *treeview = new QTreeView; QTextEdit *textedit = new QTextEdit; textedit->setText("Note: This function will apply the effect on itself and all its children."); splitter->addWidget(textedit); splitter->addWidget(treeview); // effect for splitter auto effect = new QGraphicsDropShadowEffect; effect->setBlurRadius(6); effect->setColor(QColor(0,0,0,150)); effect->setOffset(1,1); splitter->setGraphicsEffect(effect); }
No gliches :)
Note: tested on MacOs only Qt 5.12 -
@mpergand, First, I've removed the
resizeEvent
inmainwindow
andRoundWidget
, added yourpaintEvent
in both ofmainwindow
andRoundWidget
. InRoundWidget
,ShadowWidth 2
, 20 makes a huge gap in Windows 10. Added these:setWindowFlags(Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint); setAttribute(Qt::WA_TranslucentBackground);
in
mainwindow
and with these changes, those round edges are smooth, as expected, BUT I still have the blinking effect:maybe it's a windows 10 problem or because of multiple splitter.
Log
andQuery
are inside splitter1 and splitter2 containsObjects
,splitter1
andResult
. No idea why does it blink on that spot, that spot is the end point ofsplitter1
.Thanks for that
paintEvent
that smoothened those round edges.EDIT
Got that! that's because both of those splitters had that effect. I've to remove effect fromsplitter1
like thissplit1->setGraphicsEffect(0)
and with that line inQueryWidget
it's perfect:Thanks once again.