How to hide a QMainWindow until later?
-
I have created a splash window for my application, this works ok, however I want to hide the original main window until I am ready to display it, it has no ui associated with it, however it still appears even though I have called hide in the class constructor, here is a screenshot showing the new flash window which is shown on top of the original main window which is still appearing:
Here is the original main window constructor:clsMainWnd::clsMainWnd(QWidget* pobjParent) : QMainWindow(pobjParent) { //Check that window doesn't already exist Q_ASSERT_X(clsMainWnd::mspobjAppWnd==nullptr, "clsMainWnd", "mspobjAppWnd"); //Hide window until we want to show it hide(); //Create splash window new splash(this); //Get desktop geometry clsMainWnd::msrctDesktop = screen()->geometry(); //Save pointer to main window clsMainWnd::mspobjAppWnd = this; //Start socket server thread to listen to modules //This application is the socket server, when modules are started they //will send a message to this application via the server socket mspsckServer = new clsListener(clsListener::uint16NextPort(), this);
-
@SPlatten
Are you saying that if you comment outnew splash(this);
then this main window does not show?
Have you tried moving thehide()
to the caller which creates theclsMainWnd
?
Are you certain that nowhere else in your code does anythingshow()
this main window? -
@JonB , new splash is the new splash and is the once that shows on top in the screen shot, the window under it is empty and is the clsMainWnd without a ui, but still shows.
This is the constructor from the splash class:
splash::splash(QWidget *parent) : QMainWindow(parent) , ui(new Ui::splash) { //Modify the window to occupy full screen with no window dressing setWindowFlags(Qt::CustomizeWindowHint | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); //Get desktop geometry QRect rctDesktop(screen()->geometry()); //Set-up the user interface ui->setupUi(this); QString strTemp; strTemp = QString::asprintf("%dpx", rctDesktop.width()); ui->lblWidthVal->setText(static_cast<const QString>(strTemp)); strTemp = QString::asprintf("%dpx", rctDesktop.height()); ui->lblHeightVal->setText(static_cast<const QString>(strTemp)); //Set-up one second timer to perform house keeping functions QTimer::singleShot(REMOVE_SPLASH_TIME, this, &splash::onRemoveSplash); }
-
@SPlatten
Your "splash" screen is aQMainWindow
, designed to stay on screen for a second, really? I cannot imagine why you would choose aQMainWindow
here...! Per https://doc.qt.io/qt-6/qmainwindow.html#qt-main-window-framework aQMainWindow
is used for support for a menu bar, toolbar, dock widgets, central widget and status bar. That is why one uses it. Which of these are required for your one-second splashscreen?There is also a
QSplashScreen
class intended for this, though I don't want to get into a debate over what you doubtless consider your reasons are.But that has (or should have) nothing to do with show/hide behaviour.
I don't know whether what you are seeing is intentional or unavoidable. Can you afford to call
new splash()
(nothis
parent) instead, I assume that is the cause of seeing the main window behind the "splash" screen? -
@JonB , I'm really not sure I follow what you are suggesting, presently the new splash class works correctly and does exactly what it is supposed to do, the clsMainWnd which has no ui associated with it is still showing even though hide has been called in the constructor.
-
@SPlatten
As I wroteCan you afford to call
new splash()
(nothis
parent) insteadYou have statement:
new splash(this);
I am asking what behaviour is if you replace that line with
new splash();
Is that pretty clear? It's to investigate behaviour, cause of
clsMainWnd
being shown behind splashscreen. -
@JonB , thank you, in an effort to see what is happening I've added the connection:
QObject::connect(this, &QMainWindow::showEvent, this, &clsMainWnd::onShowEvent);
To my class constructor, although this results in:
/Users/sy/XMLMPAM/clsMainWnd.cpp:5507: error: 'showEvent' is a protected member of 'QWidget' ../clsMainWnd.cpp:5507:42: error: 'showEvent' is a protected member of 'QWidget' QObject::connect(this, &QMainWindow::showEvent, this, &clsMainWnd::onShowEvent); ^ ../../Qt/5.15.2/clang_64/lib/QtWidgets.framework/Headers/qwidget.h:654:18: note: must name member using the type of the current context 'clsMainWnd' virtual void showEvent(QShowEvent *event); ^
-
@SPlatten said in How to hide a QMainWindow until later?:
only the original which is empty
So in that case we can remove the splash screen from code? You are just reporting that creating a
QMainWindow
and goinghide()
in its constructor causes "a window with an empty UI" to be shown? Does not your caller which constructs theclsMainWnd
goshow()
on it?I would create a small, standalone test program which exemplifies what you are seeing. It is impossible to know what else might be going on in your code.
-
@SPlatten said in How to hide a QMainWindow until later?:
QObject::connect(this, &QMainWindow::showEvent, this, &clsMainWnd::onShowEvent);
QWidget::showEvent()
is not a signal (it is a Qt "event", any method they choose to useEvent
in its name is their convention, and they are not signals). You cannotconnect()
a slot to it.
You can, however,override
it in your derived class. -
@JonB , I'm trying to determine what is going on, the only place where clsMainWnd is created which is derived from QMainWindow is in main:
clsMainWnd w;
And I've just found the location where show is being called, thank you for you assistance.
-
@SPlatten
Yep, usually when a program creates one instance of aQMainWindow
(either on the heap or on the stack) it follows that by goingmainWindow.show()
. Which of course would undo thehide()
you have put in its constructor.As a tip: widget constructors should not show (or hide) themselves. The caller should be in charge of showing (or hiding) widgets.
-
No window shows itself by default. There is no need to add
hide()
into your constructor. You must be showing the window somewhere else (which is why @JonB suggested to usenew splash()
withoutthis
because this makes it a child of the main window and thus shows it with the main window).The most basic
main
function looks like this:int main(int argc, char *argv[]) { QApplication app(argc,argv); QMainWindow mw; mw.show(); return app.exec(); }
Are you sure you app does not include this
mw.show()
line? Instead you should callshow()
on your splash screen (which you don't seem to do). -
For the record, this is all done now, here is the splash.cpp:
static const int REMOVE_SPLASH_TIME = 10000; /** * @brief splash::splash * @param parent */ splash::splash(QWidget *parent) : QMainWindow(parent) , ui(new Ui::splash) { //Modify the window to occupy full screen with no window dressing setWindowFlags(Qt::CustomizeWindowHint | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); //Get desktop geometry QRect rctDesktop(screen()->geometry()); //Set-up the user interface ui->setupUi(this); QString strTemp; strTemp = QString::asprintf("%dpx", rctDesktop.width()); ui->lblWidthVal->setText(static_cast<const QString>(strTemp)); strTemp = QString::asprintf("%dpx", rctDesktop.height()); ui->lblHeightVal->setText(static_cast<const QString>(strTemp)); //Set-up one second timer to perform house keeping functions QTimer::singleShot(REMOVE_SPLASH_TIME, this, &splash::onRemoveSplash); } /** * @brief splash::~splash */ splash::~splash() { delete ui; } /** * @brief splash::onRemoveSplash * Removes the splash display when the timer expires */ void splash::onRemoveSplash() { hide(); }
-
@SPlatten
Now that you have resolved your question. I am still surprised why you would want anything derived from aQMainWindow
, plus its menubars etc. that you have been asking about, as a "splash" screen, which is set to disappear after 10 seconds? I know you are working on something "unusual" and generic, but still don't see the use case. -
@JonB , I was using the splash ui in my application purely for experimentation, I now have proven that I can dynamically create menus that are specified in my XML files and I have subscribers that are connected to the menu signals, it all works really well.