QTabBar with One Tab is Too Wide - c++

My widget structure is as follows:
QToolBar with a QTabBar added to it and a QToolButton added after the TabBar.
By default, there will only be one tab open, and the ToolButton functions to open more tabs. (Like the tab interface for Google Chrome)
The problem I run into is that when there is only one tab, the TabBar allocates more space than necessary (looks like: size_of_tab(0) * 2) When I add extra tabs, the button aligns nicely with the TabBar, but as soon as I close them down to only 1 tab there is extra space again.
I have tried messing with the horizontalSizePolicy and programmatically setting the width, but neither worked.
Any ideas would be appreciated.

Try setting the style-sheet of the QTabBar::tab as follows, before doing this remove all the changes you have in the code which affect the tab size. You cab adjust 100px value to suit your requirement.
QTabBar::tab
{
min-width: 100px;
max-width: 100px;
}

Related

QSlider not draggable when setting groove background

Whenever I set the groove of my QSlider to an image (as an image or background-image) or background-color (but not color) I am unable to drag it, but only move it by clicking on the slider to step it. Here is my current stylesheet for reference, this is being set via a call to setStyleSheet()
fanSliderOnStyleSheet = "QSlider {padding-left: 80px; padding-right: 80px;} \n"
"QSlider::handle:horizontal{image: url(:/images/FanSlider/blowerSw2.png); padding:-65px; }\n"
"QSlider::groove:horizontal{background-image: url(:/images/FanSlider/barind.png);}\n";
If i comment out the line that sets the groove the slider works as intended so I've eliminated any other variables of the slider I can think of.
Note: I prefer setting it as a background-image over image as it maintains the true size if I do it this way.
Does anyone have any idea on how to fix this, or is it by chance a bug with Qt? I've been banging my head against the wall on this for the past couple days and my searches haven't revealed any useful information.
The padding is too high for your handle: if you set a value higher than the size of the image in the groove property, it will interfere with the handler movements (the grab section would be empty).
I get exactly the same problem when I set an image with a width to 100px and a padding property to 110px.
Remove the padding and it should be OK:
fanSliderOnStyleSheet = "QSlider {padding-left: 80px; padding-right: 80px;} \n"
"QSlider::handle:horizontal{image: url(:/images/FanSlider/blowerSw2.png);}\n"
"QSlider::groove:horizontal{background-image: url(:/images/FanSlider/barind.png);}\n";

Qt QDockWidget adds extra margin space

I have a QDockWidget where both the contents and size of the dock should be the same. I currently am encountering an issue where although the size of the dock is valid; the parent central widget create a 4 pixel gap on the right which I cannot seem to shrink when resizing the mainwindow. Here's a screenshot:
This is the code that I use to force the dock to a specific size; which works fine and makes the dock the correct size. (it also contains a frame which should be the same size as the dock):
ui->dockFrame->resize(w, h);
ui->dock->setFixedSize(w, h);
I have also tried using layout()->setContentsMargins(0,0,0,0); for both the mainwindow and central widget to no avail.
Does anyone have an idea on where these extra pixels may be coming from, and how to resolve this issue? Thank you in advance.
The gap has very little to do with the QDockWidget. It's a property of QMainWindow - it's a movable separator between dock widgets, or between dock widget and a central widget.
You can get rid of it for example with the style sheet:
QMainWindow::separator
{
width: 0px; /* when vertical */
height: 0px; /* when horizontal */
}
in your C++ code:
mainwindow->setStyleSheet("QMainWindow::separator{ width: 0px; height: 0px; }");

Qt - Unable to move scrollbars in QScrollArea

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; }"));

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.