Why Qt's addWidget() can accept 1 argument case? - qt

statusBar()->addWidget(locationLabel);
statusBar()->addWidget(formulaLabel, 1);
Above code is from a Qt program.
And below description is from Qt help when I pressed F1 on addWidget.
As you can see, addWidget shall accept 2 arguments. My question is why above 1st sentence can be executed normally?
void QStatusBar::addWidget ( QWidget * widget, int stretch = 0 )
Adds the given widget to this status bar, reparenting the widget if it
isn't already a child of this QStatusBar object. The stretch parameter
is used to compute a suitable size for the given widget as the status
bar grows and shrinks. The default stretch factor is 0, i.e giving the
widget a minimum of space.
The widget is located to the far left of the first permanent widget
(see addPermanentWidget()) and may be obscured by temporary messages.

This is because C++ has the concept of default arguments, which means that a function declared as
void f(int i, int j=1);
can be called by
f(42);
and
f(42,43);
In the first case, the function call is equivalent to
f(42,1);
In your case,
addWidget(label);
is equivalent to
addWidget(label,0);

Related

how to get the current widget's cursor size in pixels

How to get the current mouse cursor size measured in pixels? I tried mywidget.cursor().pixmap().size() but it returns (0,0) for the standard arrow cursor.
(I need this to show a special tool tip label which would appear just below the cursor and would follow the cursor and I cannot use the standard QToolTip for certain reasons - delays etc. I already have a nice, working solution but if I display the label exactly at the cursor position, the cursor is painted over it hiding some text on the label. Of course I could move it down using some 'magic' number like 32 pixels, but this would cause me bad stomach feelings.)
You can't do this with the standard cursors. The QCursor methods only work with custom bitmaps or pixmaps. So you will either have to use your own cursors, or estimate the size.
A quick web-search suggests that the standard cursors can vary in size and there is no fixed maximum (although that probably depends on the platform). For example, on X11, the size range usually includes 16, 24, 32, 48, and 64, but other sizes may be possible (even as large as 512). The default is normally 32.
If you need accuracy, it would seem that using custom cursors is the only way to solve this problem.
You could use the code that is used in QTipLabel::placeTip, which offsets tooltips based on cursor size:
const int screenIndex = /*figure out what screen you are on*/;
const QScreen *screen = QGuiApplication::screens().value(screenIndex, QGuiApplication::primaryScreen());
if (const QPlatformScreen *platformScreen = screen ? screen->handle() : nullptr) {
QPlatformCursor *cursor = platformScreen->cursor();
const QSize nativeSize = cursor ? cursor->size() : QSize(16, 16);
const QSize cursorSize = QHighDpi::fromNativePixels(nativeSize, platformScreen);
}
To do this you do need at least one private header:
#include <qpa/qplatformscreen.h>
#include <qpa/qplatformcursor.h>
#include <QtGui/private/qhighdpiscaling_p.h>
If it doesn't have to be portable you can look at the size implementation of the QPlatformCursor implementation for the platform you're targeting (e.g. QWindowsCursor::size()) and use that code.

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();

How to create an infinitely long line

Whats is the best way of creating a line (QGraphicsLineItem) which starts at some point on the scene and continues to infinity at some angle.
The way I presently do this is by calculating were the line intersects the view and drawing the line segment.
Is there a better way?
Could I for example set the lines length to some massive number?
You could define its paint() and shape() functions so they always use all the space available and needed inside the scene, i.e. inside the visible part of qgraphicsview.
Guidelines:
Examine mapping functions for qgraphicsview, qgraphicsscene and
qgraphicsitem (mapToScene, mapToItem, mapToView or something like that)
Define your shape() and paint() functions as if your
line is exactly long all over the view (by using the mapping functions above)
So, how ever the user moves his view, repaint will examine the space used by qgraphicsview and draw exactly that long. The illusion is created that the line goes on-and-on.

Make QGraphicsView do smooth centerOn

i am not really newbie in Qt, but there are a few things i don't know...
I am programming in Python, but feel free to post your answers in ANY language.
So, i have a few QGraphicsItem (s), positioned inside a QGraphicsScene, the scene is viewed with a normal QGraphicsView. Everything is normal.
My scene is very large, 10,000 x 10,000 pixels, all graphic items are scattered around.
For example :
# Creating Scene object.
scene = QtGui.QGraphicsScene()
scene.setSceneRect(0, 0, 10000, 10000)
# Creating View object.
view = QtGui.QGraphicsView()
view.setScene(scene)
# Adding some objects to scene.
# scene.addItem(...)
# ...
# The list of items.
items = scene.items()
# This is how i center on item.
view.centerOn(some_item)
view.fitInView(some_item, Qt.KeepAspectRatio)
My question is, how can i center the view on every item, using something similar to centerOn, but smoothly ?
Currently, centerOn goes FAST on next item, i want to move it slooowly, maybe using QPropertyAnimation with easing curve ?
I tried to move the view to the next item using view.translate(1, 1) in a big cicle, but the movement is too fast, just like centerOn.
I tried to put some waiting with time.sleep(0.01) between the translating, but the windows blocks untill the cicle exists... so it's bad.
Thank you very much !
I once used a QTimeLine (with EaseInOutCurve), connected it to a slot, and then used that value to translate the view rect, like this:
const QRectF r = ...calculate rect translated by timeline value and trajectory...
view->setSceneRect( r );
view->fitInView( r, Qt::KeepAspectRatio );
For the trajectory I used a QLineF with start and end position for the smooth scrolling.
Then one can use the value emitted by timeline nicely with QLineF::pointAt().
In my case I needed to set both SceneRect and fitInView to make it behave like I wanted.
I solved my problem by placing a high value on setSceneRect. Then I centralize the scene on an object or position.
example:
this->ui->graphicsView->setSceneRect (0,0,100000000, 100000000);
this->ui->graphicsView->centerOn(500,1030);
With the setSceneRect size GraphicsView does not work right.

How to use custom drawing in QGraphicsViews in PyQt?

I need to view QGraphicsScene in 2 QGraphicsViews with condition that they have different scale factors for items in scene. Closest function which I found is drawItems(), but as far I can understand, it must be called manually. How to repaint views automatically?
I have these two code fragments in program:
class TGraphicsView(QGraphicsView):
def __init__(self, parent = None):
print("__init__")
QGraphicsView.__init__(self, parent)
def drawItems(self, Painter, ItemCount, Items, StyleOptions):
print("drawItems")
Brush = QBrush(Qt.red, Qt.SolidPattern)
Painter.setBrush(Brush)
Painter.drawEllipse(0, 0, 100, 100)
...
Mw.gvNavigation = TGraphicsView(Mw) # Mw - main window
Mw.gvNavigation.setGeometry(0, 0, Size1, Size1)
Mw.gvNavigation.setScene(Mw.Scene)
Mw.gvNavigation.setSceneRect(0, 0, Size2, Size2)
Mw.gvNavigation.show()
__init__ works, Mw.gvNavigation is displayed and there are Mw.Scene items in it, but drawItems() isn't called.
The drawItems methods on QGraphicsView and QGraphicsScene objects have been deprecated in Qt 4.6 and have to be enabled using the IndirectPainting flag, but I would't recommend using deprecated features.
Here's another stack overflow question on a similar issue. One of the answers shows how to make the paint methods on individual items in a scene aware of which view is painting them, and use different paint code when drawn in different views.

Resources