embed a qdialog into qwidget (Qt c++)
-
@SimonSchroeder @Pl45m4 @Axel-Spoerl sorry for the very late reply!
So I started to try make a widget like the suggestion, here is my code (sorry it a little bit big):
fxmessagebox.h
#include <QLabel> #include <QPushButton> #include <QHBoxLayout> #include <QDialogButtonBox> //------------------------------------------------------------------------ enum Type { Error = 1, Information , Warning }; class MessageHeader: public QLabel { public: QPushButton *closeB; MessageHeader(const QString &Text,Type type) { this->closeB = new QPushButton(this); closeB->setFocusPolicy(Qt::NoFocus); closeB->setCursor(Qt::PointingHandCursor); Set_Type(type); this->setContentsMargins(5,0,40,0); this->setText(Text); } void Set_Text(const QString &text) { this->setText(text); } void Set_Type(Type t) { if(t==Type::Error) { this->setObjectName("lineerror"); closeB->setObjectName("closebuttonerror"); } else if(t==Type::Information) { this->setObjectName("lineinfo"); closeB->setObjectName("closebuttoninfo"); } else if(t==Type::Warning) { this->setObjectName("linewarning"); closeB->setObjectName("closebuttonwarning"); } } private: QPoint m_pCursor; protected: void resizeEvent(QResizeEvent *) { closeB->setGeometry((this->width()-35),0,35,35); } }; //------------------------------------------------------------------------ class FXMessageBox:public QWidget { private: QLabel *cs; QLabel *bot; QLabel *ic; QPushButton *bClose; int defButtonIndex = -1; QString defButtonName =""; bool isModifiedHeaderText = false; QPoint oldPos; public: MessageHeader *header; QWidget *m_parent; QPoint position; QDialogButtonBox *buttonBox; QStringList buttonList; QHBoxLayout *h; QGridLayout *gl; explicit FXMessageBox(QWidget *parent = nullptr); void Set_HeaderText(const QString &text); void Set_Text(const QString &text); void Set_Buttons(const QStringList &buttonList); void Set_DefaultButton(int index); void Set_DefaultButton(const QString &name); void Set_Type(Type type); protected: void showEvent(QShowEvent *) override; bool eventFilter(QObject *obj, QEvent *e) override; private slots: void dialogButtonClicked(QAbstractButton *button); void exitClick(); };
fxmessagebox.cpp
#include <QMouseEvent> #include <QFile> #include <QProxyStyle> #include <QApplication> #include "fxmessagebox.h" //------------------------------------------------------------------------ class Style_tweaks : public QProxyStyle { public: void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { if (element == QStyle::PE_FrameFocusRect) return; QProxyStyle::drawPrimitive(element, option, painter, widget); } }; //------------------------------------------------------------------------ FXMessageBox::FXMessageBox(QWidget *parent) { this->setContentsMargins(25,25,25,25); QFile file("messagebox.qss"); file.open(QFile::ReadOnly); QString styleSheet = QLatin1String(file.readAll()); setStyleSheet(styleSheet); this->setFixedSize(380,200); this->h = new QHBoxLayout(this); h->setSpacing(0); h->setContentsMargins(0,0,0,0); this-> gl = new QGridLayout; gl->setSpacing(0); gl->setContentsMargins(0,0,0,0); this->m_parent = parent; this->buttonBox = new QDialogButtonBox(); buttonBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); buttonBox->setContentsMargins(4,4,4,4); h->addWidget(buttonBox); this->cs = new QLabel(this); cs->setWordWrap(true); cs->setObjectName("body"); cs->setAlignment(Qt::AlignCenter); this->ic = new QLabel; this->bot = new QLabel; bot->setLayout(h); ic->setObjectName("headerinfo"); bot->setObjectName("botinfo"); header = new MessageHeader("INFORMÁCIÓ",Type::Information); header->setWordWrap(true); ic->setFixedSize(35,35); bot->setFixedHeight(45); header->setFixedHeight(35); header->installEventFilter(this); connect(header->closeB, &QPushButton::clicked,this, [=] { exitClick();}); gl->addWidget(ic,0,0,1,1); gl->addWidget(header,0,1,1,9); gl->addWidget(bot,4,1,1,9); gl->addWidget(cs,1,1,3,9); this->setParent(m_parent); } void FXMessageBox::Set_HeaderText(const QString &text) { header->Set_Text(text); isModifiedHeaderText = true; } void FXMessageBox::Set_Text(const QString &text) { cs->setText(text); } void FXMessageBox::Set_Buttons(const QStringList &buttonList) { this->buttonList = buttonList; for (int i=0; i<buttonList.count() ;i++ ) { QPushButton *button = new QPushButton(buttonList.at(i)); button->setObjectName("choicebutton"); button->setProperty("ActionRole",i+1); button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); button->setStyle(new Style_tweaks); buttonBox->addButton(button,QDialogButtonBox::ActionRole); connect(button, &QPushButton::clicked,this, [=] { dialogButtonClicked(button);}); button->setCursor(Qt::PointingHandCursor); } } void FXMessageBox::Set_DefaultButton(int index) { defButtonIndex = index; } void FXMessageBox::Set_DefaultButton(const QString &name) { defButtonName = name; } void FXMessageBox::Set_Type(Type type) { if(type==Type::Error) { ic->setObjectName("headererror"); bot->setObjectName("boterror"); if(!isModifiedHeaderText) header->Set_Text("ERROR"); } if(type==Type::Information) { ic->setObjectName("headerinfo"); bot->setObjectName("botinfo"); if(!isModifiedHeaderText) header->Set_Text("INFORMATION"); } if(type==Type::Warning) { ic->setObjectName("headerwarning"); bot->setObjectName("botwarning"); if(!isModifiedHeaderText) header->Set_Text("WARNING"); } header->Set_Type(type); } void FXMessageBox::showEvent(QShowEvent *) { if(buttonList.count()==0) { QPushButton *button = new QPushButton("Ok"); button->setObjectName("choicebutton"); button->setProperty("ActionRole",1); button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); button->setMaximumWidth(100); button->setCursor(Qt::PointingHandCursor); buttonBox->addButton(button,QDialogButtonBox::ActionRole); connect(button, &QPushButton::clicked,this, [=] { dialogButtonClicked(button);}); } setLayout(gl); QList <QPushButton *> tmp = buttonBox->findChildren<QPushButton *>(); if(defButtonIndex == -1 && defButtonName=="") { tmp.at(0)->setFocus(); } else if(defButtonIndex!=-1) { tmp.at(defButtonIndex)->setFocus(); } else { for (int i=0;i<tmp.count();i++) { if(tmp.at(i)->text() == defButtonName) { tmp.at(i)->setFocus(); break; } } } } bool FXMessageBox::eventFilter(QObject *obj, QEvent *e) { if((e->type() == QEvent::MouseButtonPress)) { position = QPoint(static_cast<QMouseEvent*>(e)->globalPosition().x()-geometry().x(), static_cast<QMouseEvent*>(e)->globalPosition().y()-geometry().y()); } if((e->type() == QEvent::MouseMove )) { if(static_cast<QMouseEvent*>(e)->buttons() & Qt::LeftButton ) { QPoint toMove = static_cast<QMouseEvent*>(e)->globalPosition().toPoint() - position; move(toMove); } } return QObject::eventFilter(obj, e); } void FXMessageBox::dialogButtonClicked(QAbstractButton *button) { int actionRole = button->property("ActionRole").toInt(); qDebug()<<actionRole; } void FXMessageBox::exitClick() { qDebug()<<"Exit clicked"; }
messagebox.qss
#FxMessageBox { margin: 0px; } QLabel#body { background-color : rgb(81, 81, 81); text-align: center; font-family: Source Sans Pro; color:rgb(233, 237, 241); font-size: 10pt; padding: 20px 10px 20px 10px; } QLabel#boterror,#botwarning,#botinfo { border-bottom: 0px; border-right: 0px; border-left: 0px; padding:4px; } QLabel#boterror { background-color: rgb(232,48,65); } QLabel#botwarning { background-color: rgb(233,163,60); } QLabel#botinfo { background-color: rgb(107,171,224); } QLabel#headererror { image: url(RES/error.svg); background-color: rgb(232, 48, 65); } QLabel#headerinfo { image: url(:/RES/information.svg); background-color: rgb(107, 171, 224); } QLabel#headerwarning { image: url(:/RES/warning.svg); background-color: rgb(233, 163, 60); } QLabel#lineerror,#lineinfo,#linewarning { border-top: 0px; border-right: 0px; border-left: 0px; text-align: center; font: bold; background-color: rgb(51, 51, 51); font-family: Source Sans Pro; font-size: 10pt; } QLabel#lineerror { border-bottom: 2px solid rgb(232, 48, 65); color: rgb(232,48,65); } QLabel#linewarning { border-bottom: 2px solid rgb(233, 163, 60); color: rgb(233,163,60); } QLabel#lineinfo { border-bottom: 2px solid rgb(107, 171, 224); color: rgb(107,171,224); } QPushButton#choicebutton { background-color: rgb(233,237,241); color: rgb(102,124,146); padding-left: 10px; padding-right: 10px; border: 0px solid rgb(255, 213, 74); } QPushButton#choicebutton:focus { background-color: rgb(212,220,227); color: rgb(37,59,79); } QPushButton#choicebutton:hover { background-color: rgb(212,220,227); color: rgb(37,59,79); } QPushButton#choicebutton:pressed { background-color: rgb(182,195,206); color: rgb(37,59,79); } QPushButton#closebuttonerror,#closebuttoninfo,#closebuttonwarning { image: url(:/RES/close.svg); border: 0px; background-color: rgb(51, 51, 51); padding: 7px 7px 7px 7px; } QPushButton#closebuttonerror { border-bottom: 2px solid rgb(232,48,65); } QPushButton#closebuttoninfo { border-bottom: 2px solid rgb(107, 171, 224); } QPushButton#closebuttonwarning { border-bottom: 2px solid rgb(233,163,60); } QPushButton#closebuttonerror:hover,#closebuttoninfo:hover,#closebuttonwarning:hover { background-color:rgb(232,48,65); }
And the useage:
int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); FXMessageBox *kate = new FXMessageBox(&w); kate->Set_Text("Lorem Ipsum Dolor Sit Amet"); kate->Set_Type(Type::Warning); kate->show(); kate->move(0,0); return a.exec(); }
Everything works fine, except that when I move my fxmessage widget, the edges start to creep while moving, so they don't stay rigid. After moving everything back to normal. I don't know where the error could be, that's why I wrote the entire code (sorry for that). Thank you for your answers!
-
@Kaguro said in embed a qdialog into qwidget (Qt c++):
the edges start to creep while moving, so they don't stay rigid
Do they leave a trace on the screen? Or is it some blur effect? Can you show it?
Could be an issue with your stylesheet. Is it the same, when you don't set the stylesheet? -
-
@Kaguro
The video looks like a rendering glitch to me, which becomes more obvious on a widget without frame margins.
But since everything gets rendered nicely when the drag stops, I have the impression that the glitch is not Qt related.
In essence, there's no difference in how a widget is painted during or after a drag.The fact having a style sheet or not doesn't influence the glitch, would fit into this picture.
Have you tried the reproducer on different computers with fast/slow graphics?
-
@Axel-Spoerl
hmm interesting. Would it depend on the computer? I've only tested it on my work machine, but I'll test it at home too, where I have a faster computer. But it needs faster graphics card? Does this render require that much? What is interesting too: If i set the widget's setContentMargins, higher the number I set, the less the glitch occurs. In the video the contentmargins are 0. -
@Kaguro
I am speculating now. I can't see any glitch on my PC, but it's a fast one with a native NVIDIA driver.
The glitch on the video (watched in slomo) looks like rendering on the "new" position starts, before rendering on the "old" position stops. And as said before, technically there is no difference between rendering "on the move" and "at the end of the move". Wouldn't make sense - we can't predict, when a user stops moving. -
@Axel-Spoerl
I understand. I will try it at home and report back!
it's just not so nice, just that the edges don't glitch when i do it with QDialog (Of course, then they are not in the same window). -
@Kaguro
I completely fail to reproduce that.
If you are able to make a video, you could certainly file a bug report at https://bugreports.qt.io -
@Axel-Spoerl It's very weird to me that it works differently at you. Maybe can you also show in a video what you see? (I will try make a bug report but for some reason I think this is not a bug, especially if you don't see this behavior)
-
@Kaguro
Well, even if the bug will be closed without a fix, we should have a look at it.