Qt: Access Widget from main function and implement exit button - c++

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.

Related

Call events from the main function

I was used, in java, to create events almost anywhere, but in c++ (Qt), I notice that you have to create a class to be able to use the object's events. My question is the following : would it be possible to use MouseEvent (or any other event) belonging to a QPushButton from the main function ?
#include <QApplication>
#include <QWidget>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication app(argc,argv);
QWidget window;
QPushButton* btn = new QPushButton("Add",&window);
//Here, an event related to 'btn' to update the window...
window.show();
return app.exec();
}
PS : I know it's better to use the Qt Designer form, but I'm just asking about the possibility of doing this task.
Some events, e.g. mouse movement or focus changes, are not accessible through slots/signals.
You can use a small proxy QObject to filter events for other objects. See installEventFilter() for a code sample. You don't need to actually filter the events; you may just listen in and let them pass through.
Likewise, you can trigger/fake an event manually through QCoreApplication via notify().
As Joel Bodenmann notes, Qt uses signals and slots. You can have a slot on a QObject, but Qt can also connect to a lambda. Your lambda would have to capture window by reference, so it can update the window.
You'd probably want to connect the clicked event.
Qt offers the signal & slots mechanism. You can simply connect the QPushButton::clicked() signal to a slot that then performs the update you're referring to.
Using C++11's lambda:
// Create pushbutton
QPushButton* btn = nw QPushButton("Add",&window);
// Connect slot to 'clicked' signal
QObject::connect(btn, &QPushButton::clicked, []{
qDebug("Button clicked!");
// ... whatever else you want to happen on a button click
});
Keep in mind that you have other problems in your code as pointed out in the comments.

How to show dialog when main window became visible for the very first time in Qt widgets application?

I have Qt widgets application that has to authorize user with web service request before he can use the program. If user can not sign in for any reason, I have to exit the application.
.NET Framework implements Load event for that: when user sees window for the very firt time (the keyword here is "user sees"), it is possible to display dialog; if dialog result is not OK, we call close on main application window.
With Qt, we can override showEvent. However, it fires before user really can see main window. When I create dialog in showEvent, it appears without main window, and when I close main window in showEvent, it doesn't close (because it is not opened at the moment) and appears later event if user failed to sign in. It appears even after QApplication::quit() call.
My question is: is there a way to receive exactly the same functionality as in .NET Framework/Windows API and get event fired when user really sees window and not when he "may be sees something or will see soon"? It is possible to start timer from showEvent to get similar effect, but I think it is not professional, because you never know what may happend in user computer (may be its CPU works on 100% now), and you can not have real guarantee that timer will show dialog at correct moment.
I would try to create MainWindow and hide() it be default. The only widget to be shown at startup should be then the Login-Dialog. I would connect the successful login with the show() slot of the QMainWindow and the login failure - with the quit slot of the application.
I usually do something like this in my main.cpp:
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
LoginDialog dialog;
if(!dialog.exec()){
return 1;
}
MainWindow w;
w.show();
return a.exec();
}
that (of course) after having LoginDialog defined to inherit from QDialog and MainWindow defined to inherit from QMainWindow.
Create the main dialog at application startup, and only create the main window when the service responds positively.
You don't really need to dig deep in the event handlers.

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.

Event Handling in Qt

