Calling a function with arguments when a QPushButton is clicked - c++

I want to call a function function(QPushButton button) when the user clicks a button.
I tried connect(myButton, SIGNAL(clicked()), this, SLOT(myFunction(myClass))); but it does not work. I could do a separate function for slot but i need to create connections dynamicly for buttons created by user.

You can get the button using sender() function. This function is used to get the senders in slots. Then you have to cast it to a class (in this case QPushButton) to be able to use it. If there is a need to pass another argument, please check out the answer of this question.

I found a solution to my problem. #Rinat Veliakhmedov told me to check that question, but QSignalMapper is deprected and does not work with custom objects. I searched for a replacement for this method and found that theard. Solution with emit myFunction(myClass) is perfect for my code.

Related

Why do I get "QMetaObject::connectSlotsByName: No matching signal" with a custom dialog?

I am using Qt5.
I have a very simple dialog class that inherits from QDialog.
I have a class that uses this dialog, and also a QFileDialog:
NameDlg m_name_dlg;
QFileDialog m_file_dlg;
This class also has some slots to handle dialog closing:
private slots:
void on_dlgName_accepted();
void on_FileDlgClosed(int result);
In the constructor I do some connecting:
QObject::connect(&m_file_dlg, SIGNAL(finished(int)),
this, SLOT(on_FileDlgClosed(int)));
QObject::connect(&m_name_dlg, SIGNAL(accepted()),
this, SLOT(on_dlgName_accepted()));
The first call to connect is fine, but the second call generates the output:
QMetaObject::connectSlotsByName: No matching signal for on_dlgName_accepted()
Curiously, my slot is correctly called when the name dialog is accepted!
The documentation (and header file) for QDialog says:
Signals
void accepted()
So it isn't a parameter mismatch.
As I said above, the signal is correctly called so my code all works fine, I just would really really like to understand why I get this warning (as an educational exercise) and also get rid of it (for peace of mind).
I cannot post full code, but I do believe there should be enough for anyone to understand the problem.
Things I have tried:
Using finished() instead.
Casting &m_name_dialog to a QDialog *.
Changing the signal to QDialog::accepted().
Thanks in advance.
In some part of your code you are using the method connectSlotsByName, if you have created a design (.ui) this usually calls it since compiling generates a file ui_somefile.h, and this file is used.
According to the docs:
void QMetaObject::connectSlotsByName(QObject *object)
Searches recursively for all child objects of the given object, and
connects matching signals from them to slots of object that follow the
following form:
void on_<object name>_<signal name>(<signal parameters>);
From the above it is observed that this method will try to connect the slots that have that format, and in your case the second slot fulfills it, when trying to connect it looks for the objects and signals but in your case it does not find it since the object does not exist dlgName and generates the warning you see.
This method is created by the .ui file because through the design you can create slots by right clicking on the widget and selecting go to slot, choosing the signal and finally creating the slot.
Note:
If you are going to create your own slot, avoid using the underscores as this could cause you problems because Qt would try to connect it and if the objects do not exist it will send you several warnings.

Can QSignalMapper forward function arguments?

How could I use QSignalMapper to map multiple check box?
The signal from check box I would use is stateChanged(int flag). During the process I want to keep this int flag and it will be finally send to my custom slot with other mapped variables.
How could I achieve this? I am using Qt4.
You cannot directly forward function arguments with a QSignalMapper. There are two ways to work around this.
Rewrite a custom version of QSignalMapper that takes the appropriate function arguments and forwards them.
Connect the check box signal directly to the slot you want and check the return value of sender() in the slot to see which check box emitted the signal.

Is it possible to get information on the control on which an event was issued in Qt?

