Using on_<widget>_<signal> where widget it own class - c++

Is there a way to use the naming convention described in the title to connect a signal from your own class.
E.g:
class MyTree : public QTreeWidget
{
Q_OBJECT
private slots:
void on_this_itemClicked(QTreeWidgetItem* item, int column);
};
i understand i could use connect like this...
connect(this, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(myItemClicked(QTreeWidgetItem*, int)));
...but i was just curious as to if it works.

I am quite sure Qt auto connection use the objectName (QObject::setObjectName()), so there is no chance it can resolve this.

Related

Connect slots from another class not working in Qt

I have this class in button.h:
class Buttons : public QObject
{
Q_OBJECT
public:
Buttons();
QVector<QPushButton*> buttons;
public slots:
void getBtnInfo();
};
and in mainwindow.cpp, I connect like this:
Buttons mButtons;
for(int i = 0; i < mButtons.buttons.size(); i++) {
mButtons.buttons[i] = new QPushButton(mCentralWidget);
...
connect(mButtons.buttons[i], SIGNAL(clicked(bool)), &mButtons, SLOT(getBtnInfo()));
}
It runs without any errors; but the getBtnInfo() slot seems like not do anything. Because I tried simply just debug in this slot, not working.
But if I declare getBtnInfo() slot in mainwindow.h and connect like this:
connect(mButtons.buttons[i], SIGNAL(clicked(bool)), this, SLOT(getBtnInfo()));
then it works.
I wonder why? And how do I solve the problem above?
Thanks.
If a variable is created in a function it only exists in that function, then it will not be accessible, and that is what I think is happening, I recommend you to make mButtons a member of the class.
*.h
private:
Buttons mButtons;

Passing a QString to a class method of parent with QSignalMapper

