Choosing a window to show at app launch
-
First off, forgive me for the potentially basic question. I'm still a bit new to Qt in general, and I suspect I'm over-complicating this issue. I'm working on a desktop program in Qt 5.7. There's
MainWindow
, which is the general UI, but a newQMainWindow
has been added namedControllerWindow
. The idea is that if the--controlmode
argument is passed at runtime, the app will load and displayControllerWindow
instead ofMainWindow
.The catch is that
MainWindow
has a method that needs to be called --MainWindow::InitValues()
-- whichControllerWindow
does not have.What's the most "correct" way to handle this? I suppose the easy way is to do something like this, but I don't really like it, and feel like I'm an idiot blanking out on some obvious/simple/better approach:
if (controlModeEnalbed) { ControllerWindow cw; cw.show(); return a.exec(); } else { MainWindow mw; mw.InitValues(); mw.show(); return a.exec(); }
It works, but I rather prefer the idea of a single point of return instead of that ugliness. Any recommendations? Thank you for your time!
-
Hi and welcome to the forums
What about something like
ControllerWindow cw; MainWindow mw; mw.InitValues(); // must call always anyway QWidget* ToShow = &mw; // assume mainwin if (controlModeEnalbed) ToShow = &cw; ToShow->show(); return a.exec();
-
First off, forgive me for the potentially basic question. I'm still a bit new to Qt in general, and I suspect I'm over-complicating this issue. I'm working on a desktop program in Qt 5.7. There's
MainWindow
, which is the general UI, but a newQMainWindow
has been added namedControllerWindow
. The idea is that if the--controlmode
argument is passed at runtime, the app will load and displayControllerWindow
instead ofMainWindow
.The catch is that
MainWindow
has a method that needs to be called --MainWindow::InitValues()
-- whichControllerWindow
does not have.What's the most "correct" way to handle this? I suppose the easy way is to do something like this, but I don't really like it, and feel like I'm an idiot blanking out on some obvious/simple/better approach:
if (controlModeEnalbed) { ControllerWindow cw; cw.show(); return a.exec(); } else { MainWindow mw; mw.InitValues(); mw.show(); return a.exec(); }
It works, but I rather prefer the idea of a single point of return instead of that ugliness. Any recommendations? Thank you for your time!
// I assume here that both windows are derived from QMainWindow QMainWindow *window = nullptr; if (controlModeEnalbed) { window = new ControllerWindow(); } else { window = new MainWindow(); (dynamic_cast<MainWindow*>(window))->InitValues(); } auto result = a.exec(); delete window; return result;
-
First off, forgive me for the potentially basic question. I'm still a bit new to Qt in general, and I suspect I'm over-complicating this issue. I'm working on a desktop program in Qt 5.7. There's
MainWindow
, which is the general UI, but a newQMainWindow
has been added namedControllerWindow
. The idea is that if the--controlmode
argument is passed at runtime, the app will load and displayControllerWindow
instead ofMainWindow
.The catch is that
MainWindow
has a method that needs to be called --MainWindow::InitValues()
-- whichControllerWindow
does not have.What's the most "correct" way to handle this? I suppose the easy way is to do something like this, but I don't really like it, and feel like I'm an idiot blanking out on some obvious/simple/better approach:
if (controlModeEnalbed) { ControllerWindow cw; cw.show(); return a.exec(); } else { MainWindow mw; mw.InitValues(); mw.show(); return a.exec(); }
It works, but I rather prefer the idea of a single point of return instead of that ugliness. Any recommendations? Thank you for your time!
@fny82
Assuming your skeleton to be what you desire, you are saying thatMainWindow::InitValues()
only needs to be called when you are going to showMainWindow
, not when you are going to showControllerWindow
, right?When
controlModeEnabled
you only needControllerWindow
to be created, and when notcontrolModeEnabled
you only needMainWindow
to be created, right?And I assume both your
MainWindow
& yourControllerWindow
are derived (separately) fromQMainWindow
, right?To be fair, your existing code does implement this logic, so it's not too bad! Thought I probably wouldn't do it that way.
@mrjj's principle works, but always calls
MainWindow::InitValues()
, and also always constructs & leaves in existence both instances when you only need one, right?There are many ways you could approach this slightly differently from yours or @mrjj's.
If I take his approach I might suggest:
QMainWindow *qmw; if (controlModeEnabled) { MainWindow *mw = new MainWindow; mw ->InitValues(); qmw = mw; } else { ControllerWindow *cw = new ControllerWindow; qmw = cw; } qmw->show(); # To avoid leakage from the `new` prior to exit you will need to `delete qmw` or similar # I don't do that code 'coz I'm using Python, but you should # I leave it as an exercise for you to do correctly! return a.exec();
The point here is to
new
(on the heap) whichever (only) one you want, rather than messing about with local variables on the stack and their scope.Another approach would be to derive your own
MyBaseMainWindow
fromQMainWindow
, and then derive your two classes fromMyBaseMainWindow
. Your baseMyBaseMainWindow
could then have avirtual InitValues()
which does nothing, and yourMainWindow
only needoverride
that with its own code. Then you can always useyour_derived_main_window->InitValues()
at compile-time. If your two main window classes share other common code this can be nice.One other possibility without a base class to avoid the need for calling
mw.InitValues();
which you don't like might be to execute it from withinMainWindow::showEvent()
when first showing. Depends how early you need the initializations.In both these alternatives you'd still want the
new
s rather than local variables. -
Hi,
Since you need to call
InitValues
in all cases, why put it in your widget ? It looks like it could be a helper function in yourmain.cpp
that you call as part of your application startup. -
Brilliant suggestions. I knew I was over-complicating this. Thank you so much for the feedback and suggestions in this thread. It was immensely helpful and allowed me to solve this problem. I used a version of JonB and jsulm's suggestions, where I used a pointer to get around the scope issue and cast it to run the init method in the event the control mode argument was not in use. This did the trick beautifully. :)
Simplified example of what I ended up using:
QMainWindow* startupWindow = nullptr; if (controlModeEnabled) { startupWindow = new ControllerWindow(); startupWindow->show(); } else { startupWindow = new MainWindow(); (dynamic_cast<MainWindow*>(startupWindow))->InitValues(); startupWindow->show(); } auto execResult = a.exec(); delete startupWindow; return execResult;
-
Brilliant suggestions. I knew I was over-complicating this. Thank you so much for the feedback and suggestions in this thread. It was immensely helpful and allowed me to solve this problem. I used a version of JonB and jsulm's suggestions, where I used a pointer to get around the scope issue and cast it to run the init method in the event the control mode argument was not in use. This did the trick beautifully. :)
Simplified example of what I ended up using:
QMainWindow* startupWindow = nullptr; if (controlModeEnabled) { startupWindow = new ControllerWindow(); startupWindow->show(); } else { startupWindow = new MainWindow(); (dynamic_cast<MainWindow*>(startupWindow))->InitValues(); startupWindow->show(); } auto execResult = a.exec(); delete startupWindow; return execResult;
@fny82 said in Choosing a window to show at app launch:
startupWindow = new MainWindow();
(dynamic_cast<MainWindow*>(startupWindow))->InitValues();
I find this ugly/unwieldy! That's why I wrote:
MainWindow *mw = new MainWindow; mw ->InitValues(); qmw = mw;
Create an explicit
MainWindow*
variable first so as to use its method without casting, then assign it to your sharedQMainWindow*
variable.