[SOLVED] How to destroy parent QWidget window and create&show new QWidget as parent?
-
It might be working but it's not clean at all.
First thing, what does FreeConsole do there ?
Widgets already have a parent method to retrieve it, no need for a member variable.
Don't use c-style cast with QObject derived class, use qobject_cast.
BUT, that design is wrong: keep the responsibilities separated.
Your setting widget should just handle the settings, it's not its job to modify the content of your main window. The main window itself should handle that.
Take the case where you change some stuff in your main window, something as little as just one variable name, now you have to look at three different places to change that. I know that with modern IDE it's not a real problem but the fact is that your code is going to be a nightmare to maintain.
Please take the time to look at Qt's examples, they show nicely how to do what you want.
-
[quote]First thing, what does FreeConsole do there ?[/quote]As I already mentioned, I need it to close the command box that opens every time I start my program. I read in google that this is an easy way to hide the command box, but the problem is the flicker at the beginning, because it still opens for 0.5s and I see it appearing (what sucks and I need a solution to avoid it).
Any solutions for that?
[quote]Widgets already have a parent method to retrieve it, no need for a member variable.[/quote]Oh yes, that's right :) So many great functions provided by Qt classes!! I will spend lots of days finding new good features that make my life easier :)
[quote]Don’t use c-style cast with QObject derived class, use qobject_cast.[/quote]Ok...
[quote]Your setting widget should just handle the settings, it’s not its job to modify the content of your main window. The main window itself should handle that.Take the case where you change some stuff in your main window, something as little as just one variable name, now you have to look at three different places to change that. I know that with modern IDE it’s not a real problem but the fact is that your code is going to be a nightmare to maintain.[/quote]Oh yes, good aspect! I'm sure that at the latest when my program grows I'd have to spend lots of time thinking about opportunities to make code more dynamic like a layout, where I only have to change things in one sheet...
Thank you for that advice, that will help me much while planing future applications!!
What I additionally did is including the QDialog into main_window class as a member with a function to get input:
@class window_settings : public QDialog
{
Q_OBJECTpublic:
int columns;
my_QTextEdit* edit_person[10];
QPushButton* button_create;window_settings(int columns, QWidget* parent = 0); QStringList getInputTextEdit();
};
class window_main : public QWidget
{
Q_OBJECTpublic:
window_settings* win_settings;
QTableWidget* table;
QStringList table_headers_v, table_headers_h;
QListWidget* list;
QPushButton *button_settings, *button_calculate;window_main(int rows, int columns, QStringList &table_headers_h, QWidget* parent = 0); void updateAll();
public slots:
void settings();
void calculate();
};int main(int argc, char** args)
{
FreeConsole();
QApplication app(argc, args);QStringList table_headers_h; table_headers_h << "Amount"; for(int i = 1; i < 11; i++) { table_headers_h << "Person "+QString::number(i); } window_main* win_main = new window_main(100, 11, table_headers_h, NULL); win_main->win_settings = new window_settings(10, win_main); win_main->show(); win_main->settings();
return app.exec();
}window_main::window_main(int rows, int columns, QStringList &table_headers_h, QWidget* parent) : QWidget(parent)
{
//....
button_calculate = new QPushButton("Calculate", this);
connect(button_calculate, SIGNAL(clicked()), this, SLOT(calculate()));button_settings = new QPushButton("Settings", this); connect(button_settings, SIGNAL(clicked()), this, SLOT(settings()));
}
void window_main::settings()
{
this->win_settings->exec();
}@
How do you think about this? QDialog opens now each time user clicks window_main button "Settings".
In window_main function "updateAll()" (not shown in code), it calls QDialog function getInputTextEdit() and retrieves the stored inputs to update itsself...
Good or bad way? -
Do you have QT += console somewhere in you pro file ? If so, just remove it.
@
QStringList table_headers_h;
table_headers_h << "Amount";
for(int i = 1; i < 11; i++)
{
table_headers_h << "Person "+QString::number(i);
}
@Should rather be in your widget constructor.
If you don't want to, then you should pass your QStringList as a const reference.You still have a memory leak, you never delete win_main.
Are you still modifying window_main from your settings dialog ?
-
[quote]Do you have QT += console somewhere in you pro file ?[/quote]I'm directly compiling. I did a little program that directly calls g+++ with the needed includes, so what do I have to change to avoid displaying the command line box?
[quote]Should rather be in your widget constructor.[/quote]Thats right, it is there, I just moved it to main() for posting it, because I did not want to show the whole constructor to shorten the code & comment.
[quote]You still have a memory leak, you never delete win_main.[/quote]Oh yes, I'll fix that, but where should I do that? The only way would be to connect window closing signal to a function that deletes win_main, right? But closing the window is not the only way to close an application, so how can I avoid the memory leak if someone closes the application via taskbar / taskmanager or something else? Is there also a genereal QApplication closing signal or something else?
[quote]Are you still modifying window_main from your settings dialog ?[/quote]No, I have two functions now:
- function A (win_main member) calls function B (win_settings member) and retrieves the userinput from win_settings. So win_main updates itsself...
-
Why don't you use qmake ?
You have several possibilities but since your program is pretty simple:
@
window_main win_main(100, 11, table_headers_h);
@is enough
-
I thought Qt is known for good care about automatically deleting dynamically created QWidgets? I strongly use the QWidget* parent method to initialize each new QWidget as a child of win_main...
So the only thing compiler has to do is caring about deleting win_main...
Why doesn't this happen after closing the event-loop?
Where would I have to manually call it's destructor then? I don't know... -
Yes it does but it can't do everything:
@
window_main* window_m = new window_main(100, 11, table_headers_h); << window_m is allocated on the heap, with no parent, so it's outside of Qt's scope.
window_m->show();return app.exec();
@Either use:
@
window_main window_m(100, 11, table_headers_h);
window_m.show();
return app.exec();
@or
window_main* window_m = new window_main(100, 11, table_headers_h, NULL);
window_m->show();int ret = app.exec();
delete mainwindw_main;
return ret;
@ -
Ah there we go. Then it is a little bit the way I already tried to go.
First:
[quote]window_main* window_m = new window_main(100, 11, table_headers_h, NULL); [/quote]That is exaclty what I'm doing, take a look at my constructor:
@window_main::window_main(int rows, int columns, QStringList &header, QWidget* parent = 0) : QWidget(parent)
{
...
}@
I don't pass the NULL pointer directly by calling constructor but I declare constructor with it as default value... should be the same, isn't it?[quote]int ret = app.exec(); delete mainwindw_main; return ret;[/quote]That is exactly what I already thought of... So I still have to delete the parent QWidget manually? Then that will be the only way, and for that reason I should really take care of all my widgets to be childs of at least one parent, so I'm always safe when I just delete one QWidget.. is that the right way?
-
Yes it is, but that was just a simplified copy paste of your code to show the possibilities.
Not the parent but parentless widgets (which generally ends up being the "parent"), unless you set the WA_DeleteOnClose flag on that widget.
-
Ok, I think I got it now..
I'll do it like you recommended and delete the "parent" (parentless aka NULL pointer) after app.exec() returned and finally, I'll return the returned value from app.exec()...Thank you so much for your help and endurance!
-
Well, in this case, there's no real reason to use a pointer for your widget. Just allocate it on the stack and let it get destroyed when going out of scope.
-
Ok, you're right. I'll change this, thank's :)