dynamcly allocated buttons
Hi to all!
I've dynamically created buttons (the number of them is NOT known at compile time, but at runtime). It works ok, buttons are shown as I wanted. But now, I need to connect every button's signal clicked() to some slot function. How do I provide slot functions at runtime?? :confused:
Re: dynamcly allocated buttons
It look like I did it on my own. :D But it does not work. Is it allowed to setup slot from one object and then call slot from different object?
I got to gdb and i get following message:
Code:
warning: Object::connect: No such slot COperationWIndow::m_pMerchandizeBrowser->fillMerchandize(iIndex)
Why this does not work?
Re: dynamcly allocated buttons
Quote:
Originally Posted by
MarkoSan
How do I provide slot functions at runtime?? :confused:
I don't think you can add methods to classes at runtime in C++ :)
Quote:
Originally Posted by
MarkoSan
Is it allowed to setup slot from one object and then call slot from different object?
If you think about something like this:
Code:
connect(object1, SIGNAL(sig()), object2, SLOT(sl())); // "this" is neither object1 nor object2
then yes.
Re: dynamcly allocated buttons
Well, if I got it right, then:
Code:
m_MerchandizeSelectorButtons.at(iIndex)->connect(m_pButtonMerchandizeConfirmer,
SIGNAL(clicked()),
this. SLOT(m_pMerchandizeBrowser->fillMerchandize(iIndex)));
then second "this" is the name of "target" object?
Re: dynamcly allocated buttons
You can't put a statement into SLOT() macro like that. Take a look at QButtonGroup or QSignalMapper.
Re: dynamcly allocated buttons
QSIgnalMapper? I hate it, I've never understood it, I've read the docs about QSignalMapper but it is my humble opinion these docs are not written at the best ...
Re: dynamcly allocated buttons
Quote:
Originally Posted by
MarkoSan
QSIgnalMapper? I hate it, I've never understood it, I've read the docs about QSignalMapper but it is my humble opinion these docs are not written at the best ...
To be direct and honest, you should start with reading the article about signals and slots. It's the very basic principle of signals and slots that the SLOT() macro takes a slot name plus optional parameter types, without parameter names, and nothing more. Once you understand how signals and slots work, it should be straightforward to understand QSignalMapper docs. Besides, QButtonGroup should be even easier to use...
Re: dynamcly allocated buttons
Ok, but I simply must overcome this QSignalMapper since it is very useful. :rolleyes: I understand signal/slots feature, but this QSignalMapper is giving me headache. Now let me dig into it ... :D
Re: dynamcly allocated buttons
Does every button in a QList <QPushButton*> need its own QSIgnalMapper?
Re: dynamcly allocated buttons
Quote:
Originally Posted by
MarkoSan
Does every button in a QList <QPushButton*> need its own QSIgnalMapper?
No, you need only one signal mapper for the whole list.
In Qt docs you can find such example:
Code:
...
for (int i = 0; i < texts.size(); ++i) {
connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
signalMapper->setMapping(button, texts[i]);
...
}
connect(signalMapper,
SIGNAL(mapped
(const QString &)),
this,
SIGNAL(clicked
(const QString &)));
...
The setMapping() line tells the signal mapper that whenever the particular button invokes map(), the signal mapper should emit mapped(const QString &) signal with given parameter. So in this case you can replace all clicked() signals coming from different buttons with a single mapped( const QString & ) signal that comes from the signal mapper (of course parameter value depends on which button sent the original signal).
You can have a mapped() signal also with integer, QObject * or QWidget * parameter --- you just have to use the other setMapping() method variants instead.
In your case you can use QButtonGroup as jpn has suggested. Basically it's like a QSignalMapper but crafted especially for buttons.
Re: dynamcly allocated buttons
I would stick to QSignalMapper because I simply must overcome this topic. So, let me dig into it and try to reprogramm the example...
Well, I've done this:
Code:
m_MerchandizeSelectorButtons.at(iIndex)->connect(m_MerchandizeSelectorButtons.at(iIndex),
SIGNAL(clicked()),
m_pMerchandizeSelectorButtonSignalMapper,
SLOT(map()));
What should I now put into map() slot? Call to other's object slot?
Re: dynamcly allocated buttons
Do you know why you were suggested to use a signal mapper or do you just follow the advice blindly without trying to understand the problem first?
Re: dynamcly allocated buttons
I know why i was suggested to use signal mapper. That is because I cannot send a slot to other object, or am I wrong again??
Re: dynamcly allocated buttons
Quote:
Originally Posted by
MarkoSan
That is because I cannot send a slot to other object, or am I wrong again??
Yes, you are right - you are wrong again.
The signal mapper is used so that you can pass an integer argument to a slot connected to a signal that doesn't emit any arguments. If you just want to connect a signal to a slot, you don't need a signal mapper:
Code:
for(int i=0;i<10;i++){
connect(b, SIGNAL(clicked()), this, SLOT(fillMerchandize())); // see? no mapper
}
Compare your original code and this one. As you see fillMerchandize() doesn't take an int argument as you'd probably like it to. To get that index you have two solutions:
1. inside fillMerchandize() use QObject::sender() to compare the pointer of the object that sent the signal to each and every pointer stored in your list to determine the index of the list occupied by the button you want.
or
2. use a QSignalMapper as already advised (which basically does the same).
Note, that if you don't need the index (number) of the list but only a pointer to the button, you don't need the signal mapper - you can cast sender() to your button class and use the pointer. Just use a smart casting technique like qobject_cast.
Re: dynamcly allocated buttons
Guys, this is what I've done:
Code:
for(iIndex=0; iIndex<m_MerchandizeGroupsNames.size(); iIndex++)
{
// creates new button
//QString buttonText=m_MerchandizeGroupsNames.at(iIndex); // gets button text
Q_CHECK_PTR(pTempButton);
// adds button to list
m_MerchandizeSelectorButtons.append(pTempButton);
m_cPalette=m_MerchandizeSelectorButtons.at(iIndex)->palette(); // gets current pallete of button
m_cPalette.
setColor(QPalette::Button, Qt
::red);
// sets up new palette componenet m_cPalette.
setColor(QPalette::ButtonText, Qt
::black);
// sets up new palette componenet m_MerchandizeSelectorButtons.at(iIndex)->setPalette(m_cPalette); // sets new pallete
m_MerchandizeSelectorButtons.at(iIndex)->setFont(merchandizeButtonFont); // sets font
// connects buttons's slick to merchandize browser slot for filling pictures of selected group
/*
m_MerchandizeSelectorButtons.at(iIndex)->connect(m_pButtonMerchandizeConfirmer,
SIGNAL(clicked()),
m_pMerchandizeBrowser,
SLOT(m_pMerchandizeBrowser->fillMerchandize(iIndex)));
*/
m_MerchandizeSelectorButtons.at(iIndex)->connect(m_MerchandizeSelectorButtons.at(iIndex),
SIGNAL(clicked()),
m_pMerchandizeSelectorButtonSignalMapper,
SLOT(map()));
m_pMerchandizeSelectorButtonSignalMapper->setMapping(m_MerchandizeSelectorButtons.at(iIndex), iIndex);
// adds newly created button to layout
m_pMerchandizeSelectorButtonsLayout->addWidget(m_MerchandizeSelectorButtons.at(iIndex));
//delete pTempButton; // deletes temp button
}
/*
connect(m_pMerchandizeSelectorButtonSignalMapper, SIGNAL(mapped(qint16 iIndex)),
m_pMerchandizeBrowser, SIGNAL(clicked(qint16 iIndex)));
*/
connect(m_pMerchandizeSelectorButtonSignalMapper, SIGNAL(mapped(qint16 iIndex)),
this, SIGNAL(clicked(qint16 iIndex)));
I still get gdb warnings about there is not signalmapper::map slot. I might be stupid or something, but please help me!!
Re: dynamcly allocated buttons
Quote:
Originally Posted by
MarkoSan
Code:
connect(m_pMerchandizeSelectorButtonSignalMapper, SIGNAL(mapped(qint16 iIndex)),
this, SIGNAL(clicked(qint16 iIndex)));
Go take a look at QSignalMapper docs. Which signals does it offer? Does it offer a signal with qint16 parameter? Notice that qint16 is not same type as int.
Re: dynamcly allocated buttons
And we don't pass variable names in SIGNAL and SLOT signatures.
Re: dynamcly allocated buttons
I've finally rewritten the code as follows:
Code:
for(iIndex=0; iIndex<m_MerchandizeGroupsNames.size(); iIndex++)
{
// creates new button
//QString buttonText=m_MerchandizeGroupsNames.at(iIndex); // gets button text
Q_CHECK_PTR(pTempButton);
// adds button to list
m_MerchandizeSelectorButtons.append(pTempButton);
m_cPalette=m_MerchandizeSelectorButtons.at(iIndex)->palette(); // gets current pallete of button
m_cPalette.
setColor(QPalette::Button, Qt
::red);
// sets up new palette componenet m_cPalette.
setColor(QPalette::ButtonText, Qt
::black);
// sets up new palette componenet m_MerchandizeSelectorButtons.at(iIndex)->setPalette(m_cPalette); // sets new pallete
m_MerchandizeSelectorButtons.at(iIndex)->setFont(merchandizeButtonFont); // sets font
// connects buttons's slick to merchandize browser slot for filling pictures of selected group
/*
m_MerchandizeSelectorButtons.at(iIndex)->connect(m_MerchandizeSelectorButtons.at(iIndex),
SIGNAL(clicked()),
this,
SLOT(setGroup()));
m_pMerchandizeSelectorButtonSignalMapper->setMapping(m_MerchandizeSelectorButtons.at(iIndex), iIndex);
*/
connect(pTempButton, SIGNAL(clicked()),
m_pMerchandizeSelectorButtonSignalMapper, SLOT(map())); // connects button to signal mapper
m_pMerchandizeSelectorButtonSignalMapper->setMapping(pTempButton, (int)iIndex); // sets mapping
// adds newly created button to layout
m_pMerchandizeSelectorButtonsLayout->addWidget(m_MerchandizeSelectorButtons.at(iIndex));
//delete pTempButton; // deletes temp button
} // for
connect(m_pMerchandizeSelectorButtonSignalMapper, SIGNAL(mapped(const int&)),
this, SIGNAL(clicked(const int&))); // connects signal mapper to button
Now, how do I "catch" SIGNAL "clicked"? I've declared it in .h file with:
Code:
signals:
void clicked(const int &iIndex); // pushbutton slot
and If I try to write appropriate code for it in the .cpp file, I get following error:
Code:
Severity and Description Path Resource Location Creation Time Id
./debug\moc_COperationWIndow.o In function `ZN16COperationWIndow7clickedERKi': eROSystem line 0 1200210789421 2773
C:/Documents and Settings/markofr/workspace/eROSystem/debug/moc_COperationWIndow.cpp multiple definition of `COperationWIndow::clicked(int const&)' eROSystem line 85 1200210789421 2774
first defined here eROSystem COperationWIndow.cpp line 348 1200210789421 2775
make: *** [debug] Error 2 eROSystem line 0 1200210789421 2777
make[1]: *** [debug\eROSystem.exe] Error 1 eROSystem line 0 1200210789421 2776
Why??
Re: dynamcly allocated buttons
Quote:
Originally Posted by
MarkoSan
I've finally rewritten the code as follows:[code] {snip}
Why??
Because you can only implement the code for slots not signals :) Make "clicked(const int&))" this a slot rather than a signal.
Please make sure you know the basics of signals and slots first. :)
Re: dynamcly allocated buttons
I've read signal/slot mechanism, but I saw nowhere in the docs slot can take parameters, so it can or not???