QComboBox signal not trigged - c++

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.

Related

Qt custom QPushButton clicked signal

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.

QT Signal / Slot

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);
}

Menu action connection does not find slot

I am creating a QSystemTrayIcon traymenu. Its contextmenu has several actions which I need to identify.
public slots:
void s_showNote();
void Traymenu::createMainContextMenu(){
...
std::string noteTitle = m_noteList[i]->getTitle();
QString menuEntryName = QString::fromStdString(noteTitle);
QAction *openNote = m_mainContextMenu.addAction(menuEntryName);
QObject::connect(openNote,SIGNAL(triggered() ),this,SLOT(s_showNote()) );
QVariant noteID;
noteID.setValue(m_noteList[i]->getID());
openNote->setData(noteID);
The error is
QObject::connect: No such slot QSystemTrayIcon::s_showNote()
All of the code above is a part of my class definition that inherits from QSystemTrayIcon. How can I call the SLOT?
You seem to have at least two issues ongoing:
Use Q_OBJECT for QObject derived classes.
You will need to re-run qmake correspondingly.
As for the first point, please use C++11 and at least Qt 5.2 in the future because in cases like this, you will get a static compiler time error which comes handy for avoiding these tedious issues.

How do I get a signal to call a function with certain arguments?

I want to get a signal to call a function with certain arguments, like the example below.
QPushButton *yes = new QPushButton("Yes");
yes->connect(yes, SIGNAL(clicked()), NULL, SLOT(printf("You pressed a button")));
How do I accomplish this?
An often overlooked way to reverse signal/slot relationships is QObject::sender. You can call it in the receiving slot to get a handle on the QPushButton (using qobject_cast) and get the text from there. Alternatively you can use QSignalMapper to augment signals.
It seems very inefficient but you could create a new signal with a QString argument, which you connect to your pushbutton. The text contained will be defined on your emit call.
eg.
connect(yes, SIGNAL(clicked()), this, SLOT(emitHelloWorldText());
connect(this, SIGNAL(emitText(QString)), receiver, SLOT(dostuffWithText(QString)));
then your emitHelloWorldText method can be something like
void emitHelloWorldText() {
emit emitText("Hello world");
}
Then this can be picked up by your receiver class
void doStuffWithText(const QString &text) {
Unfortunately, the slot and the signal must have matching arguments. If you really need to stick with this interface, you could create an intermediary slot to propagate the received signal, but there’s no real way around.

How to use QMetaMethod with QObject::connect

I have two instances of QObject subclasses and two QMetaMethod instances of signal in one of objects and slot in another object. I want to connect this signal and slot with each other.
I've looked through the qobject.h file and find that SIGNAL() and SLOT() macro are just add "1" or "2" character to the beginning of method signature so it looks like it should be possible to add the same character to the beginning of string returned by QMetaMethod::signature() but this approach depends on some undocumented internals of toolkit and may be broken at any time by a new version of Qt.
Does anybody know reliable way to connect signals and slots through their QMetaMethod reflection representation?
Edited:
I've created suggestion in Qt issue tracker:
https://bugreports.qt.io/browse/QTBUG-10637
If anybody also interested in this feature you can vote for this ticket there.
This has been fixed as of Qt 4.8.0:
https://bugreports.qt.io/browse/QTBUG-10637
Suppose we have a QObject* m_subject, and wish to connect the change-notification signal of a property to a propertyChanged() slot:
const QMetaObject* meta = m_subject->metaObject();
QMetaProperty prop = meta->property(meta->indexOfProperty("myProperty"));
if (prop.hasNotifySignal()) {
QMetaMethod signal = prop.notifySignal();
QMetaMethod updateSlot = metaObject()->method(
metaObject()->indexOfSlot("propertyChanged()"));
connect(m_subject, signal, this, updateSlot);
}
I successfully used this to make a QWidget subclass which finds all the properties of any QObject and creates a QLineEdit for each of them, with a connection to keep the QLineEdit updated whenever the corresponding property changes. (Because I didn't find a way to pass a propertyID value to propertyChanged() though, it was necessary to make a subclass of QLineEdit and implement propertyChanged() there. QSignalMapper didn't help, because all the properties are in the same object.)
Thanks to MBack, I now use metamethods to connect my view to my model's properties dynamically for MVVM or MVC pattern.
In order to respect DRY, a boilerplate is required with something like this :
void MyClass::connectSignalToSlot(QObject* sender, std::string signalName, QObject* receiver, std::string slotName)
{
int sigIdx = sender->metaObject()->indexOfSignal(signalName.c_str());
auto signal = sender->metaObject()->method(sigIdx);
int slotIdx = receiver->metaObject()->indexOfSlot(slotName.c_str());
auto slot = receiver->metaObject()->method(slotIdx);
connect(sender,signal,receiver,slot);
}
void MyClass::connectPropertyChangedToSlot(QObject* sender, std::string propName, QObject* receiver, std::string slotName)
{
int sigIdx = sender->metaObject()->indexOfProperty(propName.c_str());
auto signal = sender->metaObject()->property(sigIdx ).notifySignal();
int slotIdx = receiver->metaObject()->indexOfSlot(slotName.c_str());
auto slot = receiver->metaObject()->method(slotIdx);
return connect(sender, signal, receiver, slot);
}
It looks like there is no way to make it work without relying on internal implementation. If I were you, I'd submit feature request to Qt bug tracker, write a code that mimics current behavior SIGNAL/SLOT macros and add unit test that will fail when SIGNAL/SLOT behavior changes.
There might be a simpler solution to the problem you're trying to solve: describe what exactly are you trying to do without any implementation details.
If signature method is public in QMetaMethod then the result shouldn't be broken by trolls and it's safe to use it (documentation says nothing about "dangers" when using QMetaMethod::signature method). I think you can safely use it. Just to be sure, what version of Qt you are using right now ?