Qt - Unable to move scrollbars in QScrollArea - c++

I have an application that includes a vertical layout of push buttons, which is inside a container widget, which is inside a scroll area, which is part of another layout, which is applied to the main window. The setup is currently in a working state, and I'm able to scroll using the vertical scrollbar on the right side of the window.
The problem is that this application is meant for a touchscreen, and the default scrollbar is too small for fingers. I've been able to resize it using setFixedWidth() and/or stylesheets; however, the left edge of the scrollbar remains in the same position. The result is that the scrollbar only expands to the right, putting it off-screen.
I've tried figuring out how to move the scrollbar back to the left so that the entirety of it can be seen on-screen, but I've not been able to find out how to do this yet, as I'm still fairly new to Qt. I've tried using setGeometry(), but it seems to have no effect whatsoever. I even tried creating a separate QScrollBar and adding it manually, but I get the same off-screen result.
Is there something in the layout settings that could be causing this?

You should use stylesheets to resize scrollbars:
ui->scrollArea->setStyleSheet(QString("\
QScrollBar:horizontal { height: 30px; } \
QScrollBar:vertical { width: 30px; }"));

Related

Qt Scroll area can't scroll

I have a problem with QScrollArea, I want to make a scrollable design, because standard window is not enough for me. But, I can't scroll it down and add / see new content. I don't know why. I want to set for eg. 1600 px scroll area height and make a layout to it in Desiner. But in this situation I can't scroll it:
I heard a tip to add a layout to ScrollArea, but I don't want to use it, I want to make a layout myself.
I have tried to uncheck 'widgetResizable'
So is it any other method to scroll this widget?

Positioning QPushButtons via qss in QT

I have a set of five buttons that I am trying to position in a qss file. The default position that I have set up in the ui file works for one of the layouts I need. However, I want to group the buttons differently in the other theme.
I am new to qss files and have been experimenting, but cannot figure out if some things are possible. The "left" property is defined here: http://doc.qt.io/archives/4.6/stylesheet.html#left-attr but nothing happens when I try to use it.
margin-left actually moves the button, but only relationally. So, if the buttons are positioned in the ui file with a gap of 100 between them, a margin-left for the second button in the list is offset by 100.
What am I doing wrong? Could it be some setting in the ui file that is preventing it from moving? I already "broke layout" and it doesn't seem to matter. Is there a good resource you'd suggest?
Here is a sample of my qss file. The left has no effect.
QPushButton#Button_1
{
min-width: 50;
max-width: 50;
min-height: 50;
max-height: 50;
position:absolute;
subcontrol-origin: border;
left:200;
}
EDIT:
I've figured out that I can change the position of the button by deriving a class from QPushButton and making a "GeomX" qproperty. This seems to work, but I am running into an odd issue now. When I first load my app, it draws the buttons as they are positioned on the ui file. When I use the "change theme" option that I've coded, and select the currently loaded theme, it moves the buttons as I'd expect. However, resizing the app dumps them back to the ui positions and restarting also places them back in their ui positions. Is there a setting in the ui file that I could alter to get it to stop moving them? Is there a load-order issue that I need to address? Is it possible to even address this? What is going on?
Generally speaking, style sheets in Qt are used to alter the way a widget is drawn, not where it is positioned (except to add padding/margin). As the documentation you've referenced mentions, the "left" property is specific to sub-controls (that is, components within a widget and not the widget itself).
What it sounds like you're trying to accomplish (change the layout depending on the theme) would likely require a different approach. A couple of options would be to react to when the theme changes by:
Moving around your spacers in your layout to move the buttons to the desired position
Using a stacked widget, one page in the stack for each layout you desire, and change which page in the stack you're showing depending on what theme you're using.

Widget under a QTabBar with unwanted frame

