Widget under a QTabBar with unwanted frame - c++

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.

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/C++ - Set background of disabled button?

I have all my buttons disabled in a grid, but for some, I'd like to change the background color. I'm trying:
_fieldButtons[0][0]->setStyleSheet("color: blue; background-color: blue;");
Where
QVector<QVector<QPushButton*> > _fieldButtons;
However, these buttons are all disabled, and only the text color gets changed:
How can I change the background, but not the text? Thank you!
UPDATE
I figured it's not working because the buttons are flat. How can I change flat button colors?
Two options:
Add border: none; to your stylesheet.
Use setAutoFillBackground(true) in conjunction with QPalette::Button
myButton->setFlat(true);
myButton->setAutoFillBackground(true);
QPalette pal = myButton->palette();
pal.setColor(QPalette::Button, QColor(Qt::blue));
myButton->setPalette(pal);
http://doc.qt.io/qt-5/qpushbutton.html#flat-prop
Try this:
myButton->setPalette(QColor("#124e6b"));
simply change the QColor to suit your use.
Or in Qt Creator you can right-click on the widget and select Change Style Sheet, as shown here:
Here you have two "Pseudo-States" in your control. For list of "Pseudo-States" refer below link.
http://doc.qt.io/qt-5/stylesheet-reference.html#list-of-pseudo-states
The first "Pseudo-State" is -- flat
The second "Pseudo-State" is -- disabled
Here you have to club both the states to set the style using "setStyleSheet".
_fieldButtons[0][0]->setStyleSheet(":flat:disabled {background-color: blue; border: none;}");
look for ":hover:enabled" (two different "Pseudo-States" how documentation handled) in the below link to get better idea.
http://doc.qt.io/qt-4.8/stylesheet-syntax.html
To understand, why you we have to give border:none for QPushButton, please look for below information in the first hyperlink in this answer.
"Warning: If you only set a background-color on a QPushButton, the background may not appear unless you set the border property to some value. This is because, by default, the QPushButton draws a native border which completely overlaps the background-color."

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

Qt remove empty space between widgets on QVBoxLayout

I have annoying problem. I created QVBoxLayout on which I added my widgets.
This is sample from my constructor:
layout = new QVBoxLayout;
layout->setMargin(0);
layout->setContentsMargins(QMargins(0,0,0,0));
layout->setSpacing(0);
And then I have function to add widgets.
layout->addWidget(_wave);
_wave is my own widget. But you can add whatever you want, for example QButton.
What do I want achieve?
Similar like this but without any spaces beetween widgets added to layout. Just only QButtons or other widget, sticked each other.
I added everywhere setMargins, setSpacing etc.
Please help me with that, I don't really have an idea what should I do.
Sorry for colors, but I wanted to mentioned what I want to achieve. I have mainWindow on which I added QWidget. This widget have blue background. Then to the layout, Im addding some widgets, which are orange on this image. I just want to be sure, that this blue background between widget isnt visible. I want to have widget under widget, without any space.
I know the question was posted a year ago, but if it can help some people save some time, I would be glad. I had the same problem and was able to solve it by setting:
QFrame.setFrameShape() to NoFrame
QFrame.setLineWidth() to 0.
The image below is the result of 2 QtextEdit put side by side in a Layout, using the described method.
http://doc.qt.io/qt-5/qframe.html#lineWidth-prop
Try this to achieve a "tight" look. Note that if you resize the parent widget, they will not move. Not sure if this is what you want or not, but...
// After all widgets are added to the layout
layout->insertStretch( -1, 1 );
The 2nd argument needs to be higher than any other stretch factor. Stretch factor is default zero, so if you don't set it, the above one-liner should work.
Spacing Never Zero?
As the Qt document says, some default GUI widget has extra frame around it.
Take QPushButton as an example:
In some GUI styles a default button is drawn with an extra frame
around it, up to 3 pixels or more. Qt automatically keeps this space
free around auto-default buttons, i.e. auto-default buttons may have a
slightly larger size hint.
So the culprit is not the layout but the widget itself instead. "Invisible" margin of a default widget remains even if the spacing of the layout has been set to 0.
Soultion
If you really need a "compact" layout, my suggestion is to resort to the stylesheet of the widget.
Examples
Here are examples to illustrate the idea:
Here, we have a vertical layout with both margin and spacing equal to 0, and the buttons with custom stylesheet:
QPushButton {
border: 2px solid #8f8f91;
border-radius: 6px;
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #f6f7fa, stop: 1 #dadbde);
min-width: 80px;
}
// (further stylesheet for button click is needed)
Resetting stylesheet allows us to make the layout more compact:
Insert a default QPushButton to see the difference:
You can see there is space around the default QPushButton. That's the same for other kinds of widgets.
I could be wrong but there does not seem to be an obvious and non-hack of a way to do what you desire. However, according to the documentation you may find that just doing a manual layout will solve your problem. (http://doc.qt.io/qt-5/layout.html : Manual Layout)
It seems as if one could implement a Layout class that actually provides a very compact horizontal or vertical layout and I believe I had written one a few years ago using Python and Qt. With that in mind, you should be able to implement your own MyCompactLayout(horizontal=True) and use it.

Maintaining rounded corners when the height is less than twice the border radius?

In Qt you can use CSS stylesheets to give a QWidget a rounded corner:
QWidget#myWidget {
background-color: #ffbb33;
border-radius: 20px;
}
I wanted to animate this QWidget to show it popping up from the bottom of the screen to notify the user, but found that when the height of the widget is less than the border radius, the rounded edges jarringly disappear.
Is it possible to prevent this?
Update: I appreciate everyone's web related solutions to this problem. Most of them actually do translate pretty well to this application. But I do just want to point out that this application is coded in C++ with Qt libraries. If you have other web-related solutions, please do post them, but be aware that if you're using web technologies to do this, then "It works for me" isn't exactly applicable in this case. ;)
You could animate the corners. Start small or no border radius and build up to what you need. You may not be using jQuery but you could do something similar.
CSS
#myWidget {
border-radius: 5px;
}
jQuery
$('#myWidget').animate({ 'border-radius': '20px' }, 1500);
Why not just set the bottom CSS property to its negative height, and then animate the bottom property to 0, rather than height? See this fiddle for an example. This way you don't have to mess with the height of the element, and there won't be any weird squishing of the content, either.
Since you're using QPropertyAnimation, you can set up an animation in parallel to your resizing animation that animates the rounded border going from radius 0px to 20px (or whatever).
one thing you could do is to reimplement the QWidget's resizeEvent, and there, calculate the maximum availabe size for the borders. Then set the border radius using this.setStyleSheet("border-radius: ?px"); (replacing ? for the result, ovbiously)
You can check here how to reimplement a function: https://beginnersbook.com/2017/09/cpp-function-overriding/, where BaseClass is QWidget and DerivedClass is the new widget, which you could call QRoundedCornersWidget.