i'm having an issue with the following signal-slot
QCheckBox *hasNotify = new QCheckBox;
connect(hasNotify, SIGNAL(stateChanged(int state)), this, SLOT(showhideNotify(int state)));
I get this in my application output
QObject::connect: No such signal QCheckBox::stateChanged(int state)
But here http://qt-project.org/doc/qt-5/qcheckbox.html#stateChanged they say this signal is included in QCheckBox, so I'm confused about what the problem is.
signal and slots parameters must not contain any variable names, so you should write
connect(hasNotify, SIGNAL(stateChanged(int)), this, SLOT(showhideNotify(int)));
Take a look at documentation here
Related
I have checked my code several times and i still can't get why it is not working.
I use a QComboBox connected to a slot in the class like this :
this->choixCam = new QComboBox;
this->choixCam->addItem("Camera 1");
this->choixCam->addItem("Camera 2");
this->choixCam->addItem("Camera 3");
this->choixCam->addItem("All cameras");
QObject::connect(this->choixCam, SIGNAL(currentIndexChanged(int)), this, SLOT(this->selectCam(int)));
This previous part of code is defined is the constructor of my class MainWindows, called in the main. The definition in the header file is the following :
public:
QComboBox* choixCam;
public slots:
void selectCam(int choixCam);
I tried with successfully to run the slot from another signal.
Using the signal with QString, the signal activated(int) or trying an exemple find on the net didn't work neither. Signals/slots mecanism also work for QButton and QSpinBox.
I am running out of idea. Some help would be very appreciate.
Thank you.
#eyllanesc answer should work. Just change SLOT(this->selectCam(int)) to SLOT(selectCam(int)).
But why isnt it the same for QT?
Lets have a look at the connect method:
QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal,const QObject *receiver, const char *method,
Qt::ConnectionType type)
(https://github.com/qt/qtbase/blob/e4c39d5e1e7ee8c2bba273e6d613ec519b7fa9c2/src/corelib/kernel/qobject.cpp#L2659)
and at the SIGNAl and SLOT definition:
#define SLOT(a) "1"#a
#define SIGNAL(a) "2"#a
QT uses c-strings to identify the signals and slots for qobjects.
These strings are used as keywords in some kind of dictionary over all qobjects, signals and slots.
Just try std::cout << SIGNAL(some text) << std::endl; to see what SIGNAL and SLOT do.
Thats why can call connect even without SIGNAL and SLOT:
connect(this->choixCam, "2currentIndexChanged(int)", this, "1selectCam(int)");
Now you know that
SLOT(this->selectCam(int)) will produce "1this->selectCam(int)" as keyword instead of "1selectCam(int)"
The SIGNAL and SLOT definitions are used because most IDEs disable C++ autocompletion inside quotation marks, which makes it hard to write the correct function signature.
I want to get a QTreeView widget to emit a clicked(const QModelIndex&) signal whenever a pushbutton is clicked. This is so that I can get a list of all the items that are selected within the QTreeView at the time of clicking the pushbutton. Now I thought I could connect two signals with distinct arguments (Qt Connect signals with different arguments), however when I try to call
connect(ui.pbAddVideo, SIGNAL(clicked()), ui.treeView_video, SIGNAL(clicked(const QModelIndex&)));
I get the error message:
QObject::connect: Incompatible sender/receiver arguments QPushButton::clicked() --> QTreeView::clicked(QModelIndex)
Have I misunderstood the whole signal forwarding concept?
As always, many thanks.
Firtsly, what index you must send by clicking a button from your tree?
Secondly, since c++11 standart you can do something like that:
connect(ui.pbAddVideo, &QPushButton::clicked, [=] { emit ui.treeView_video->clicked(ui.treeView_video->currentIndex()); });
I would solve your problem with the following approach:
First you have to handle the button click:
connect(ui.pbAddVideo, SIGNAL(clicked()), this, SLOT(onLoadVideo()));
In the slot you need to get the list of selected items from the tree view and do something with them:
void MyClass::onLoadVideo()
{
QItemSelectionModel *selectionModel = ui.treeView_video->selectionModel();
QModelIndexList selectedVideos = selectionModel->selectedIndexes();
foreach (QModelIndex *video, selectedVideos) {
// Play the video.
}
}
You are connecting one SIGNAL() to another SIGNAL() which is perfectly ok but their parameters should match. In your case the second signal has a parameter(i.e QModelIndex) that the first signal does not have.
Have I misunderstood the whole signal forwarding concept?
Yes.
When a signal is emitted, Qt takes the signal's arguments and passes them to the connected slot/signal.
Valid signal-slot connection
For example, suppose you connect the QSlider::valueChanged(int) signal to the QSpinBox::setValue(int) slot. When the valueChanged() signal is emitted, this is effectively how the slot gets called:
// "Emitting a signal" == "Calling the signal function"
QSlider::valueChanged(int sliderSignalValue)
{
QSpinBox *receiver = findReceiver();
receiver->setValue(sliderSignalValue);
}
Valid signal-signal connections
Similarly, if you connect the QSlider::valueChanged(int) signal to the QSpinBox::valueChanged(int) signal, the code behaves like this:
QSlider::valueChanged(int sliderSignalValue)
{
QSpinBox *receiver = findReceiver();
emit receiver->valueChanged(sliderSignalValue);
}
Now, if you want to connect in the opposite direction (connect(ui.treeView_video, SIGNAL(clicked(const QModelIndex&)), ui.pbAddVideo, SIGNAL(clicked()));, it's perfectly fine:
QTreeView::clicked(const QModelIndex& viewSignalValue)
{
QPushButton *receiver = findReceiver();
emit receiver->clicked(); // No problem. The viewSignalValue is simply ignored.
}
Invalid signal-slot connection
However, for the connection that you wanted to make, the code will need to behave like this:
QPushButton::clicked()
{
QTreeView *receiver = findReceiver();
emit receiver->clicked(/*???*/); // ERROR: You need to pass a QModelIndex value!
}
You've got a parameter mismatch. QTreeView::clicked() requires a QModelIndex value, but QPushButton::clicked() cannot provide this. Therefore, you cannot connect these two together.
Does this make sense?
Many thanks to #vahancho whose answer I have adopted. There is no point in using the "clicked()" signal from the qTreeView since I do not need to wait for this to access the data inside. Hence:
connect(ui.pbAddVideo, SIGNAL(clicked()), this, SLOT(addVideo()));
void VigilWidget::addVideo() {
QItemSelectionModel *selectionModel = ui.treeView_video->selectionModel();
QModelIndexList selectedVideos = selectionModel->selectedIndexes();
foreach (QModelIndex video, selectedVideos) {
qDebug().nospace() << video.data(0);
}
}
As to my question about how signal to signal connections work, thanks to everyone for taking the time to explain this :)
I want to send two integers, string and fret, to a SLOT that will process the location of the button that was pressed. The SIGNAL and SLOT argument have to match so I am thinking I need to reimplement the QPushButton::clicked event method. Problem is I am new to Qt and could use some direction.
connect(&fretBoardButton[string][fret], SIGNAL(clicked()), this, SLOT (testSlot()));
If you use the C++11 connection syntax you can use a lambda with calls testSlot with your string and fret arguments:
connect(&fretBoard[string][fret], &QPushButton::clicked, [this, string, fret]() {
testSlot(string, fret);
});
This code creates a lambda using the [captures, ...](arguments, ...) { code } syntax. When you make the connection it captures the string and fret variable values, and will then pass them on to testSlot when the button is clicked.
There are Two approaches you could use to add the string and fret information. one is to use the sender() function to get the button which emitted the signal. you can the access fret and string if they are members of your button class so in the SLOT you would have.
MyPushButton *button = (MyPushButton *)sender();
button.getFret();
button.getString();
However since you are already subClassing QPushButton you could use a private SLOT to catch the buttonClicked signal and re-emit a signal with the right values.
In the constructor
connect(this, SIGNAL(clicked()), this, SLOT(reemitClicked()));
and then the reemit SLOT
void MyPushButton::reemitClicked()
{
emit clicked(m_fret, m_string);
}
be sure to add the appropriate private slot and public signal to you class
https://doc.qt.io/archives/qq/qq10-signalmapper.html see this artical for a good discussion on various ways to add an argument to signal.
I've got a question about signals and slots. In my app, I want to connect a signal from one object to a textEdit in a dialog window. My signal emits a QString; if I violate encapsulation (by making the UI public instead of private) and connect the signal directly to the textEdit it works. But I feel that it's not the right way. If I make something like the following:
connect(m_osgWidget->picker.get(), SIGNAL(setX(QString)), m_addAgentDlg, SLOT(getX(QString)));
where:
void getX(QString)
{
this->ui.textEdit(QString);
}
It gives me an error that I can't use QString in this this->ui.textEdit(QString); I need the QString from setX() signal pasted into the textEdit of m_addAgentDlg. How this can be done? Where did I make a mistake?
I am sorry to say this, but you need to learn basic C++. The proper syntax is this for such things in C++ with Qt:
connect(m_osgWidget->picker.get(), SIGNAL(setX(const QString&)), m_addAgentDlg, SLOT(getX(const QString&)));
// Why do you call it getX? Should it be called setText instead?
void getX(const QString& string)
{
ui->textEdit->setText(string);
}
I have created a ToolButton with my qt designer and Im trying to connect it to a slot.
I wrote this
connect(ui->toolButton_addfiles, SIGNAL(triggered()), this, SLOT(changeDirectory()));
Im able to run the program but when I press the button I see the following log into my qt Application Output :
Object::connect: No such signal QToolButton::triggered() in ../RightDoneIt/rightdoneit.cpp:10
Object::connect: (sender name: 'toolButton_addfiles')
Object::connect: (receiver name: 'RightDoneIt')
If I change the toolButton_addfile to some action like (actionChange_addfile) it will work fine.
How can I make this connection work ?
As the error says, there's no signal triggered() but triggered(QAction*) in the QToolButton.
Edit
In the connect function you must have the signal signature like triggered(QAction*) since QToolButton class has no signal triggered() (with no parameter) declared
You could use the auto-connection process of Qt.
In the class referencing your UI, create a slot called :
on_toolButton_addfiles_clicked();
Exemple :
See : A Dialog With Auto-Connect
class ImageDialog : public QDialog, private Ui::ImageDialog
{
Q_OBJECT
public:
ImageDialog(QWidget *parent = 0);
private slots:
void on_okButton_clicked();
};
Hope this helps !
Edit : No triggered signals in qAbstractButton. See http://doc.qt.nokia.com/4.7/qabstractbutton.html
QToolButton() has the signal method triggered(QAction *), this signal is to be addressed if triggering of the related QAction connected to the QToolbutton is of interest. At the same time QToolButton is inherited from QAbstractButton(), which has the toggled(bool checked) signal. If you want to catch the signal triggered by pressing/unpressing the tool button, you may do as following:
auto toolbutton = new QToolButton(this);
connect(toolbutton , &QAbstractButton::toggled, this, []() { // your code });
Alternatively (I have not checked if this solution works), you may define explicitly, what signal to be caught
connect(toolbutton , qOverload<bool>(&QToolButton::toggled), this, [](bool val) { // your code});
I'm guessing you're creating a QAction, adding it to the QToolButton and trying to connect it to a slot in your own class?
You can connect your slot to either the QToolButton::triggered(QAction*) signal or directly to the QAction::triggered() signal. Either way, the QAction must be added to the QToolButton through QWidget::addAction(QAction*), the slot's method signature must match the signal's signature, and the connect invocation must include the signal/slot parameters, not just the names of the signal and slot.