QSlider not draggable when setting groove background - c++

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

Related

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."

smooth animation using css3 transition

I have add a font awesome user icon in an element. When I hover on that element I want the icon size to be decreased thoroughly. So I have used transition as "all 0.5s ease". It works but it animated step wise. Can it possible to animate the icon smoothly.
The problem you have is that as the text reduces in size, so does the hover target, which means the text can reach a point where you are no longer hovering and so it starts to grow again. This is likely to cause a nasty visual jaggy effect.
In the below example, the first example uses "focus" which isn't affected by the change in size. The second uses "hover", which is highly likely to be affected.
Click or tab onto example one and it will resize smoothly. Try to hover on example two and it will be horrible.
You can solve this by having a hover target that remains a constant size, so isn't reduced during the animation.
Other common causes for jagginess in this particular area (resizing text) are:
If the browser struggles to render the font during the resize
If the before and after sizes are not far apart and the animation has a long duration
If the before an after sizes are very far apart and the animation is has too short a duration
div {
font-size: 5em;
transition: font-size 0.5s ease;
}
div:focus {
font-size: 0.5em;
}
p {
font-size: 5em;
transition: font-size 0.5s ease;
}
p:hover {
font-size: 0.5em;
}
<div tabindex="0">
Example One
</div>
<p>
Example Two
</p>

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.

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.