I have a problem with QTabBar/QTabWidget. This is what my program looks like at the moment, using QTabBar:
As you can see, there is an unsightly line between the QTabBar and the QScrollArea underneath it. This line is part of the frame of the QScrollArea, which I can't simply get rid of, because it is required on the other three sides. I realise I could use QTabWidget, but then I would have to create a widget for each tab, which is not feasible here: the contents of the QScrollArea change according to the selected tab, but there is only one QScrollArea widget. (Duplicating it each time a new tab is created would cause its own problems.)
So does anybody know a way to either:
(i) tell the QScrollArea to draw a frame without the top line; or
(ii) use the same widget for each tab in a QTabWidget?
Update 3 For another approach, see my answer below.
Update 1 I have implemented zvezdi's suggestion, and the unsightly line has disappeared:
This is an improvement. But it's not right. Look at the gaps between the scroll bars and the border. On the right, it's two pixels instead of one; on the bottom, it's three pixels. And the gap on the right between the QScrollArea border and the mainWidget border is one pixel too big. This is due to QTabWidget's border style, which I am losing my sanity trying to change. If I say:
MyTabWidget -> setStyleSheet ("QTabWidget::pane { margin: 0px,0px,0px,0px }") ;
then the margins seem to be right, but the borders disappear:
If I say:
MyTabWidget -> setStyleSheet ("QTabWidget::pane { "
" margin: 0px,0px,0px,0px;"
" border: 1px solid darkgray;"
"}") ;
then I'm almost back to where I started:
If I try to remedy this with:
ApplicationTabWidget -> setStyleSheet ("QTabWidget::pane { "
" margin: 0px,0px,0px,0px;"
" border: 1px solid darkgray;"
" border-top: 0px;"
"}") ;
then again I am mocked for my pains:
Update 2 If I forget setStyleSheet and just turn documentMode on, this is what I get:
Please somebody, tell me I'm being stupid, and there's a perfectly simple solution to all this.
You said "the contents of the QScrollArea change according to the selected tab" well if I assume that this is not true, and what you mean is that the content of the widget that is inside the scroll area changes, then you can try this:
Make as many QScrollArea objects as many tabs you need in your QTabWidget, but only one, for example QTextEdit, which you will show in every scroll area, and which content will change on tab change (takeWidget() from the old tab's QScrollArea & setWidget() on the new tab's QScrollArea)
I don't know how you've designed your code, but to try my suggestion your code should be designed around the widget inside QScrollArea, rather than the QScrollArea itself.
Unless I misunderstand, if you turn off the QScrollArea's border by setting the frameShape to NoFrame, the tab widget still has its frame lines on the sides and the bottom where you want them.
I have tried another approach: Use QTabBar, as in the first screenshot, and then change the style for MyScrollArea (obvious, in retrospect):
MyScrollArea -> setStyleSheet ("QScrollArea {"
"border: 1px solid #898C95;"
"border-top: 0px;"
" }") ;
This is the result:
Almost right! There are three problems:
- the little square at the intersection of the two scroll bars is missing its bottom border (but it gets drawn if I click on the scroll bars, or resize the window, or the main window loses focus);
- the colur #898C95 is hard-coded, so it won't be right if the user changes the style. But if I leave out the border style, then the whole border is painted white. Is there a way to query the current border colour of a style?
- most seriously, the background colour of the breakpoint widget on the left-hand side is not white any more.
But I think I've wasted enough time on this! I will stick with this solution unless anybody can suggest something else to try.

Stringray Grid transparent background

In Stringray grid, there is the ability to use a transparent background which allows the background of the dialog to be shown through the grid.
In the documentation it states:
But be careful; you should disable scrolling or you have to redraw the grid each time it is scrolled (by overriding DoScroll).
I have a scrollable gird and override the DoScroll and make sure I call Redraw and also tried Invalidate, however the grid is still not completely erasing and redrawing.
I also tried using the old drawing method by setting m_bForceOldDrawing to TRUE.
How can I create a grid that has a transparent background that paint correctly after a scroll without leaving artifacts?
Yes you have to redraw the grid by overriding DoScroll because it is no longer using ScrollWindow to scroll contents because the background is transparent.
However you now have artifacts of the grid over your background.
This is because the background behind the grid is not getting redrawn.
Do you have clipchildren set for the parent?
Another potential problem is that the background is not being drawn because it doesn't realize it has been exposed.
Try calling the parent with the following.
Parent.Invalidate();
Parent.UpdateWindow();
before calling...
Invalidate();

Qt: Dragging a widget to scroll the widget's parent QScrollArea?

I've got a long horizontal QLabel displaying a png (the image shows a signal/time graph). Under that, I've got a QTableWidget. Both of these are in a QScrollArea because I want them to stay vertically aligned (the cells in the table correspond with the signal seen directly above them). I'm trying to add a handler to the QLabel such that the user can use the picture itself to scroll the scrollarea, rather than having to use the scrollbar. Is there a tried-and-tested way to do this? Directly setting the scrollarea's sliderPosition inside the QLabel's dragMoveEvent doesn't seem smart, because when the scrollarea scrolls it also leads to another dragMoveEvent on the (moving) QLabel.
I would suggest wrapping the combination (including the scroll area) in their own widget, and overriding the dragMoveEvent() on that widget. The dragMoveEvent() shouldn't be triggered when you change the scroll position if you are doing it this way, I wouldn't think, although I haven't actually tested it.