QScrollArea - how to do precise programmatic scrolling - qt

I am using Qt to build a view for multipage documents. I'm drawing each page to a separate QLabel widget, like in the ImageViewer example app.
The QLabels are organized vertically using QVBoxLayout. This all works nicely, with a little grey margin between the pages.
What I want now is, when the user does page down, to move the scroll so that the top of a particular QLabel appears right at the top of the window. the "ensure" functions might do that, but I'm not immediately seeing how.
Has anyone done something like this?

If a child widget is taller that the viewport height ensureWidgetVisible scrolls to the middle of the widget.
If you need to scroll to the top of the widget you can do it easily with a little calculation:
//childWidget - QLabel you want to move to
//area - QScrollArea
// calculate childWidget position in coordinates of the viewport
const QPoint p = childWidget->mapTo(area, QPoint(0,0));
// move scroll bar
area->verticalScrollBar()->setValue(p.y() + area->verticalScrollBar()->value());

Related

reducing the width of QMenuBar and QToolBar in mainWindow

In my MainWindow ,menuBar contents and toolBar contents are few that it will occupy only a small portion in the left side off the main window and the rest of the portion is left empty.
Im having a info frame with some widgets in it in the right side of the centerwidget.
my question is that can i use the the info frame from the menu bar space itself
as menubar and toolbar can occupy only left portion of the mainwindow and i can use the entire right portion for info frame..?
You can't use that space through layout because this space is already taken by the main menu and the toolbar. There is no option to put something in this space.
But you can add a main window's child without putting it in any layout. It will be shown above all layed out children. But you will have to calculate and adjust size and position of this widget manually.
For example, add the following code to the main window's constructor:
QPushButton* b = new QPushButton("TEST", this);
b->move(200, 0);
It looks like this:

Qt & Qt Designer - Making widget fill the parent without padding

I wanted to make my widget fill the parent window, even when the window resizes, so I read this: How to make a Qt Widget grow with the window size?
But this solution created a new problem: my widget automatically re-sizes to the size of the window, but there's padding on the sides of the window. I want the widget to completely fill the parent, and it's not doing that. Look:
Here you can see that the tab widget doesn't entirely fill the parent. I've done some research and have seen that through programming, you can configure the layout to get rid of this padding. Problem is, I'm building my GUI in QDesigner, so I can't just go layout->setMargin(0);
My question is, how to I get rid of this padding on the sides of my window through Qt Designer?
In the bottom of central widget properties there is a section of Layout (it is red), where you can set layout margins. Also, you still can do it programmatically:
QMainWindow::centralWidget()->layout()->setContentsMargins(0, 0, 0, 0);

QScollArea doesn't autoscroll when dragging inside it

I have some widgets inside a QScrollArea and I'm dragging between these widgets, the problem is that the QScrollArea doesn't scroll when I'm dragging inside it, so if I want to drag between a widget A to the widget B and the widget B is not visible on the viewport, the QScrollArea doesn't automatically scroll when the mouse moves to the edge of the viewport.
Subclass your scroll area, and add in one of the functions below.
http://qt-project.org/doc/qt-4.8/qwidget.html#mousePressEvent
http://qt-project.org/doc/qt-4.8/qwidget.html#dragMoveEvent
http://qt-project.org/doc/qt-4.8/qwidget.html#dragLeaveEvent // Probably just need this one
When the dragMoveEvent reaches the edge of your widget, or when the dragLeaveEvent happens, detect which edge it is, or left at, and then scroll your area in that direction.
Hope that helps.

Qt 4.8: Layout: Hide widgets if no more space available

My application window can be resized to zero-size. I do not want to restrict the minimum window size. There are several widgets (QLineEdits, QLabels, QPushButtons) layoutet by a HBoxLayout.
At first, all widgets in the HBoxLayout were resized without respecting their sizeHint when the window was very small.
Then I used setFixedSize(sizeHint) on them. Now they do not get shrunk below their sizeHint, but instead they start overlapping when the window is very small.
What I want is what Thunderbird does (screenshots attached):
It smoothly hides the widgets by moving them out of the window border. Their size is unchanged.
How can I achieve that with the Qt Layouting system?
my application: normal window
http://i.stack.imgur.com/WLgLy.png
my application: small window
http://i.stack.imgur.com/IIhhs.png
Thunderbird: normal window
http://i.stack.imgur.com/AYJ83.png
Thunderbird: small window
http://i.stack.imgur.com/ZyQou.png
Put your widgets into a QScrollArea
Set the vertical and horizontal scroll bar policy's to AlwaysOff
Layout your Scroll area as you wish
Done & done
Probably that's not what you want but consider this:
Put your all stuff in a widget (named just 'widget' here), do not put this 'widget' into any layout just leave it free and add this event function to your window class:
void MainWindow::resizeEvent(QResizeEvent *event){
ui->widget->move(QPoint(event->size().width()-ui->widget->width()-20,ui->widget->y()));
QMainWindow::resizeEvent(event);
}
it works!

QT Layout - initial directions

I am new to QT. I'm trying to understand the layout mechanism by trying to implement this small window seen below. It has the following elements under the QWidget that's the main window:
One big QWidget that stretches on all the client area.
Two QWidget containers on the top of the window. Both should have the same height, but the right one stretches horizontally, as the window grows/shrinks.
one button container widget on the top right, with fixed height and width
Large QWidget container filling the rest of the client area, that should resize as the window resizes.
The parent window itself is resizeable.
I'm looking for hints as to what layout I should use. How do I achieve this programatically? define what stretches automatically, what stays with a fix size? and how the proportions are kept where they need to be kept.
I'd appreciate any pointer you may have.
The easiest, and IMHO best, way to accomplish this is via the QHBoxLayout and QVBoxLayouts. You can do this via the designer in QtCreator, but I find it doesn't work perfectly if you need to adapt things over time. If it's a static set of widgets, I do suggest designing it using the QtCreator designer as it'll greatly simplify your life.
If you're going to do it programatically, the main window should be set to use a QVBoxLayout and then two sub-QVBoxLayout's after that, where the bottom one is configured to take any space it can get. Then in the top QVBoxLayout, add a QHBoxLayout with your two upper components.
to set a widget to fixed size in code you call setFixedSize( int h, int w ) on the widget. To do it in Designer click on the widget and look in the property editor in the QWidget section. open the sizePolicy thingy and set horizontal and/or vertical to fixed. Then open Geometry and set the width and Height.
To make them stretch at different ratios in code you use a separate argument when using a box layout. eg layout->addWidget( button1, 1 ); layout->addWidget (button2, 2); this would cause button2 to expand at twice the rate of button1. To do this in designer, open the sizePolicy property of the widgets and set the HorizontalStrech and/or VerticalSretch. Note that the size policy needs to not be Fixed in this case for the direction you want to set the stretch on. Also it will never let a widget shrink below its minimum size (it would rather mess up the ratio than shrink something too small).

Resources