Refer to the Sender Object in Qt - c++

I'm having some trouble, I'm fairly new to Qt and C++ and was testing the waters so to say. Ill try to describe my problem as follows. I have a LineEdit QLineEdit and this edit has a connection which looks like this:
connect(my_lineedit, SIGNAL (textEdited(QString)),this, SLOT (handleEdits()));
The handleEdits() method gets called and does the following:
Disconnect the previous Signal from my_lineedit
Create a new QLineEdit which gets a new signal and calls handleAddedEdits()
Adds the newely created Edit to my layout.
The stated above works fine Im just telling you this so you get the picture.
Now in the new method which I called handleAddedEdits() I want kinda the same procedure to happen again.
Disconnect the Signal which calls handleAddedEdits() from the Edit which invoked this method in the first place.
Create a fresh QLineEdit
Add this to my layout.
The problem is: in the first case my_lineedit is declared in my class so I can freely refer to it and and remove the signal as I wish. In the second case I have a QLineEdit which was created dynamically in the handleEdits() method and is the "Sender". My Question is, how can I refer to the "Sender Object" ro remove the Signal from the dynamically created edit?

You need to use QObject::sender() method in your receiver's slot:
For cases where you may require information on the sender of the
signal, Qt provides the QObject::sender() function, which returns a
pointer to the object that sent the signal.
handleAddedEdits()
{
QObject* obj = sender();
disconnect( obj, SIGNAL(textEdited(QString)), 0, 0 );
//...
}

Related

HOw to reload the present UI details once is switch from different UI in QT C++

I have two forms one is trainee_view.ui
and other is enter_new_trainee.ui
so for that i have trainee_view.cpp,trainee_view.h to see the list of Trainee in DB
and enter_new_trainee.cpp,enter_new_trainee.h to enter new trainee details
now in trainee_view.ui i have a push button "ADD Trainee"
so if i click this button it will go to "enter_new_trainee.ui"
void trainee_view::on_pushButton_2_clicked()
{
newtrainee=new enter_new_trainee(this);
newtrainee->setWindowFlags(Qt::Window);
newtrainee->show();
// connect(newtrainee, SIGNAL(destroyed()), this, SLOT(refresh_form()));
}
so by using connect() i am trying to refresh the trainee_view after entering the new trainee details. so how can i emmit the signal from
2nd form to 1st form such that i call refresh_form() method in 1st form .
I tried to use destroyed() signal on newtrainee but could not refresh my trainee_view form.
To be MOre simple . i just want to get an object is destroyed or not so if destroyed i can call refresh() method to load back the changes done on widget
for that i opted connect() method so how should i call that. becoz if i call
connect(newtrainee, SIGNAL(destroyed()), this, SLOT(refresh_form()));
there is no effect i.e nothing is loading into the view.
am newbie to qt so pls try to help me.
Thank YOu.
I'm not sure if I correctly understand your app, but I think you misunderstand the concept of Signals and Slots. Look here for some examples. In some simplification you can look at signal and slots this way: connect() command is a place which will not do anything - it just stay and keep listening for a signal. So you should place it in trainee_view.cpp. That's the first part and I see you did it correct, or almost correct. But you need also something that will send the signal, and this is exactly what emit() command do - it should be placed in enter_new_trainee.cpp just after description of generation new entry. For example, let assume user input new entry in LineEdit in UI:
[...]
QString newEntry = ui->LineEdit->text(); //Save entry to variable
emit(newEntry); //Emit it to signal slot
[...]

How to tell when a QPushButton is clicked in a QButtonGroup

In my project, I have 40 QPushButtons all put into a QButtonGroup like this:
QButtonGroup* group = new QButtonGroup(this);
group->addButton(ui->slot_0);
group->addButton(ui->slot_1);
//...
group->addButton(ui->slot_38);
group->addButton(ui->slot_39);
Each button is a QPushButton that I made checkable. That way only one button can be checked at a time. All works great, but how can I "make a slot" when one of the buttons becomes checked? I don't want to have 40 different slots, one for each button all to end up doing essentially the same thing. Is there any way I can just use the QButtonGroup I put them in?
As Jamin and Nikos stated: you should create your own slot to handle the signal emitted by QButtonGroup. It could be something like this:
In the header file:
public slots:
void buttonWasClicked(int);
In the *.cpp file:
void MainWindow::buttonWasClicked(int buttonID)
{
cout << "You have clicked button: " << buttonID << endl;
}
And in the code responsible for creation of the MainWindow (i.e. in constructor but not necessairly) there should be this line:
connect(group, SIGNAL(buttonClicked(int)), this, SLOT(buttonWasClicked(int)));
Be aware that since Qt5 the connect syntax has changed. The syntax I used here is from Qt4. It still works but is deprecated now (for more information please refer to New Signal Slot Syntax in Qt 5). Moreover I would suggest going through QButtonGroup class reference as there are other available signals which could suit your needs better than the one I've chosen.
BR
The documentation for QButtonGroup shows a QButtonGroup::buttonClicked() signal - have you already tried that one?
The signal comes in two variants - one that gives the QPushButton as a parameter (as a QAbstractButton), and one that gives the ID of the button in the group.
You can use connect() to setup signal and slot connections in your C++ code.
Sometime during the initialization of your window's class (perhaps in the constructor), call this:
connect(myButtonGroup, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(theSlotThatYouWrite(QAbstractButton*));
Where myButtonGroup is probably this->ui->nameOfTheButtonGroup, and theSlotThatYouWrite is a function that you write in your own code, that belongs to your window's class, that returns void and takes a signal QAbstractButton* as a parameter (since that's what this specific signal gives as an argument).
Make sure theSlotThatYouWrite is under the label "private slots:" or "public slots:" in your class's interface.
Here's a screenshot of actual usage of some signals and slots in my own code.
Signals and Slots is something very important to learn, but can be bit of a hill to climb when first trying to understand it!

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...

