Function pointers in Qt
-
ahhhhh, man! this is veryyyyyyyyyyyyyyyy diasppointing. The class isn't Qt derived :D
but I think I'm starting to get the solution. but I need your help!
I'm reading a book called "Professional C++" by Solter and Kleper.
An example solution to my problem is the following (under Pointers to Methods):
@
SpreadsheetCell myCell;
double (SpreadsheetCell::*methodPtr) () const = &SpreadsheetCell::getValue;
cout << myCell.*methodPtr) () << endl;
@I'm trying to do like this code as follows:
@
double (Blochsim::*getConstantFieldDirPtr) () const = &Blochsim::getConstantFieldDirection();
@
but this line is giving me the following error:cannot call member function 'double Blochsim::getConstantFieldDirection()' without an object.
I tried to define and object from the class Blochsim (which I know doesn't make sense because it's in another line):
@
Blochsim bs;
double (Blochsim::*getConstantFieldDirPtr) () const = &Blochsim::getConstantFieldDirection();
@
but still gives the same error!any idea how to solve this??? :D I'm happy I'm getting close to the solution!!!
-
It would be:
@
(bs.*getConstantFieldDirPtr)();
@Example:
@
class TObj {
public:
double funcA() {
return 0;
}};
int main(int argc, char *argv[])
{
TObj tobj;double (TObj::*funcAPtr)() = &TObj::funcA; (tobj.*funcAPtr)();
}
@I've write some years an similar code on PalmOS.
-
But then again, you need the object where you call it. If I understood correctly, he does not want to have the object in present. otherwise, he would not need that.
I would go with "boost::bind":http://www.boost.org/doc/libs/1_46_1/libs/bind/bind.html#with_boost_function
-
So, I have a working example for your needs together with boost::bind and boost::function.
here we go:@
#include <QtGui/QWidget>
#include <boost/function.hpp>class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = 0);protected slots:
void changed1(int);
void changed2(int);private:
boost::function<void(int)> setValue1;
boost::function<void(int)> setValue2;
};
@I have a widget with two children, a slider and a spin box. The change of one of the triggers the slots. There I will (without using the class) change the value of the other object:
@
#include <QtGui/QSlider>
#include <QtGui/QSpinBox>
#include <QtGui/QVBoxLayout>
#include <boost/bind/bind.hpp>MyWidget::MyWidget(QWidget parent) :
QWidget(parent)
{
QSlider pSlider = new QSlider(Qt::Horizontal, this);
pSlider->setRange(0,100);
pSlider->setValue(20);
connect(pSlider, SIGNAL(valueChanged(int)), this, SLOT(changed1(int)));QSpinBox* pSpin = new QSpinBox(this); pSpin->setRange(0,100); pSpin->setValue(20); connect(pSpin, SIGNAL(valueChanged(int)), this, SLOT(changed2(int))); QVBoxLayout* pLayout = new QVBoxLayout(this); pLayout->addWidget(pSlider); pLayout->addWidget(pSpin); setLayout(pLayout); setFixedSize(sizeHint()); setValue1 = boost::bind(&QSlider::setValue, pSlider, _1); setValue2 = boost::bind(&QSpinBox::setValue, pSpin, _1);
}
void MyWidget::changed1(int value)
{
setValue2(value);
}void MyWidget::changed2(int value)
{
setValue1(value);
}
@the trick here is the usage of
- boost::function<void(int)> setValue1;
together with: - setValue1 = boost::bind(&QSlider::setValue, pSlider, _1);
The only disadvantage is: you need boost (at least partially...)
you need (at least on boost 1.44) all headers in boost, and the following folders in boost:
- bind
- config
- detail
- exception
- function
- function_types
- mpl
- preprocessor
- type_traits
- utility
- boost::function<void(int)> setValue1;
-
I have the object under the following hierarchy, which is in another window!
((MainWindow*)parentWidget())->openGLApp->blochsim->setConstantFieldDirection(double value)
I'll give it a shot and try!! thank you all!
do you see it a problem anyway calling the object like that? I have access to the object that way!!
-
it is the same logic:
@
boost::function<void(double)> setValue1;setValue1 = boost::bind(&CBlochism::setConstantFieldDirection, ((MainWindow*)parentWidget())->openGLApp->blochsim, _1);
@
make the boost::function the parameter, like here:
@
LinkedSliderDoubleSpinBox::LinkedSliderDoubleSpinBox(double minValue, double maxValue, long int bins,
boost::function<void(double)>,
boost::function<double()>, QWidget *parent) :
QWidget(parent)
{...}
@and call it like this;
@
boost::function<void(double)> setValue = boost::bind(&CBlochism::setConstantFieldDirection,
((MainWindow*)parentWidget())->openGLApp->blochsim, _1);
boost::function<double()> getValue = boost::bind(&CBlochism::getConstantFieldDirection,
((MainWindow*)parentWidget())->openGLApp->blochsim, _1);constantFieldDirChanger = new LinkedSliderDoubleSpinBox(minConstantDir, maxConstantDir, sliderLength, setValue, getValue, this);
@
EDIT: updated the examples, Gerolf
-
Thanks! I'll tell you what I get as soon as it's tested!
Unfortunately, I'll have to go get some sleep now because I'm traveling tomorrow early to Berlin... so I'll try everything I can in the train :D
Good night everyone, and thanks for the help!
see you tomorrow, with success hopefully :-)