How does Qt find widget instances? - c++

At the first, Qt isn't my primary framework as well as C++ isn't my primary language, so my question may be very easy but it's unclear for me from tutorials.
There is a simple sample in official tutorial:
#include <QApplication>
#include <QPushButton>
int main(int argc, char **argv)
{
QApplication app (argc, argv);
QPushButton button ("Hello world !");
button.show();
return app.exec();
}
But they don't explain how button links with app to it could be shown and wait events. I can imagine there is a some singleton and button, and app find each other via that singleton or there is a some preprocessor that finds widget instances and automatically links it with app instance. But I want to know real situation. How are they linked together?
P.S. I am sure someone asked a similar question already but I couldn't find. If you know any duplicate of my question, specify it, pls, I will delete my topic then.

Your guess is almost correct despite the fact that the "singleton" is the QApplication itself.
By reading the QApplication's documentation, you can see that only one QApplication object has to exist.
According to the documentation again:
"It handles widget specific initialization, finalization."
Then to answer your question, I know that there exists a global pointer to the QApplication instance that you can access via qApp.
I'm pretty sure that this is what it is used by any QWidget to find the QApplication object.

Related

Creating, handling and switching between windows QTCreator

My research into the question suggests that I'm somewhat beating a dead horse, however I can't seem to get a conclusive answer.
I'm using QT Creator to create a GUI that will help interface with a register of units(simple objects, with some ID's and such).
I have a Main Menu, which contains 5 push buttons and a table. Pictured here. My project currently includes these files, and my main currently looks like this:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
UnitRegister e;
CommInterface c;
w.setRegistryPtr(e);
w.setCommPtr(c);
w.setTablePtr(w.findChild<QTableWidget*>("unitTable"));
w.show();
return a.exec();
}
What I want to do is press one of the four push-buttons on the left, and use that to switch to a different view in the main window.
For this purpose I considered using a QStackedWidget, and then having a page for each menu button. My question is this:
How do I/Should I create a separate QT Item Form Class(header, .cpp
and .ui file) for each page
How do I switch between the pages I've added using the QT Designer.
How do I ensure that the different pages can access the UnitRegister created in my main file.
I'm not necessarily searching for a complete answer, but something to get me going.
Switching Pages: Consider a QButtonGroup to give your buttons ids that you can map to the indexes of your QStackedWidget. Then you can do this:
connect(buttonGroup, SIGNAL(buttonClicked(int)), stackedWidget, SLOT(setCurrentIndex(int)));
Organizing the Pages: Create a .ui file and corresponding container widget for each page in your widget stack. This is much easier than one massive .ui file.
Accessing the UnitRegister: There are tons of ways to do this. Adding a setter function to your classes is one way.

QApplication does not exit when main window closes

I have a QMainWindow that is used to browse and view images with. These images are special medical images that are read using a wrapper that I wrote.
The GUI has a QListview on the left, which shows a list of thumbnails. When the user selects one of them, the QVTKWidget displays the corresponding image on the right. I use a vtkRenderWindowInteractor to manipulate the displayed image.
My main looks like the following:
#include <QApplication>
#include "GUIClassName.h" //inherits from QMainWindow
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GUIClassName w;
w.show();
return a.exec();
}
My closeEvent looks like the following:
void GUIClassName::closeEvent(QCloseEvent* event)
{
// mainInteractor is a vtkSmartPointer<vtkRenderWindowInteractor>
if (this->_mainInteractor != NULL)
this->_mainInteractor->TerminateApp();
event->accept();
}
The issue is that when I close the QMainWindow, the application does not terminate. That is the command prompt stays open and Press any key to continue does not appear. If I Ctrl+break, then the application exits (obviously) but I get the following message:
QObject::~QObject: Timers cannot be stopped from another thread
I have noticed that if I only select one thumbnail and display it in the QVTKWidget, the program terminates just fine. But when I select one thumbnail, display it and then select another thumbnail, then the program does not terminate when I close the window.
I was wondering if anyone could tell me what I am doing wrong here. I would gladly copy/paste more code, but I am not sure which parts are relevant at the moment.
I have read the following in hopes of an answer, but so far I have been unable to solve this issue:
Qt app stays in memory even after MainWindow is closed
Qt process stays in memory after application closes
C++ application does not kill all processes on exit
Thanks
Did you stop all your threads?
I'm not familiar with VTK, but looks like someone run some code in thread and did not stop them properly.
RazrFalcon gave me a good hint. I am not an expert in Qt (yet) so I was looking for the Qthread that was being executed at all the wrong places.
The answer lies in the vtkRenderWindowInteractor class. For most vtkObjects (if I am not mistaken), calling new on the vtkSmartPointer deletes/stops the object if it already exists. However, this does not happen for vtkRenderWindowInteractor.
The solution was the following. When switching between thumbnails, I had to check for the existence of the interactor and if it was running, I would just call
this->_mainInteractor->TerminateApp();
to stop the hidden Qthread.

