PDA

View Full Version : Calling a slot with arguments



drhex
1st May 2008, 14:32
I need a slot to be called with an argument after Qt has done its internal bussiness and started the event loop again. The two options I see are:



connect(this, SIGNAL(mysig(int)), someobject, SLOT(myslot(int)));
emit mysignal(arg);


but that won't work because it calls mysignal right now instead of waiting for other scheduled stuff.



QTimer::singleShot(0, someobject, SLOT(myslot()));

calls the slot at the proper time, but won't pass an argument. Anything put within the parentheses of myslot() is expected to be a type rather than a value.

I suppose I could use the singleShot method and pass the argument via a global variable but that feels like being back to C64 Basic where GOSUB didn't take arguments...

Is there a more elegant way?

Aceman2000
1st May 2008, 14:55
I think if you emit a signal it will be called after 'Qt does its internal business'.

On QTimer: connect it to a slot of your own, which in turn calls myslot, but now with parameters. (like: void myslot_caller(){myslot(42); /*or some variable*/})

Hope it helps.

drhex
1st May 2008, 15:14
I think if you emit a signal it will be called after 'Qt does its internal business'.

Not when I tried.. The "business" I'm talking about is drawing all the stuff that has been addWidget'ed since the main event loop was last run.

Your other solution still does not have method and arguments in a combined package, but at least can use a class member instead of a global. I'll settle for that.

Aceman2000
1st May 2008, 16:24
You can specify a fifth argument to connect, which is a Qt::ConnectionType. Try Qt::QueuedConnection or Qt::BlockingQueuedConnection.

drhex
1st May 2008, 18:09
The problem turned out to be worse than expected.
What I have is a QScrollArea with plenty of small widgets in it. The user did something that necessitated killing and rebuilding those widgets. That works, but the scrollbar's position gets reset to 0. Therefore I read its position before redrawing and intended to restore it afterwards from that slot.

Somehow, Qt was not finished drawing when the event loop started up again (i.e minimum() and maximum() of the QScrollBar are both zero). I had to call Qtimer::singleShot with a delay of 250ms to be allowed to move the scrollbar.

Of course, I did not want to be dependent on that arbitrary value so I had the slot call itself every 100ms until the scrollbar's maximum() was sane.

Aceman2000
1st May 2008, 19:01
Killing the widgets and rebuilding them seems a bad idea to me, isn't it possible to do this a gentler way?

drhex
1st May 2008, 21:22
Some of the widgets won't be there after the rebuild. I will probably change the code so that it kills only those and moves the others around to fill the holes.
But doing that is more error-prone (new one could have been inserted too) than calling the already working kill&rebuild method I had.
But rebuilding is slow, so I guess I'll have to implement the optimized version afterall.