I am new to Qt GUI programming and come from a .NET/Winforms background as far as GUI development goes. I am using the Qt Creator IDE.
How can I handle a button press event in Qt to do something like the following:
if (button.clicked = true)
{
startProgram();
}
Also, how would I browse for a configuration file which would populate values into all of my line edit textboxes when opened? I am programming this in C++.
EDIT: I am taking a console app that someone else wrote and building a GUI around it. I want to access one of the functions in there from a button click event. However, I can't figure out how to get the functions of the original app to be in scope of the GUI which I have created when I try to use SIGNALS and SLOTS.
A simple example could be something like this. Say you have a class like ProgramStarter:
#include <QObject>
class ProgramStarter : public QObject {
Q_OBJECT
public slots:
void startProgram() {
//Do stuff
}
};
and something like this where ProgramStarter is used:
#include <QtGui/QApplication>
#include <QPushButton>
#include <QObject>
#include "programstarter.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QPushButton *testButton = new QPushButton("Push me");
testButton->resize(100, 40);
testButton->show();
ProgramStarter *program = new ProgramStarter;
QObject::connect(testButton, SIGNAL(clicked()), program, SLOT(startProgram()));
return app.exec();
}
Qt uses signals and slots to communicate between objects. The core idea is that signals are emitted when events occur and these signals can be connected to slots. In this case the button emits a clicked() signal when the button is pressed and the clicked() signal is connected to the startProgram() slot. So when the button is pressed, startProgram() is called.
Qt has a meta-object system for enabling the use of signals and slots, among other things. This is the reason why ProgramStarter inherits QObject and why the Q_OBJECT macro is in the header. I highly suggest reading this if you want to understand how signals and slots and the meta-object system work in Qt: http://doc.qt.io/qt-5/signalsandslots.html
It's a little long to explain but you connect the signal from the button to the slot with the function.
connect(button, SIGNAL(triggered()), this, SLOT(doSomething()));
You really need to read and understand signals and slots before trying to write code
edit: You are trying to call functions in a compiled separate running program?
Are you confusing Qt Signals with C/Unix signals? You could start the separate app from within your Qt app, get its PID and then send it a 'c' signal.
Or if you have the source of the app you could include it's code into your Qt app and then call any of the functions by simply wrapping them with a Qt slot handler.
In order to access the functions defined in the console application, you need to include the headers (.h/.hpp) that declare these functions, and link their implementation. I you have the source code of the implementations (.cpp), you need to add them to the sources to be compiled (they will be compiled in object files (.o) that will be linked in the final executable). If the console application is a front-end to a set of functions defined in a library (.lib, .a), you need to link this library.
After that, you can use Qt's signal/slot mechanism to connect the "button clicked" signal to a slot calling the function you want to execute, as described in other answers.
It seems like your problem is not really to do with Qt or GUI programming at all, but rather a general design issue. Others have told you how to be notified when the button is pressed - it's up to you to hook that notification up to whatever code you want to call. Some possibilities:
If you just need to call a function then include the appropriate header file and call it.
If you have an object you want to call a method on, then you will need to provide a reference to that object to the class which receives the notification.
If your console app is a separate program, you can use QProcess to launch and communicate with it.
I guess your problem is that you cannot call the console app's function, because it hasn't been defined to be a slot. So here is how you might do it.
Let's assume you have a console app class which might look like this:
class ConsoleApp
{
public:
void run()
{
// Code which you want to trigger by a button in your UI.
}
}
Then we implement a Qt based wrapper class which inherits from QObject class and, hence, is able to send and receive signals. This class simply provides a custom slot which delegates execution to the ConsoleApp class.
class ConsoleAppWrapper : public QObject
{
Q_OBJECT
public slots:
void startProgram()
{
m_consoleApp.run();
}
private:
ConsoleApp m_consoleApp;
}
Ok, and now we want a button which, when pressed, will trigger a call of the 'run()' method.
int main(int argc, const char** argv)
{
QApplication app(argc, argv);
// Define wrapper for console app.
ConsoleAppWrapper wrapper;
// Define button and connect its 'clicked()' signal
// to the wrapper's 'startProgram()' slot.
QPushButton startProgramButton("Start Program");
connect(&startProgramButton, SIGNAL(clicked()), &wrapper, SLOT(startProgram()));
// Show the button.
startProgramButton.setVisible(true);
// Start Qt's event loop.
app.exec();
}
This should give you a 'Start Program' button which, when pressed, will call ConsoleApp::run() method.
While this example is not Qt Designer based I hope this example helps you hunderstand how signals and slots work in Qt.
Cheers,
Jonny
If you have a button created with the Designer you can use on_myButton_clicked() slot in the parent widget class, just like in WinForms.