How to use QCursor::pos() without using QApplication?

I'm writing a project in Qt Creator, and if I write
QPoint cursorPos=QCursor::pos();
then cursorPos={-2147483648,-2147483648} which is obviously wrong. However, if I write
QApplication *application=new QApplication(argc,argv);
QPoint cursorPos=QCursor::pos();
then cursorPos is the correct mouse position. Is there any way I can get QCursor::pos() to work without QApplication? Thanks. :D
QApplication object does so much initialization. One of the QApplication's main areas of responsibility in the Qt documentation :
It manages the application's mouse cursor handling, see setOverrideCursor()
Also from the Qt documentation about QCursor :
Note: It is possible to create a QCursor before QGuiApplication, but
it is not useful except as a place-holder for a real QCursor created
after QGuiApplication. Attempting to use a QCursor that was created
before QGuiApplication will result in a crash.
So it seems that it is not possible to use QCursor without QApplication or QGuiApplication.

Run a method from a C++ program with Qt without writing entire program in Qt [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
Is it possible to run a certain method from a C++ program with Qt with certain input parameters when for instance a button is clicked without writing the complete program in Qt itself?
Let's say that I have a project in Visual Studio with a corresponding .exe and I want to run the method example with input parameter 5 whenever a button is clicked. How could I do that?
Qt operates by creating a QWidget window, and then an event loop.
Your code to create a window, and then a button that triggers another function is trivial.
Many of the examples Qt provides show this functionality.
To get started, Download Qt. Download the Qt Add-On for Visual Studio. Note, that the express edition of visual studio doesn't work with the Qt Add-On.
After you have all that done, create a Qt project from the Qt classes that are available. In this case, I would not choose QML/Qt Quick, but just a Qt Widgets class, such as QWidget or QDialog or QMainWindow.
Using the Qt Add-On should ensure that you have the libraries found and available to Visual Studio.
Make sure that you can get a Hello World example is buildable and running using a Qt Widget of some sort.
The code it generates for you should look like this:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
To add in a button, you need to place it on a Widget and then connect a SLOT to its clicked() signal. The following is a compact way to do it.
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QDebug>
#include <QApplication>
static void someFunction ()
{
qDebug() << "Button was clicked";
// run my other function that requires a parameter of 5
qDebug() << "Run my other function with 5!";
// otherFunction(5);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
QPushButton *button = new QPushButton("Click Me");
QObject::connect(button, &QPushButton::clicked, someFunction);
QVBoxLayout *vbox = new QVBoxLayout();
vbox->addWidget(button);
w.setLayout(vbox);
w.show();
return a.exec();
}
To make a powerful GUI, you will want to leverage more than just a functor, and use QObjects and let it use the moc compiler and create your own signals and slots for all your custom functions.
Connecting to a functor is new with Qt 5.
http://qt-project.org/wiki/New_Signal_Slot_Syntax
http://woboq.com/blog/new-signals-slots-syntax-in-qt5.html
A more verbose way to do it, but allows for more expandability and OOP, is to subclass QWidget or QMainWindow, like it generated for you, and put a method in your subclassed function that you put under your slots list in your header file.
http://qt-project.org/doc/qt-5/signalsandslots.html
Take the time to understand signals and slots and you can create almost any GUI you can imagine using Qt. Good luck.
Hope that helps.

Qt: Access Widget from main function and implement exit button

I want to implement an exit button in my application, which has the following setup:
I have a main function which looks like this:
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
I also have a mainWindow function which has been generated by the QT Creator IDE.
I design the GUI with the Qt Designer and when I want a pushbutton to do something when clicked, I use a function like this:
void on_selection_clicked();
I hope the setup is now sufficiently described.
Now to my problem: I want to implement a button, which, when clicked, terminates the window and the application. I first tried implementing this in a function like this:
void on_exit_clicked();
But I don't know that to to here.
Then I heard of a aproach via QObject::connect, but I have two questions:
1.) Where should I put this? In the main function? 2.) can I access the object simply via the object name given in the QT Designer?
no you should connect it in the constructor of the MainWindow
connect(ui->exit,SIGNAL(clicked()),QCoreApplication::instance(), SLOT(exit()));
QCoreApplication::instance()->exit() will quit the application
yes through the ui field in MainWindow see the code above
I don't know which Qt version you use, so I will suppose Qt 5.0 (signal/slot mechanims was updated).
QWidget has slot QWidget::close().
QPushButton provides signal QPushButton::clicked(bool checked = false)
So you can connect them in constructor of your MainWindow:
QObject::connect(your_button, &QPushButton::clicked, this, &QWidget::close());
Also I suggest to look into the files generated from *.ui files - so you have deeper understanding of what's going on.