How to get the length of the left/right offsets in a QSlider? - qt

I'm trying to make a subclass of QSlider that allows the user to insert "bookmarks" so they can remember significant locations on the slider. I've run into a problem painting the tabs on the slider - using QStyle.sliderPositionFromValue, I get a value but it is slightly inaccurate. If I'm on the left side of the slider, the tab is painted too far left, and on the right side it is painted too far right. I believe this is because QSlider.width() returns the width of the whole object, including the small offsets at the left and right. So width() might return 630 pixels, when the length of the slider itself is really 615.
This is the code I'm using to get the pixel position and draw a line across the slider.
pos = QStyle.sliderPositionFromValue(self.minimum(),self.maximum(),sliderIndex,self.width())
painter.drawLine(pos,0,pos,self.height())
I've been looking at the QT Source here starting on line 2699 and it seems like I need to be using the PixelMetric class from QStyle. I've tried using:
self.style().pixelMetric(QStyle.PM_SliderSpaceAvailable)
But that returns 0, which is clearly not the value I need.
I'd appreciate any advice.
Edit: As suggested in the comments, I changed the call to:
self.style().pixelMetric(QStyle.PM_SliderSpaceAvailable, QStyleOption(1,QStyleOption.SO_Slider),self)
This however, returns -14, which also doesn't match for the value of the offsets (I tried using self.width()-14 but the offset remains.

Related

How to get the negative position value in Group?

