how to switch windows between cpp files? in Qt - c++

I have problem with my small app in Qt framework C++
I have a first window which there's two buttons where you can choose to play music or video. The music button will close the "choose window" and should open "music window" and similarly for video button.
I don't know how to do this... I know a way which I've leant and used but this method I'm going to explain how it doesn't fit to my current issue.
I've created a pointer of that window class in header of choose window and when the music button is clicked, I new the pointer and musicWindow->show(); and hide(); the choose window, this is good but there is a problem:
the new opened music window doesn't have any taskbar icon/thumbnail and when Its minimized there's no way to have that opened again(except wtih alt-tab)
and dont find a way to open it like a complete new window, I just can open all of them at once by using choosWindow.show(); / musicWindow.show(); /... .
I know there must be a way, but I dont even know what topics to search for to get further...
FirstWindow.cpp:
void FirstWindow::on_musicChoose_clicked()
{
//send a signal from here
}
void FirstWindow::on_videoChoose_clicked()
{
//send a signal from here
}
main.cpp:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
FirstWindow w;
if(//what condition?)
{
MusicWindow mw;
mw.show();
}
if(//what condition?)
{
VideoWindow vw;
vw.show();
}
return a.exec();
}

I found my answer in Qt Forum:
https://forum.qt.io/topic/68602/child-window-in-taskbar/3
#Radek(Qt Forum): Try passing 0 (zero) as parent when you create them.
FirstWindow.cpp:
void FirstWindow::on_musicChoose_clicked()
{
this->hide();
mw = new MusicWindow(0); // passing nullptr as parent
mw.show();
}
void FirstWindow::on_videoChoose_clicked()
{
this->hide();
vw = new VideoWindow(0); // passing nullptr as parent
vw.show();
}
main.cpp:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
FirstDialog w;
w.exec();
return a.exec();
}

Related

Show Window with Shortcut Keybinder and Focus to TextBox GTK4

I'm building a project like uLauncher where I can pop out a window and focus on the textbox right away. I was able to get the window out using libkeybinder for the shortcut and get the window out with win->show(), but the problem is that the keyboard cursor is in the window behind the window.
How do I get the focus to be on the textbox window?
This is the main code:
void shortcutHandler(const char *keystring, void *user_data) {
winroot->show();
}
int main(int argc, char *argv[]) {
Gtk::Main kit(argc, argv);
winroot = new MainWindow();
auto app = Gtk::Application::create(GTK_ID);
app->hold();
keybinder_init();
keybinder_bind(KEY_SHORTCUT, shortcutHandler, NULL);
return app->run(*winroot);
}
``

How to hide QMainWindow and show splashcreen during startup?

I am trying to hide the MainWindow of my Qt desktop app during startup, and to show a splashscreen. Both only happens after the loading phase, even though I call both splash.show() and window.hide() before the loading phase. I tried to split loading phase and constructor, but result is the same. How can I achieve both before the loading phase ?
Update 1
To display the splash screen, I had to add a call to QApplication::processEvents()
Update 2
The black window was actually not the MainWindow, but a ghost window that popped because scrollArea->setVisible(true) was called in the constructor.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPixmap pixmap(QStringLiteral(":/ressources/icons/icon.png"));
QSplashScreen splash(pixmap);
splash.show();
MainWindow window; // this loads for 5-6 seconds
a.processEvents();
window.showLoginPrompt();
splash.finish(&window);
return a.exec();
}
Based on your code and some example I could make it run like you are trying to do.
You only need to call your promptLogin function instead.
#include <QApplication>
#include <QTimer>
#include <QSplashScreen>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSplashScreen *splash = new QSplashScreen;
splash->setPixmap(QPixmap("D:\\Projects\\SplashScreen\\TestSplashScreen\\splash.png"));
splash->show();
MainWindow mainWin;
QTimer::singleShot(2500, splash, SLOT(close()));
QTimer::singleShot(2500, &mainWin, SLOT(show()));
return app.exec();
}

Run QFileDialog::getOpenFileName without separate event loop?

I'm using QFileDialog::getOpenFileName right now. However, as suggested in this article, this crashes when the main application closes while the dialog is open. You can see an example of how to reproduce the crash here:
int main(int argc, char **argv) {
QApplication application{argc, argv};
QMainWindow *main_window = new QMainWindow();
main_window->show();
QPushButton *button = new QPushButton("Press me");
main_window->setCentralWidget(button);
QObject::connect(button, &QPushButton::clicked, [main_window]() {
QTimer::singleShot(2000, [main_window]() { delete main_window; });
QFileDialog::getOpenFileName(main_window, "Close me fast or I will crash!");
});
application.exec();
return 0;
}
I can use QFileDialog with the normal constructor instead, as described here. However, then I don't seem to get the native windows file open dialog.
Is there a way to get a non crashing program and use the native Windows file open dialog through Qt?
If you close your main_window instead of deleting it, you won't get any crash.
By the way, you could check if there is any QFileDialog opened to avoid a wrong app exit.
In the next example, I'm closing the dialog, but you could implement another solution:
#include <QTimer>
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
#include <QFileDialog>
#include <QDebug>
int main(int argc, char **argv) {
QApplication application{argc, argv};
QMainWindow *main_window = new QMainWindow();
main_window->show();
QPushButton *button = new QPushButton("Press me");
main_window->setCentralWidget(button);
QObject::connect(button, &QPushButton::clicked, [main_window]() {
QTimer::singleShot(2000, [main_window]() {
QObjectList list = main_window->children();
while (!list.isEmpty())
{
QObject *object= list.takeFirst();
if (qobject_cast<QFileDialog*>(object))
{
qDebug() << object->objectName();
QFileDialog* fileDialog = qobject_cast<QFileDialog*>(object);
fileDialog->close();
}
}
main_window->close();
});
QFileDialog::getOpenFileName(main_window, "Close me fast or I will crash!");
});
application.exec();
return 0;
}
The design of your application is broken. The shut down of the application normally happens when the outernmost event loop in the main thread exists. This won't happen while a file dialog is active - by definition, its event loop is running then. Thus you're doing something you shouldn't be doing, and the file dialog is merely a scapegoat, or a canary in the coalmine indicating brokenness elsewhere.