Qt can I connect signals/slots to self in constructor?

EDIT: Not related to signals/slots/connect. Problem was constructor calling constructor.
There might be a better way to do this - I'd be interested in hearing those...
I have MyClass that is derived from a QLabel. I want to pass more data about the derived class back in the signal than what the base signal does. So I made a slot to intercept the customContextMenuRequested signal and emit a revised one that has more data.
When I try to connect up this signal in the constructor, then my slot never gets called. But if I move the Policy and connect lines out to the parent widget(not class hierarchy parent) so they execute after MyClass is fully constructed, then my slot will get called. But I always want that to be connected for this class and it seems like something I would want in it's constructor rather than counting on the parent class to remember to do it.
Is there something I'm doing wrong? Or a better way to add data to a signal?
MyClass::MyClass() : QLabel()
{
QFont currFont = font();
currFont.setPointSize(15);
setFont(currFont);
setBackgroundRole(QPalette::Mid);
std::cout << "connecting customContextMenuRequested" << std::endl;
/** PROBLEM START */
setContextMenuPolicy(Qt::CustomContextMenu);
// Is there anything wrong with connecting from "this" to "this" in a constructor?
QObject::connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(addCellDataToMenuContextRequest(const QPoint&)));
/* PROBLEM END **/
}
MyClass::MyClass(QString &cellString, int row, int col)
: QLabel(cellString)
{
MyClass();
setRow(row);
setCol(col);
}
// This one is a slot
void MyClass::addCellDataToMenuContextRequest(const QPoint& pos)
{
// This doesn't get printed if I connect in my constructor,
// but it does print if I do the same connect from a parent widget.
std::cout << "called addCellDataToMenuContextRequest" << std::endl;
emit customContextMenuRequestedForCell(pos, _row, _col);
}
So I would like the parent widget to just look for customContextMenuRequestedForCell but right now, the parent widget seems to need to be responsible for customContextMenuRequested as well.
Actually, you CAN call (sort of) another constructor if you are using C++11. It's called delegating constructor. But I don't think that will make the problem go away. Your issue seems to be that meta object is not fully constructed when connect() is called. Also, you'll probably need to move to Qt 5 for C++11 to work.
The solution is to delay the connection until the object is fully constructed. You can start a timer with an interval of zero. It will trigger on the next event loop processing which will certainly be after your object is fully constructed.
Then in your timerEvent, make the connection and kill the timer.
EDIT: Didn't see your edit. Looks like you find the solution. Ignore this then. :)
BTW. You didn't call another constructor. You created a temporary MyClass object.
A way to make this "cleaner" would be to reimplement QWidget::mouseReleaseEvent() within MyClass. The way to implement it would be, if the QMouseEvent type passed to mouseReleaseEvent is not a right-click mouse release, call QLabel::mouseReleaseEvent(event). If it is a right-click mouse release event, you can emit your custom signal. This gives the benefit of using the existing mouse button release handling code given by QLabel/QWidget, while allowing you to intercept the one case where you want to emit the custom signal.
EDIT Oh, and be sure to call event->accept() after your mouseReleaseEvent handles the custom case.

How to know which QLineEdit emitted the editingFinished() inside the signal handler?

I want to implement a custom response to user input for several similar QLineEdit objects. I want to create a common handler of editingFinished() or textChanged() signal and assign it to all the QLineEdits. However, the response requires the knowledge of the sender of the signal - for example, it must highlight the entered text with different colors.
How do I know the sender of the signal inside it's handler?
You can get pointer to sender with call to QObject::sender() and then cast this pointer to QLineEdit. Something like
void MyClass::onTextChanged(const QString& text)
{
QLineEdit* edit = qobject_cast<QLineEdit*>(sender());
if (edit)
{
// Do something with QLineEdit
}
else
{
// Just to make sure that you have not make mistake with connecting signals
}
}
May be you should consider using of QSignalMapper technique: http://doc.qt.io/qt-4.8/qsignalmapper.html