PDA

View Full Version : Override setValue() of QScrollBar



RolandHughes
11th October 2014, 16:55
Qt 4.8.x on Linux

I'm in a situation of needing to override the setValue() method of a QScrollBar. The scrollbar is on a QTreeWidget. Yes, FlickCharm and several other things could be setting the position so, no, anything involving the mouse is out of the question. I think the real problem has to do with the Q_PROPERTY macro and the fact QAbstractSlider doesn't declare the slot virtual.

Why override the setValue() slot? Simple. Many points can change that value. The valueChanged() signal is only emitted when setValue() is called with a DIFFERENT value than currently stored. I need value changed to emit no matter what. Why? Because if you are bumping into one end or the other of the tree we want to provide feedback to the user.

Perhaps I just need more caffeine, but having trouble.

First attempt was the least amount of code I could think of.

Class declaration

class ValueScrollBar : public QScrollBar
{
Q_OBJECT
public:
explicit ValueScrollBar(QWidget *parent = 0);
explicit ValueScrollBar( Qt::Orientation orientation, QWidget *parent = 0);

public slots:
void setValue(int _value);
};

slot source
void ValueScrollBar::setValue(int _value)
{
if (_value == value())
emit valueChanged( _value);
else
QScrollBar::setValue( _value);
}



I can create one of these. Assign it as the vertical scrollbar for the tree widget. Add data to the tree, then deliberately call tree->verticalScrollBar()->setValue( 5) and never hit a break point in the slot source.

Has anybody ever overridden the setValue() method for a scrollbar? Please tell me how you did it. I truly hope I don't have to roll my own scrollbar because of something short-sighted in QAbstractSlider.

Thanks

Added after 29 minutes:

I just confirmed it. Very short sighted design on part of QAbstractSlider. None of the slots are virtual. When something uses, say, QTreeWidget->verticalScrollBar()->setValue() it is _always_ going to take the base implementation.
(*%^*&^%(*&)(*&U)(*&(*&^*&^%*&^%

anda_skoa
11th October 2014, 19:07
Property change signals, as their name suggests, are only emitted on change of the property.
This is to ensure that connections do not end up creating endless loops.

The setters of most properties are therefore not virtual to ensure that a subclass does not accidentally breach that behavioral contract.

You can of course violate that on any custom property, though it is obviously not very wise.

Cheers,
_