connecting QGraphicsview signal to UI slot - c++

I am new to QT and C++ and i have legacy qt-c++ code here which i cant get to work.
Probably its something about the lifetime of the calling objects but hey, but please tell me what i am missing.
In a QT .ui i have various Frames and Widgets containing Frames and Widgets containing a QVBoxLayout which we shall call "myLayout"
On click in the .ui file i use
myWidget = new mywidget(some params);
myLayout->addWidget(myWidget);
where myWidget is declared as mywidget *myWidget; in the header file
myWidget is a QWidget which internally adds a QVBoxLayout to itself and adds a QGraphicsView. Using the MouseReleaseEvent i emit a signal from the QWidget.
now when i try to connect the signal slot (which i do in cpp file from the ui)
connect(myWidget, SIGNAL(mySignal(QString)), this, SLOT(mySlot(QString)));
the signals never catch the slot. the slot is public, the signal isnt.
What did i do wrong? Can somebody help. Feel free to ask further questions since i dont really know whats important in c++ questions;)
edit:
the signal gets emitted by QGraphicsObjects which themselfs connect to a slot in the QGraphicsView. This Slot is called and debuggable. at the end of the Routine an emit mySignal("..."); is called.

Maybe you forgot to add Q_OBJECT macro in your widget declaration. Qt documentation: http://doc.qt.io/qt-5/qobject.html#Q_OBJECT

Related

Access Qt UI of another Class from the MainWindow Class

I want to understand if the following sequence is possible? If yes, how can we achieve the same?
MainWindow Qt GUI has a QPushButton
While we click on the QPushButton, it must open another Qt GUI Window (a different class, say 'DialogClass')
In the newly opened Qt GUI Window we have a QLineEdit and QPushButton
While we enter data in the QLineEdit and click on the QPushButton (of the DialogClass) the MainWindow class should receive the data entered in QLineEdit
Any help on this item will be appreciated. Thanks in advance!
Qt foresees its signals and slots approach for such purposes.
The QPushButton of your class offers a signal clicked which you connect to a custom (self-written) slot of your dialog. The dialog's slot then should read the contents of the QLineEdit and publish these on the dialogs own (custom) signal, which is connected to a (custom) slot of your main window, which then can process the value originally contained in the line edit.
Details will resemble pretty much the example of Qt's signals and slots documentation, so I won't be more explicit about.

How to externally call a signal in Qt?

