I am doing a software with a drawing surface that represent a plot (like a sin function) (A child of QWidget) and I would like to have a QScrollBar acting like a QScrollArea. So if my drawing widget show show 750 dots (my plot is made of dots), but there are 1000 dots, I would like the slider of the ScrollBar to fill 75% of the available space.
I can't use a QScrollArea because the scroll is proportionnal with the size of the widget it contains. In my case, the scroll must be proportionnal with the number of dots on the screen. I know how to get my ratio, but I don't know how to setup correctly the QScrollBar
Example: I edited the value of PageStep, but I don't understand how this work. I can set pageStep to 100 with a range of [0,99] and it will fill the half of the QScrollBar.
My interface:
QWidget (Vertical Layout) //Main Widget
Drawing Surface (Child of QWidget)
QScrollBar (Horizontal)
Well, I think I am able to do something with this:
http://harmattan-dev.nokia.com/docs/library/html/qt4/qscrollbar.html
The relationship between a document length, the range of values used in a scroll bar, and the page step is simple in many common situations. The scroll bar's range of values is determined by subtracting a chosen page step from some value representing the length of the document. In such cases, the following equation is useful: document length = maximum() - minimum() + pageStep().
So in my case the length is the number of dots and I can set minimum() to 0. So, as you can see on the picture, to do something like QScrollArea. The proportion is: PercentageVisible = PageStep / Length and another equation is Length = PageStep + Max.
I have two equations, two missing values (PageStep and Maximum) and two known values (PercentageVisible and Length).
Example: I have 1024 dots, but only 75% of them are shown.
0.75 = PageStep / 1024 ----------> PageStep = 768
1024 = Max + 768 ----------------> Max = 256
You can try it in your software and it will works. I know there's not so much people that will needs to reproduce this because QScrollArea will do the job in most of the case.
By example, this code is in a slot reacting from a resize event:
ui.sbarRange->setPageStep(u64SampleCount * dRatio);
ui.sbarRange->setMaximum(u64SampleCount - ui.sbarRange->pageStep());
You can create a new QWidget subclass and reimplement sizeHint
and paintEvent
. In the paintEvent
you can use event->rect()
to determine which area is currently exposed and needs to be drawn. Note that paintEvent
must be fast if you don't want your window to freeze. Also you need to put created widget in QScrollArea
.
Here is a simple example that draws a sinusoid:
class SinWidget : public QWidget {
public:
QSize sizeHint() const {
return QSize(10000, 200);
}
void paintEvent(QPaintEvent* event) {
QPainter painter(this);
for(int x = event->rect().left(); x <= event->rect().right(); x++) {
painter.drawPoint(x, 100.0 + qSin(0.05 * x) * 20.0);
}
}
};
QScrollArea area;
area.setWidget(new SinWidget());
area.show();
This example will work fine with very large widget size (e.g. 100 000 pixels). So full repaint or memory allocation doesn't happen. You only need to keep your paintEvent
fast.