Communicate with two instances of Qt program

I used in my Qt program code to avoid opening second instance:
#include "mainwindow.h"
#include <QApplication>
#include <QSharedMemory>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
const char* MEM_KEY = "42";
QSharedMemory sharedMem(MEM_KEY);
if (sharedMem.create(1024))
{
qDebug() << "Create shared memory";
}
else
{
if (sharedMem.error() == QSharedMemory::AlreadyExists)
{
qWarning() << "Already create. Exiting process";
return 1;
}
}
MainWindow w;
w.setWindowFlags(Qt::MSWindowsFixedSizeDialogHint);
w.show();
return a.exec();
It works (this code block opening second instance of my aplication [it is automatically close]), but I want to send an message or signal from opened for a moment second instance to first instance to perform for ex. maximalize window of first instance. Could you tell me how to do this simply?
You can use QtSingleApplication for this purpose. For example:
int main(int argc, char *argv[])
{
QtSingleApplication a(argc, argv);
if (a.isRunning())
{
a.sendMessage("42");
qWarning() << "Already create. Exiting process";
return 1;
}
MainWindow w;
a.setActivationWindow(&w);
QObject::connect(&a, SIGNAL(messageReceived(QString))
, &w, SLOT(onMessageReceived(QString)));
w.show();
int ret = a.exec();
QObject::disconnect(&a, 0, &w, 0);
return ret;
}
...
void MainWindow::onMessageReceived(const QString &message)
{
// Do stuff
}
You are looking for IPC (inter process communication) and sadly, i don't think there is a portable way of doing this, except for creating a socket and listening on 127.0.0.1. But if you are on unix i do recommend using qdbus. That is what all the cool linux programs are doing ;)
On windows there is i believe something similar. (But this is all not built into qt.) You can find the handle of your window (HWND) and use sendmessage().
to send a custom message you'll have to declare your own WM_SECONDINSTANCE (or something similar) by:
#define WM_SECONDINSTANCE WM_USER
#define WM_SOMEOTHERMESSAGE WM_USER+1
or use an enum (i'm lazy).
This tells your existing instance that another instance has been opened. To handle it in qt have a look at this.
To find the HWND, i would just put it int your shared memory from your first instance.
(My windows-knowledge is a bit rusty, so sorry for any errors)

How I show application when open application again Qt

Now, I have 1 application, but I don't want to open application twice, so I using QShareMemory to detect application when open twice.
And my question is: how I show current application in screen when user open application the second ?
int main(int argc, char *argv[]) {
Application a(argc, argv);
/*Make sure only one instance of application can run on host system at a time*/
QSharedMemory sharedMemory;
sharedMemory.setKey ("Application");
if (!sharedMemory.create(1))
{
qDebug() << "123123Exit already a process running";
return 0;
}
/**/
return a.exec();
}
Thanks.
Here's another approach in pure Qt way:
Use QLocalServer and QLocalSocket to check the existence of application and then use signal-slot mechanism to notify the existing one.
#include "widget.h"
#include <QApplication>
#include <QObject>
#include <QLocalSocket>
#include <QLocalServer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
const QString appKey = "applicationKey";
QLocalSocket *socket = new QLocalSocket();
socket->connectToServer(appKey);
if (socket->isOpen()) {
socket->close();
socket->deleteLater();
return 0;
}
socket->deleteLater();
Widget w;
QLocalServer server;
QObject::connect(&server,
&QLocalServer::newConnection,
[&w] () {
/*Set the window on the top level.*/
w.setWindowFlags(w.windowFlags() |
Qt::WindowStaysOnTopHint);
w.showNormal();
w.setWindowFlags(w.windowFlags() &
~Qt::WindowStaysOnTopHint
);
w.showNormal();
w.activateWindow();
});
server.listen(appKey);
w.show();
return a.exec();
}
But if you're using Qt 5.3 on Windows, there's a bug for QWidget::setWindowFlags and Qt::WindowStaysOnTopHint, see https://bugreports.qt.io/browse/QTBUG-30359.
Just use QSingleApplication class instead of QApplication:
https://github.com/qtproject/qt-solutions/tree/master/qtsingleapplication
int main(int argc, char **argv)
{
QtSingleApplication app(argc, argv);
if (app.isRunning())
return 0;
MyMainWidget mmw;
app.setActivationWindow(&mmw);
mmw.show();
return app.exec();
}
It is part of Qt Solutions: https://github.com/qtproject/qt-solutions