Transfer Data Between Two Children Using Qt Signals and Slots (C++) - c++

In Qt C++, I have a parent object MainWindow. MainWindow has (among others) 2 member objects: vector, and Serial.
Some relevant members of GUI:
QPushButton pushButton;
int itemNumber;
Relevant members of Serial:
void send(int number)
When GUI's member pushButton is clicked, I want to pass GUI's member 'pushButton' as the argument to the function Serial::send(int number). I see one option of doing something like
connect(GUI,SIGNAL(clicked()),this,SLOT(customSlot()));
in my MainWindow function. However, then I don't know which item in my vector it came from, so I don't know which itemNumber to grab (they're all different).
I also thought maybe I'd do it in the GUI class, but that doesn't have access to the Serial::send(int number) method. I don't want a Serial object in each GUI, because it just won't work that way at this point.
How can I pass information from the child object GUI up to the parent object MainWindow from a signal?
Thanks!

Use QObject::sender() function inside a slot to get the object witch sent a signal.
Of course, you need some appropriate cast method:
void someSlot() {
QPushButton *sender = qobject_cast<QPushButton *>(sender());
...
}

Related

Senders objectName is absent | QT & Cpp

I have created a little UI with a simple toolbar. I am initing the toolbar within the initToolbarfunction. This function is within a Class inheriting from QMainWindow.
void Main_Frame::initToolBar() {
rectangle.setText(rectangle_text);
circle.setText(circle_text);
triangle.setText(triangle_text);
triangle.setObjectName(triangle_id);
circle.setObjectName(circle_id);
rectangle.setObjectName(rectangle_id);
toolBar.addAction(&triangle);
toolBar.addAction(&circle);
toolBar.addAction(&rectangle);
connect(
&toolBar, &QToolBar::actionTriggered, this, [=]() {
process_toolbar_ac_evt(*sender());
});
}
I want any tool bar events to be processed through process_toolbar_ac_ect(QObject obj). Within that method, I want to decide what action (within the toolbar) has been triggered.I want to do this by the objectname. Therefore I have given any action an object name. But when I call sender().objectName() I get an empty QString.
My suggestion is, that sender returns a pointer to on of my actions that I put to the toolbar. If this is the case, why I get an empty QString on the sender()?
void Main_Frame::process_toolbar_ac_evt(QObject &evt) {
if (evt.objectName() == circle_id) {
// If circle action has clicked, to this ...
}
}
As you are connecting to one of QToolBar's signals the sender() will be your tool bar object.
Simply use the QAction argument that is passed in the QToolBar::actionTriggered signal. That's what it is for.
NB: Avoid QObject::sender() wherever possible. It virtually breaks the desired decoupling achieved by signals and slots.

Can't access a control in a widget from another widget in Qt

I have this widget in Qt:
"connecttoserver.h"
"connecttoserver.cpp"
"connecttoserver.ui"
and this one:
"mainwindow.h"
"mainwindow.cpp"
"mainwindow.ui"
How can I access the "connectToserver" elements from the "mainwindow" widget?
I've tried doing this:
void MainWindow::on_btnLogin_clicked()
{
connectToserver ccc;
ccc.ui.txt_mail_ip.text();
}
But it doesn't work.
It's C++: to access one widget member from another widget, just create a method (or a Qt slot, if you prefer) and invoke it from the other widget. For being accessible, the method (or the slot) mut be public, or otherwise the two classes must be friend.

How can I catch the change of a child Widget in Qt?

I have some dynamically added QWidgets and I want to carry out some task when they are changed.
I think I can't use connect() because I also need the name of the QWidget that triggered the change.
How can I also see which QWidget was changed and still catch the value change event with a common handler?
The quick-and-dirty way is to use connect() as usual, and then in your slot method, call sender() to find out which object sent the signal. For example:
// slot method that you've connected all of your widgets' stateChanged(int) signals to
void MyClass :: someWidgetsStateChanged(int newState)
{
const QObject * s = sender();
if (dynamic_cast<const QCheckBox *>(s) == _myFirstCheckbox) printf("First checkbox is now %s\n", newState?"Checked":"unchecked");
else if (dynamic_cast<const QCheckBox *>(s) == _mySecondCheckbox) printf("Second checkbox is now %s\n", newState?"Checked":"unchecked");
[... and so on...]
}
Note that the reason this is considered "dirty" is that it breaks encapsulation. In particular, the someWidgetsStateChanged() method above now behaves differently depending on which object generated the signal, and so if e.g. at some point in the future you connected a QPushButton::clicked() (or whatever) to that same slot, you'd probably have to update the someWidgetsStateChanged() implementation to handle it appropriately. Still, this works and doesn't require a lot of effort to implement.
Use this to catch events before they are passed to QObject subclass instances:
http://qt-project.org/doc/qt-4.8/qobject.html#installEventFilter
After some additional thinking I arrived at saying why not to extend these controllers?
So that I could hook them to the parent object using parent() or using a custom constructor.
It requires potentially though that I define them as friend classes...

Qt4: The best way to access parent class (1 level up, 2 levels up .... )

I'm wondering how to access parent class in my Qt application.
Lets say my project has following structure:
mainWindow: MainWindow
tabWidget: QTabWidget
tab1: MySubClass1
tab2: MySubClass2
tabWidget: QTabWidget
xtab1: MySubSubClass1
xtab2: MySubSubClass2
It is a little simplified.
What I want to do is to access mainWindows object from one of xtab2 slot functions.
(1) What would be the best method ?
I tried to pass the pointer to mainWindow along the tree but I get runtime errors.
(2) Should I include mainwindow.h in xtab.h file or should I do it in xtab.cpp file ?
Thanks for help :)
If you really need the mainwindow, passing the MainWindow pointer is the best way to do it. A static method has the drawback that it will stop working with more than one mainwindow.
I would suggest to avoid accessing the mainwindow from the contained widgets though and use signals instead. E.g.:
class MainWindow {
public:
explicit MainWindow( QWidget* parent=0 ) {
tab = new TabWidget;
...
MySubSubClass1* ssw1 = new MySubSubClass;
connect( ssw1, SIGNAL(textChanged(QString)), this, SLOT(page1TextChanged(QString));
tab->addWidget( ssw1 );
}
private Q_SLOTS:
void page1TextChanged( const QString& ) {
//do something...
}
};
MySubSubClass1 then emits textChanged(), addresseeChanged() (e.g. in Addressbook), or whatever level of abstraction or detail makes sense on the higher level. That way MySubSubClass is generic and doesn't have to know about MainWindow at all. It can be reused in any other context. If MySubSubClass itself contains other widgets, it can again connect to their signals.
You could create a static method and object inside MainWindow that would return mainwindow object.
Something like this:
private:
static MainWindow* _windowInstance
public:
static MainWindow* windowInstance()
{
return _windowInstance;
}
This seems to be the simples solution in most cases. Now you just have to include mainwindow.h whenever you need to access this object.
And don't forget to initialize _windowInstance in the contructor, like this;
_windowInstance = this;
By parent class, I assume you mean parent widget?
If you want to find the top level widget, QWidget::window() will point you to it. Use dynamic_cast or qobject_cast to turn it into your MainWindow object.
If you want to go up some arbitrary level, use paerntWidget().
There are a variety of different solutions to this problem, the one you chose as the answer is in terms of object orientation and encapsulation one of the worse ones. Some thoughts
Encapsulation: if you find yourself having to provide access accross a large distance in relation (down a long chain of containers or subclasses) you might want to look at the functionality that you are trying to distribute. I might be that it should be encapsulated in a class by itself that can passed around easier than where it is currently located (the main window in your case).
Abstraction: Unless it is actually functionality of QMainWindow that you need to access don't pass a pointer to your MainWindow class, create an interface for the functionality that you need, have your MainWindow implement that interface and pass around and object of the interface type instead of your MainWindow type.
Signals and Slots: As Frank noted, implement the appropriate functionality using Qt's signalling mechanism, this makes the connection between the caller and callee into a dynamic one, again separating it from the actual MainWindow class
QApplication: If you absolutely have to have global information restrict the entry point, you already have one singleton the QApplication object, make it the maintainer of all the other objects that need to be globally accessible, derive your own QApplication class and maintain global references in there. Your QApplication class can then create or destroy the needed global objects.
With more information about what you need to do with the MainWindow instance or what needs to be communicated you will also get better answers
QWidget* parent = this ;
while (parent -> parentWidget()) parent = parent -> parentWidget() ;

qt GUI connecting

I am just starting out with QT. I have read through some tutorials, and I think I have an understanding of signals and slots. I am writing a GUI that has various buttons that change the state of my main program. So for example in a drawing app, you would pick different drawing tools (using various buttons).
What is the best way to go about this? My first thought was to try to connect the clicked signal of the PushButton to some function that sets a current_tool variable. I did some searching and couldn't find a way to connect a QObject signal to a regular function.
This leads me to believe that there is probably a different approach. One where I create a new QObject (my own extension that is) that has various GUI properties. I would then define my slots here for the various buttons.
What is the best way to do this in QT. I am new and do not know of the preferred practice.
Any info would be useful,
thanks
You can define these "normal functions" as slots. Slots are just normal functions that can also be called by signals:
class ToolSelector : public QObject {
Q_OBJECT
public:
Tool *selected;
public slots:
void selectBrush();
void selectPen();
void selectFill();
};
ToolSelector::selectBrush() {
delete selected;
selected = new Brush();
}
ToolSelector::selectPen() {
// ...
}
// ...
toolsel = new ToolSelector();
brushButton = new QPushButton();
connect(brushButton, SIGNAL(clicked()), toolsel, SLOT(selectBrush()));
Inherit from the class that uic generates, creating, say, a MyAppWindow class. Provide extra METHODs in that class, as well as a Document or Drawing object. Connect these methods to the signals you're interested in, and them alter a member variable that contains the drawing state.