The dashed rectangle is the parent group and inside, there is a label. Its x is negative.
Now, what I want to do is relocation the outside group to the contents' top-left point and meanwhile the contents' move back to the outside group's (0,0) point. The result looks like everything keeps the same position as before.but in fact, both inside content and outside group is moved.
It is easy to realize in flash, however, in flex i got trouble.
The function "getRect" returns wrong values.it's never return the correct position the inside content is.(like the thumb shows,the position should be like [-70,50])
(Feel free to correct me because I'm not sure what you want to accomplish here)
If your Label (let's say it is called myLabel) is correctly located directly inside of your Group, simply calling myLabel.x will return the X-coordinate of the label compared to its parent (which is your Group here, so you should get -70).
Then if you want to move the label so it fits into your Group viewport, you have two solutions:
Either you manually set myLabel.x = 0 and myLabel.y = 0. In this case the label will actually be moved at the Group origin.
Either you retrieve the matrix of your label component to call its .translate(dx, dy) function. Using the matrix functions will modify the way your Label is displayed, but its position will remain unchanged (More information about that on this page).
Short answer: If you don't care about keeping the original position of your label, just set myLabel.x = 0 and myLabel.y = 0 and it should be moved correctly.

qscrollbar (not a qscrollarea) setValue not working

I am working on a qwtPlot and have implemented custom scrollbars to illustrate the position of things on the plot when zooming in (in regards to the whole thing - so basically the percentage).
Now, everything works fine, apart from the moment, when I do any zooming or panning right at the beginning (or simply when I see the whole plot and then I want to zoom in).
This is a slot I am using to refresh the appearance of the scrollbar:
void ScrollHorizontal::refreshAfterChanges() {
setValue(myPlot->getLowerBound(QwtPlot::xBottom));
setPageStep(myPlot->get_X_delta());
setSingleStep(myPlot->get_X_delta()/10);
setMaximum(myPlot->dataFromSources->lastTimeValMicro()-pageStep());
update();
printV("HorizontalScroll::setValue",myPlot->getLowerBound(QwtPlot::xBottom));
printV("value", value());
printV("pageStep", pageStep());
in the constructor I set the maximum to 0 (just in case, but it doesn't change anything)
The last 3 lines print out some values useful for debugging. What I found out thanks to them is that the slot is executed correctly, but the setValue(int) function doesn't work as I would expect it to:
//printed values right after starting the program
HorizontalScroll::setValue=0
value=0
pageStep=7320
//printed values after using the zoomer once
HorizontalScroll::setValue=956.316
value=0
pageStep=2225
Then, when I move the plot a tiny bit, e.g. zoom it 1.1 times, the setValue works properly and value() return the same thing I set. But if I go to the 100% view (the starting point) I get the same problems again.
Just to illustrate it, here are some screenshots:
http://tinypic.com/view.php?pic=2znph7s&s=8#.UvNkDoZhauY
(100% view, right before zooming in)
http://tinypic.com/view.php?pic=ke7nn9&s=8#.UvNkYIZhauY
(badly set qscrollbar)
Ok - problem was caused by the line
setMaximum(myPlot->dataFromSources->lastTimeValMicro()-pageStep());
It was setting the maximum to 0 sometimes. why? I wanted the slider to take up the whole length of the scrollbar so that at the beginning when the plot was shown in 100% view, you couldn't scroll it and I could achieve that by setting the pagestep to my plot's maximum value and the maximum to 0.
But that caused the setValue(int)problem - you can't set a value bigger than the maximum.
So what finally worked for me is:
double valueToSet=myPlot->getLowerBound(QwtPlot::xBottom);
if(valueToSet>maximum())
setMaximum(valueToSet);
setValue(myPlot->getLowerBound(QwtPlot::xBottom));
setPageStep(myPlot->get_X_delta());
setSingleStep(myPlot->get_X_delta()/10);
setMaximum(myPlot->dataFromSources->lastTimeValMicro()-pageStep());
update();

Antialiasing in Qt's QGraphicsScene make overlapping lines darker

When using anti-aliasing rendering in Qt's QGraphicsScene, there is a behavior that makes drawings appear not as expected: overlapping lines become darker. I could not see any description of this behavior in the documentation, and I cannot find a way to disable it.
For example if I want to draw such a polygon:
Because of the number of points, it is impossible not to have overlapping lines - fine. But because anti-aliasing is activated, some borders appear 'thicker' than others.
Is there any way to avoid this and have anti-aliased lines that can overlap and yet at the same time be rendered without getting darker?
I know of course that I can redefine the paint() function and draw manually individual lines that do not overlap, but this is what I want to avoid. I am using Pyside and this would significantly slow down the application, due to the high frequency at which paint() is being called.
EDIT Fixed by defining the object shape using QPainterPath / QGraphicsPathItem instead of QPolygon / QGraphicsPolygonItem. In that case the moveTo function allows to avoid lines that overlap.
Another thing you could try is adding half a pixel to your coordinates (not dimensions). This fixed the anti-aliasing issue for me.
XCoord = int(XValue) + 0.5
YCoord = int(XValue) + 0.5
Also make sure that before that you have integer pixel values.

How to make qt qgraphicsview scale to not affect stipple pattern?

I draw few rectangles inside the QGraphicsView ; I use custom stipple pattern for these by creating a QBrush with my QPixmap. This gets displayed with the default zoom level as expected.
When I call view->scale(), the rectangles show up bigger or smaller as I expected. However Qt has scaled the individual bits of the stipple pattern which is not expected; I expected it to draw the larger or smaller rectangle again with the brush.
Eg.
If I had used a stipple pattern with one pixel dot and pixel space, after zooming in, I want to see a larger rectangle but I want the same stipple pattern with same pixel gaps. Is this achievable somehow? Thanks.
I ran into the same problem while developing an EDA tool companion in Qt.
After some trying, what I did (and seems to work for me) is to create a custom graphics item. On the paint method, I do:
QBrush newBrush = brush_with_pattern;
newBrush.setTransform(QTransform(painter->worldTransform().inverted()));
painter->setBrush(newBrush);
That is to apply the inverse transformation of the item to the brush (so it does not scale).
I think that the setDashOffset is only for the border of the shapes (not the fill).
You may use QPen::setDashOffset:
http://harmattan-dev.nokia.com/docs/library/html/qt4/qpen.html#setDashOffset
You'll need to set the offset based on the scenes zoom/scale level. You can grab a pointer to the scene in your item by calling scene(), don't forget to check for NULL though since it will be NULL when not added to the scene (although you shouldn't in theory get a paint() when not in a scene).
The other option is to use:
http://doc.qt.digia.com/qt/qpainter.html#scale
To undo the views scaling on your painter.
In case anyone is still looking on this, a related question here regarding scaling of standard fill patterns instead of pixmap fill patterns may help. Basically, it may not be possible to modify scaling of standard fill patterns (a few workaround ideas are listed), but, working with alpha values instead gives the desired effect if you are looking for varying colors, especially gray levels - and is much less convoluted.

How to get the position of the first and the last tick mark in a Qslider?

I want to draw a tick mark for a qslider in paintEvent, so I should get the exact position of each tick mark. As you know, the handle of slider takes some space, so the first tick mark does not sit at the left/top position of the slider, there is offset of several pixels. Same thing happens to the last tick mark which indicates the maximum value. I want to know how many pixels of the space? (On win and mac, the handle are not in the same width)
If you have not yet done so, download the Qt source code and copy how they do it. You will want to look in the various Q...Style classes, i.e QMacStyle, QWindowsXPStyle, etc. Some of the key calculations come from:
QStyle::sliderPositionFromValue() method
QStyle::pixelMetric(QStyle::PM_SliderTickmarkOffset, ...)
Look in the various drawComplexControl methods for case CC_Slider:, where slider controls are drawn. In the Qt 4.7 code, this starts on line 2699 in qwindowsxpstyle.cpp, for example.

Resources