I have a parent class with its method to change a labels picture on certain Signals. E.g. When something happens in a QComboBox... (valueChanged, activated)
class parentClass : public QMainWindow
{
Q_OBJECT
...
public slots:
//this is the slot i want to connect to some signal of
//e.g a combo box to change the picture by passed in string
void changePicture(QString fileName);
Then i have this child:
class childClass : public QObject
{
Q_OBJECT
public:
childClass(parentClass *parent, QTabWidget *tab, QStringList *guards=0);
private:
bool readCombo(QXmlStreamReader *xmlreader);
Now inside of readCombo i want to read a string and pass it to change picture:
QString imageFileName = xmlreader->attributes().value("image").toString();
QSignalMapper * signalMapper = new QSignalMapper(parent);
//this is just one of many trials to get this working, i hope you get the picture
connect(combo , SIGNAL(activated(int)), parent, SLOT(changePicture(QString *)));
signalMapper->setMapping(combo, imageFileName);
But this gives me either No such Signal , No such Slot or in the upper case Incompatiple sender/receiver arguments
I would appreciate some help on this one since the syntax is really not being intuitive (imo) and i can't find any good reference that is working for my case (did trial and error a lot before asking)
Some issues with your code.
you really can't connect to a private slot of a QObject
You are creating a new signal mapper every time you call readCombo which you aren't clearing - resulting memleaks.
calling connect multiple times creates multiple connections i.e., you will call the same slot multiple times with single signal.
From your example code, I see that you can solve this either by making the parentClass slot public OR add a signal to the childClass and connect to it in the parentClass.
Other option is change the readCombo like this:
QString imageFileName = xmlreader->attributes().value("image").toString();
parentClass->changePicture(imageFileName);
and your parent class as
class parentClass : public QMainWindow
{
Q_OBJECT
...
public slots:
//this is the slot i want to connect to some signal of
//e.g a combo box to change the picture by passed in string
void changePicture(QString fileName);
I see several errors:
You are connecting to a private slot in parentClass from childClass, you should make it public if you want to connect it.
You connect a signal to a slot with another function signature. Your signal has parameter type int, and slot type QString*. The functions should share the same type of parameters.
In your connect you refer use the parameter type QString* in your slot, but in parentClass the parameter type is QString.
For more information about signals and slots see: Signals & Slots.
PS: your naming of childClass and parentClass is not clear either since they both inherit from QObject. See C++ inheritance.
OK, got it:
QString imageFileName = xmlreader->attributes().value("image").toString();
QSignalMapper * signalMapper = new QSignalMapper(parent);
signalMapper->setMapping(combo, imageFileName);
connect(signalMapper, SIGNAL(mapped(QString)), parent, SLOT(changePicture(QString)));
connect( combo, SIGNAL(activated(int)), signalMapper, SLOT(map()) );

Create a custom slot in C++, Qt5

in python we write custom slots quite easily by passing in the function to be called when a signal is generated.
While in C++ connect function requires us to pass the address of the slot function or so i figured. How do i do that. I tried using this but did'nt work.
Python code::
class imviu(QtGui.QWidget):
def __init__(self):
super(imvui,self).__init__()
self.btn=QtGui.QPushButton('Browse')
btn.clicked.connect(self.openimg)
def openimg(self):
#do something
C++ code::
class imviu: public QWidget
{
public:
imviu(QWidget *parent=0);
QPushButton *btn=new QPushButton("Browse");
void openimg(void);
};
imviu::imviu(QWidget *parent)
:QWidget(parent)
{
connect(btn, SIGNAL(clicked()),this,SLOT(openimg()));//this does'nt work:QObject::connect: No such slot QWidget::openimg()
}
void imviu::openimg()
{
//do something
}
In order to use signals and slots, you need to have the Q_OBJECT macro in your class as well as identifying which functions should be the signals and the slots. Have a look at the documentation for a more in-depth explanation.
After this, you need to set up the project file so that MOC can generate the necessary code.
Your class definition should look like this:
class imviu: public QWidget
{
Q_OBJECT
public:
imviu(QWidget *parent=0);
public slots:
void openimg();
private:
QPushButton *btn;
};

How to deal with the SIGNAL(with arguments) of dynamically added QObject in QT?

I've found out that QSignalMapper can deal with the SIGNALs with NO Arguments, but how can I deal with some SIGNALs with it's arguments.
The actually problem is, I have created some QProgressBar dynamically, and i wanted to use QNetworkReply's downloadProgress(qint64, qint64) to update the bar, then the problem occurred.
The problem is that QNetworkReply's downloadProgress(qint64, qint64) and QProgressBar's slots are incompatable in any way. And signal mapper will not help you in this case, that is too specific.
You have to make you own adapter class:
class Adapter: public QObject
{
Q_OBJECT
public:
explicit Adapter(QProgressBar* bar, const QNetworkReply* reply):QObject(bar)
{
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(changeProgress(qint64,qint64)));
}
private slots:
void changeProgress(qint64 progress, qint64 total)
{
QProgressBar* bar = static_cast<QProgressBar*>(parent());
bar->setMaximum(total);
bar->setValue(progress);
}
};

Dynamic Creation in Qt of QSlider with associated QLCDNumber

I was wondering what's the best way to go about the following scenario?
I am dynamically creating QSliders that I wish to link to an associated QLCDNumber for display. The thing is I would like to have tenths available, so I would like to have a conversion between the QSLider and the QLCDNumber to divide by 10. At this point all I keep really is the QSlider, the QLCDNumbers I just create and forgot about. Is there an easy way of doing the conversion and connection without having to keep too much information?
Thanks in advance.
I'd try something along the following lines:
// create a new signal in your parent widget
signals:
void updateLCDNumber(double);
// and a slot which performs the conversion
private slots:
void performConversion(int value)
{
double convertedValue = value * 0.1;
emit(updateLCDNumber(convertedValue));
}
// then set the signals/slots up like this
connect(mySlider, SIGNAL(valueChanged(int)), this, SLOT(performConversion(int)));
connect(this, SIGNAL(updateLCDNumber(double)), myLCDNumber, SLOT(display(double)));
Afterwards you can completely "forget" about your LCD number, i.e. you don't need to keep a pointer or reference.
EDIT: A solution for several sliders:
class MySlider : public QSlider
{
Q_OBJECT
public:
MySlider(QWidget *parent=0) : QSlider(parent)
{
connect(this, SIGNAL(valueChanged(int)), this, SLOT(performConversion(int)));
}
signals:
void updateLCDNumber(double);
private slots:
void performConversion(int value)
{
double convertedValue = value * 0.1;
emit(updateLCDNumber(convertedValue));
}
};
Now create MySlider instances instead of QSlider ones and connect your QLCDNumbers:
connect(mySlider1, SIGNAL(updateLCDNumber(double)), myLCDNumber1, SLOT(display(double)));
connect(mySlider2, SIGNAL(updateLCDNumber(double)), myLCDNumber2, SLOT(display(double)));
...
This way you can also implement different conversion factors and the like, just modify the MySlider implementation.
I hope that helps.
This is basically what I ended up using; it seems to work (though it violates the whole object oriented philosophy).
signalMapper= new QSignalMapper(this);
QObject::connect(tmpSlider, SIGNAL(valueChanged(int)), signalMapper, SLOT(map()));
sliderMapper->setMapping(tmpSLider, tmpLCDNumber);
QObject::connect(signalMapper, SIGNAL(mapped(QWidget*)), this, SLOT(updateLCD(QWidget*)))
...
void MyClass::updateLCD(QWidget* lcdNum){
((QLCDNumber*)lcdNum)->display(((QSlider*)(signalMapper->mapping(lcdNum)))->value()*.1);
}