Cannot create a Qt dialog inside another - c++

This code generates two separate dialogs, while I would like one to be inside the other:
class MyTree : public QWidget {
QTreeView *view;
...
}
//class MyTree : public QDialog {...} // same result
QApplication testApp(argc, argv);
QDialog *topWidget = new QDialog;
MyTree *pjrTree = MyTree::Build();
pjrTree->setParent(topWidget);
topWidget->show();
testApp.exec();
Both the dialog and the tree appear correctly. I just cannot enforce the containment relation.

You're doing it completely incorrectly. You have to create a layout, which contains your elements.
Look at this example:
http://qt-project.org/doc/qt-5.0/qtwidgets/dialogs-findfiles.html

Your solution set only parent of pjrTree but don't add it to QDialog layout. You can simply inherent class MyTree from QDialog, which directly inherent QWidget. It would be more clear and correct.

Deriving the class MyTree from QTreeView, instead of having a pointer to QTreeView as a member variable, fixed my problem.

Related

What are `(QWidget* pobj=0)` and `(QWidget* pwgt/*=0/)` for?

I have just started to learn QT. Can't understand how do theese constructors work. For example:
//Progress.h
#include<QtWidgets>
class QProgressBar;
class Progress:public QWidget{
Q_OBJECT
private:
QProgressBar* m_pprb;
int step;
public:
Progress(QWidget* pobj=0);
public slots:
void slotStep();
void slotReset();
//
//Progress.cpp
#include<QtWidgets>
#include"Progress.h"
Progress::Progress(QWidget* pwgt/*=0*/):QWidget(pwgt)
{
//some buttons
}
So, the question is, what happens in constructors?
What you are creating is a Progressclass which inherits from QWidget.
The QWidget class can take an parentargument, if you look at the documentation:
Constructs a widget which is a child of parent, with widget flags set to f. If parent is nullptr, the new widget becomes a window. If parent is another widget, this widget becomes a child window inside parent. The new widget is deleted when its parent is deleted.
This parentin your code is called pwgt (I would think it stands for parentWidget)
What you do, is creating a default argument for your constructor to be set automatic to 0:
Progress(QWidget* pobj=0);
Cleaner maybe would be (for convenience with Qt standard):
Progress(QWidget* parent=nullptr);
So, why do do you need the constructor to look like this?
It is the same reason, which stands for QWidget:
You can set a parent widget, but you don't have to!
The QWidget class will deal for you with this, either you set a parent or not.

Qt: parent-child widgets. Does closing of a single child widget imply closing of other children?

I have the following problem with the test Qt application, which contains one parent widget and two child widgets, which are separate windows. If the parent widget is hidden, then closing a single child widget implies closing the second child as well as closing the whole application.
Is it the normal behavior of the parent/child widgets in Qt? Is there a way to keep the second child widget visible and the application running?
#include <QApplication>
#include <QtWidgets>
class MyWidget : public QWidget {
public:
MyWidget(const QString& title = "", QWidget *parent = nullptr) :
QWidget(parent) {
setWindowTitle(title);
setWindowFlags(windowFlags() | Qt::Window);
setVisible(true);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyWidget parent("Parent");
MyWidget *child1 = new MyWidget("Child1", &parent);
MyWidget *child2 = new MyWidget("Child2", &parent);
QTimer::singleShot(5000, [&](){parent.hide();});
return a.exec();
}
There're three widgets of simple class MyWidget:
the parent one 'parent' with two childs 'child1' and 'child2'.
After 5 sec the parent widget is hidden by the QTimer::singleShot.
After that, if I close, e.g. child1 window, the second window child2
is also automatically closed and the application is finished.
I'd expect that child1 and child2 are independent, and closing one of them shouldn't close another one.
Usually children in Qt are independant of another just like you want them to. However when the last primary window is closed in (see QApplication::lastWindowClosed) the application closes as a whole. Likely thats whats happening here. I am unsure why, though.
What you could try is manually define closeEvents for your windows. Still your behaviour is weird, as I remember reading that hiding a parent window should also hide its children here: (https://www.qtcentre.org/threads/61708-Multiple-windows-hide-parent-when-child-shown-unhide-when-child-closed).

Adding widget to layout only works in constructor of custom class

I have a class MainWindow subclassing QMainWindow. As the central widget I have a QScrollArea with a QWidget inside, as a container for my own custom widgets. I set a QVBoxLayout as the layout for the QWidget container and pass this layout to the constructor of my custom class, which is supposed to dynamically create instances of my custom widget class and add them to the layout.
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = Q_NULLPTR);
virtual ~MainWindow ();
private:
QVBoxLayout mainLayout;
QScrollArea scrollArea;
QWidget container;
NotificationControl control;
};
MainWindow::MainWindow (QWidget *parent) :
QMainWindow(parent),
container(&scrollArea),
control(&mainLayout) {
container.setLayout(&mainLayout);
scrollArea.setWidget(&container);
setCentralWidget(&scrollArea);
}
Now in my NotificationControl class I have a method addNotification:
void NotificationControl::addNotification (Notification notif) {
qDebug() << "NotificationControl addNotification" << notif.get_app_name();
NotificationWidget* widget = new NotificationWidget(notif);
container->addWidget(widget);
}
When this method is called, I get the debug output, but nothing is added to the layout. But if I add this to the end of the constructor of NotificationControl...
NotificationWidget* notif = new NotificationWidget(Notification());
container->addWidget(notif);
...for some reason it works. I'm pretty sure the problem isn't the NotificationWidget class. For testing purposes I made some changes, it doesn't actually use the Notification object that is passed at all.
What could be the problem?
Edit: I just noticed that adding widgets later (not in constructor) makes the widgets added in the constructor disappear.
Any widget added as a child widget must be explicitly shown if the parent widget is already visible. Usually, the child widgets are added before the parent widget is shown, and they then become visible themselves, too. But if you add them later, you must make them explicitly visible.

Adding custom QWidget during runtime

I'm trying to implement a custom widget hierarchy:
QMainWindow -> QFrame -> MyWidget -> QFrame -> MySubWidget
Here is how MyWidget class looks like:
class MyWidget : public QWidget {
Q_OBJECT
public:
MyWidget(QWidget *parent = 0, ...);
...
public slots:
void SlotFunction(int i);
...
private:
MySubWidget *sub_w;
QFrame *sub_frame;
...
}
If I try to create an MySubWidget during MyWidget constructor, then all MySubWidget elements are shown as intended:
MyWidget::MyWidget (...) : QWidget(parent) {
...
sub_frame = new QFrame(this);
...
sub_w = new MySubWidget(sub_frame); // commented out on a runtime test
}
But if I try to add subwidget during runtime, sub_frame remains blank. I.e. signal reaction:
void MyWidget::SlotFunction(int i) {
sub_w = new MySubWidget(sub_frame); // update, repaint, show and hide methods aren't helphul
}
I know this is an old question, but I was having a very similar issue and it turned out to be a lack of call to the QWidget::show(). Perhaps that was your problem as well?
My question here: Dynamically add instance inherited from QWidget
Cheers.
Are you reaching your function?
At the top of your function before making a new instance of MySubWidget put:
qDebug() << Q_FUNC_INFO;
Is the slot connected properly?
Qt will let you know if it is unable to connect a slot using a runtime warning. Look at the debug output that shows up in Qt Creator and it may mention a reason why the slot was never reached.
Is subframe visible?
If the parent of your object isn't visible, then showing or hiding the child object will only affect it when the parent is shown.
Hope that helps. Good luck.

Qt : is good in a c++ class to have a widget field not declared as a pointer

class Foo : public QMainWindow
{
MyWidget *alertDlg_;
MyWidget alertDlg2_;
};
Is second field can be dangerous ?
Thanks
EDIT:
example of problem :
{
QPushButton button("button");
QWidget widget;
button.setParent(&widget);
} // crash
Yes, because the Qt has it's own memory management, and if alertDlg2_ has a parent, you would get double deletion.
You can read more about qt object trees and ownership in this article. You can see in it that it is not safe to do what you did in your edited example. That is why are you getting the crash.