I know how to call a signal from inside the class where the signal is located: by using emit. But what if I want to call it externally, from the parent object?
The reason why I want to do is is because a given QPushButton is connected to a slot which picks the button that called it by using sender(). Now I want the same functionallity of that slot to be called but not after a manual click in the button, but from within the code itself. Normally I would just programatically call for the slot, but because of the usage of sender(), that way is invalid: calling the slot directly will not give it the id of the button.
So how could I "externally" ask for the object for it to emit one of its signals? That is, how can I make my QPushButton emit its clicked() signal from within the code, not by clicking the button with the mouse?
You cannot emit signal directly from the parent object.
Only the class that defines a signal and its subclasses can emit the signal. (http://qt-project.org/doc/qt-4.8/signalsandslots.html#signals)
You can define a method in your QPushButton emitClicked() where you emit the signal. Then you call emitClicked() on instance of your QPushButton from the code.
The Qt headers contain this interesting line (in qobjectdefs.h):
#define emit
Which means that presence or absence of the emit keyword has no effect on the code, it's only there to make it more obvious to the human reader that you are emitting a signal. That is to say:
emit clicked();
is exactly the same (as far as the C++ compiler is concerned) as
clicked();
Given that, if you want your button to emit its clicked() signal, it's just a matter of doing this:
myButton->clicked();
(although if you wanted to be clever about it, this would work equally well):
emit myButton->clicked();
Seems that Qt Test module is just for this case.
Check out this tutorial on simulating GUI events.
Basically you use QTest::​mouseClick and pass pointer to your push button.

Access QML signal deep in the hierarchy

I am trying to emit a signal on completion of creating an object. Like this:
Component.onCompleted: mySignal()
This is in a QML file deep in the hierarchy. I now see two solutions for accessing this signal in C++.
First is passing the signal up the hierarchy until main.qml and then in C++ do this:
//Create a Quick View object.
QQuickView *view = new QQuickView();
//Object to access QML properties and childs.
QObject *container = (QObject *) view->rootObject();
//Connect signal and slots
QObject::connect(container, SIGNAL(mySignal()), this, SLOT(onMySignal()));
This I have tried and for some reason the slot is not called. It works for all the other signals I send and emit from main.qml, but not the one emitted from Component.onComplete. I can verify that the signal is emitted from the QML side, but never received on the C++ side.
The second thing I tried was instead of passing the signal to main.qml, I would get a reference to the QML file emitting the signal I want. I tried that doing so:
//Create a Quick View object.
QQuickView *view = new QQuickView();
//Object to access QML properties and childs.
QObject *container = (QObject *) view->rootObject();
//Connect signal and slots
QObject::connect(container->findChild<QObject*>("mySignalQmlFile"), SIGNAL(mySignal()), this, SLOT(onMySignal()));
where mySignalQmlFile is the ID of the main rectangle that has the signals defined within it.
and I get the error:
QObject::connect: No such signal QQuickRectangle_QML_54::mySignal() in ..\GC\mainwindow.cpp:62
I am now not sure how to proceed.
For your first try, I think it is possible that your signal is emitted before you even connect your signal and slot so that it is never received the signal.
For your second try, you need to use objectName from your qml file, not "mySignalQmlFile".
I recommend you to read this following tutorial.
http://developer.nokia.com/community/wiki/Using_objectName_to_find_QML_elements_from_Qt
Also, your qml file needs to be called or used before you connect signals and slot. Otherwise, it will not be able to find the object so that you would get the same error.

QT/C++ yet another issue about accessing UI files

Although I have read the answers to this question
QT/C++ - Accessing MainWindow UI from a different class
and searched the whole www for quite some time - I don't get it working.
I was given the task to recreate an applications UI using QT Designer. Unfortunately there was already some UI spread all over several classes (the team then came across the idea, that using QT but not using the Designer however "handcoding" the UI seems to make little sense)
So now my job is to untangle the open ends, create a GUI (done that) find every possible signal and slot and put it all together to look nice and clean.
So much for the theoretical part.
Addition: I have very little experience in C++ and I seem to be getting nowhere searching for answers and don't have the time to read whole books until tomorrow, otherwise I wouldn't ask.
I am kind of going nuts about two things:
A) My mainwindow.cpp, mainwindow.h and mainwindow.ui need to be linked into other files e.g. the previewwidget.cpp...
the previewwidget.cpp had a lot of code like:
buttonLayout->addWidget(fpsSpinBox, 0, Qt::AlignCenter);
buttonLayout->addWidget(playButton, 0, Qt::AlignCenter);
buttonLayout->addWidget(backwardButton, 0, Qt::AlignCenter);
apparently I replaced it by creating the corresponding buttons in Designer.
now in the same file theres the connect SIGNAL SLOT entries (I added the "ui->")
connect(ui->playButton, SIGNAL(clicked()), this, SIGNAL(playButtonClicked()));
connect(ui->stopButton, SIGNAL(clicked()), this, SIGNAL(stopButtonClicked()));
connect(ui->forwardButton, SIGNAL(clicked()), this, SIGNAL(forwardButtonClicked()));
but the compiler keeps telling me:
\preview\previewwidget.cpp:77: Error:'ui' was not declared in this scope
I put the ui_mainwindow.h into the header but that wasn't the solution either.
B) This Question is probably related very closely to the first one: since the Designer strickly keeps model/view/controll apart I need to rewrite the signals and slots to match the new UI - has anyone got a good tutorial or any hints for me how to do this fast and uncomplicated?
Any help would be greatly appreciated.
Let's assume you have a class called MyWidget and a corresponding ui file MyWidget.ui. In order to use it in your class I would do the following:
In the MyWidget.ui set a value to the objectName. It's the first property in the Property Editor if you open the file with the Designer. I would name it MyWidget
In the MyWidget.h you have to do the following:
Declare a namespace for the ui object and forward declare it.
Add as member variable (private) a pointer to the ui object.
Sample header file follows:
#ifndef MY_WIDGET_H_
#define MY_WIDGET_H_
#include <QWidget>
namespace Ui {
class MyWidget;
}
class MyWidget : public QWidget {
Q_OBJECT
public:
MyWidget(QWidget* parent = NULL);
~MyWidget();
// Add other class functions
private:
Ui::MyWidget ui;
}
#endif // MY_WIDGET_H_
In the MyWidget.cpp
Include the automatically generated ui_MyWidget.h
Create a new ui object in the constructor
Call the setupUi function in the constructor
Delete the ui in the destructor
Sample code:
#include "MyWidget.h"
#include "ui_MyWidget.h"
MyWidget::MyWidget(QWidget *parent)
:QWidget(parent), ui(new Ui::MyWidget)
{
ui->setupUi(this);
}
MyWidget::~MyWidget()
{
delete ui;
}
Now you are ready to use the ui throughout your class. For example if you have a spin box called spinBox1 you can take its value using
int val = ui->spinBox1->value();
.ui Signals and Slots
I would advise you to use QtDesigner in order to make the connections between ui widgets and slots. Check this link for more details.
If you want to connect a widget with a custom slot you can again do it using the designer.
Switch to Edit Signals/Slots mode (F4)
Drag and drop from the widget which it to emit the signal, to the widget which is to receive the signal.
A Configure Connection dialog appears, showing the signals for the emitting widget, and the slots for the receiving widget. Click
Edit... below the slots column on the right.
A Signals/Slots of ReceivingWidget dialog appears. In here its is possible to click the plus icon beneath slots to add a new slot of
any name.
You can then go back and connect to your new slot in the Configure Connection dialog, or indeed in the Signal/Slot Editor
dockwidget back in the main window.

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.