I am trying to create one event handler for button clicks and connect that to multiple buttons (creating a simple calculator where pressing each number adds its text to the lineEdit).
In C# we would use the sender object which was passed as a parameter and then cast it back to Button and get its Text or other needed property and go on.
I am new to Qt, Do we have such a thing or a similar approach in Qt? Since I couldn't get it out of the signal/slot method of Qt.
On the QObject / QWidget that receives the signal, call this->sender() (QObject::sender()), and cast it with dynamic_cast<MyWidgetType*>(...)
You can find some good examples here for linking back to the issuer of an event.
http://doc.qt.digia.com/qq/qq10-signalmapper.html
They give you different examples for
The sender() Approach (like Jamin Grey's approach below)
The Subclass Approach
The Signal Mapper Approach

When will cellChanged signal be fired in QTableWidget?

I am using a QTableWidget to display and edit a data matrix. For validation purpose, I used the QLineEdit as items in this table. As following,
pTable=new QTableWidget(N,N,this);
pItem=new QLineEdit();
pItem->setText(tr("%1").arg(pInfra->adjacencyM(i,j)));
rx=new QRegExp("0|1");
validatorRegexp=new QRegExpValidator(*rx,0);
pItem->setValidator(validatorRegexp);
pTable->setCellWidget(i,j,pItem);
Since I want to know if data in certain cell has been changed, so I tried cellChanged(int, int) signal, and connect it with my own slot cellEdited(int,int), like this
connect(pTable,SIGNAL(cellChanged(int,int)),this, SLOT(cellEdited(int,int)));
But, when I edit QLineEdit in the cell, I can not catch this signal. When will this signal be fired? Or can I do this using another signal or in some other way?
Thanks!
The problem is that the cellChanged() signal is emittet only if the table model is issued the setData() method, which normally comes from the QLineEdit of the delegate. Since You have your own mechanism by setting the cell widget the setData() method of the model will never be called. Which means you'll have to connect to the textChanged() or the textEdited() signal of the QLineEdit object you put in the cells.
Another valid option is the approach mentioned by beduin in the comment.
Also possible: You could subclass the used delegate and make it create QLineEdit objects with your validator. Which would be the cleanest approach since you don't interfere with the model/view architecture and can rely on the signals the table object is sending.
Best regards
D
Not aware about causes of this problem. Considering another ways. You can catch QLineEdit signal textChanged and use QSignalMapper to bind signal, fired by each QLineEdit to particular cell number. Maybe itsn't the best qway to do that, but you can use it in case this problem won't be solved.

Callback for button in Qt Designer?

I just started using QtCreator tonight, and it seems it puts all of the interface stuff inside of the ui file. I followed a tutorial to create a resource for my icons, then I added them to a menu bar at the top.
I need to make a connection when one of them is clicked though, and cannot figure out how to make a callback for it.
Am I going to have to completely create them through code or is there some way to add a callback for them (rather than just making them interact with other objects).
Menu bar items are action objects. To do something when they are clicked, you need to catch the triggered() signal from the action. Read more about signals and slots here.
To do this, you need to declare a new slot in your MainWindow class. Qt also supports doing this automatically, without the need to connect anything, but I prefer doing it myself. If you're not interested, just skip this part.
First, we declare a new slot in your window class:
private slots:
void clickMenuButton();
Then, in your constructor, you need to connect the triggered signal to your new slot:
connect(ui.actionObject, SIGNAL(triggered()), this, SLOT(clickMenuButton()));
The first argument is the object that holds the signal we'll listen to (your menu button). The second is the name of the signal. The third is the object that holds the receiving slot (in this case, our window). The fourth is the slot.
And just like that, clickMenuButton() will be called whenever the action is clicked.
As I said before, Qt can also automatically connect signals to slots. The disadvantage here seems to be that you can't change the slot's name, but you don't need to connect it either.
Qt Creator supports creation of slots for widgets: in the case of your menu action, you should go to the form designer, and you should see a list of actions in your form (if you don't, find the Action Editor). Right click the action you want, and push Go to slot.... There, double click triggered().
Qt Creator will then open the new slot in your code editor, and you can do whatever you want to here!
To do that you'll need to add a QAction, add it to the menu, associate an icon with it and then create a callback for it. I'm using the VS Integration so I don't know the details of how to do it in Creator but it should be possible without creating stuff in code.
There should be somewhere an actions editor. from there you add an action, then right-click it or something to add an icon to it, then drag it do the menu and then possibly double click it to create a slot for it. This is how it works in the VS Integration atleast.