I came across a button style which I like, I wanted to recreate it for use in pyqt5, using the QPushButton class, and styling it with css. If I can recreate it, I can change it's colours in cool ways.
In CSS terms, the button has a "solid" border of 1px all around, with a "border radius" of 2px, and I found it at 21px tall, however obviously it's resizeable. If anyone is wondering, it is the humble "Vista" button:
The Qt framework implements features based on the older CSS 2.1 standard, so somebody with knowledge of only CSS may know how this is done.
My inexperience with CSS is letting me down, unfortunately. Usually I can brute-force my way through a problem, and then tidy up and optimise my implementation, however here I have hit a bit of a stump.
90% of the look of the button can be created with a simple linear gradient for the background-color, however there is an "inner border" (bevel effect) of 1px which is flush with the real border and goes all the way around the button, I am having trouble re-creating this look.
The bevel is deceptively one color at the bottom and a different one at the top, and along the sides of the button there is a seperate linear gradient to link them together.
I tried messing with border styles, even with using gradient colours for the border, and I am not having any luck. Something that seemed useful called the "double" border style unfortunately was of no use to me, since you cannot control both border colours separately very well.
The below should explain it all.
No linear gradient in background color gets you this:
A simple linear gradient with a few stops gets this:
A complex (crudely done) linear gradient can get top+bottom bevel:
And this is a real button (not made by me), notice the sides:
Here is the code for the 3rd picture (over-engineered linear gradient with very many stops, don't laugh, this is a rough version - it can be done with less steps, but it is pixel perfect everywhere apart from the sides)
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QPushButton, QVBoxLayout)
app = QApplication([])
window_container = QWidget()
window_container.setWindowTitle("Buttons")
window_container.setMinimumSize(200,125)
window_container.setObjectName("window_container")
window_container.setStyleSheet("QPushButton {"
+ "border-style: solid;"
+ "border-width: 1px 1px 1px 1px;"
+ "border-radius: 2px;"
+ "border-color: #707070;"
+ "font: 9;"
+ "padding: 3px;"
+ "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, "
+ "stop:0 #FCFCFC, "
+ "stop:0.075 #FCFCFC, stop:0.111 #F2F2F2, stop:0.216 #F2F2F2, "
+ "stop:0.217 #F1F1F1, stop:0.252 #F0F0F0, stop:0.320 #EFEFEF, "
+ "stop:0.350 #EDEDED, stop:0.389 #ECECEC, stop:0.499 #EBEBEB, "
+ "stop:0.500 #DDDDDD, stop:0.556 #DBDBDB, stop:0.611 #DADADA, "
+ "stop:0.667 #D8D8D8, stop:0.700 #D6D6D6, stop:0.750 #D4D4D4, "
+ "stop:0.800 #D2D2D2, stop:0.870 #D1D1D1, stop:0.910 #CFCFCF, "
+ "stop:0.945 #F3F3F3, "
+ "stop:1.0 #F3F3F3);"
+ "}"
)
button_1 = QPushButton("Top")
layout = QVBoxLayout()
layout.addWidget(button_1)
window_container.setLayout(layout)
window_container.show()
sys.exit(app.exec())
After a full analysis, I can provide a breakdown of what needs to be done, apologies for the crude diagrams:
In this diagram, (c) is the main gradient fill (which doesn't share colours with anything else on)
Here's a legend for the above diagram to help make sense of things:
I don't know if I've reached the limits of what linear-gradient tool can do, or if there's something super easy I am missing, but I have every reason to believe this is possible, it's just rather specific.
The real trick here is that the "side" bevels need to be linear gradients connecting the top row of pixels inside the button to the bottom row, I can't figure that bit out.
Maybe someone finds this fun or a challenge, I am happy to try anything (within reason).
setStyleSheet()
does not completely overridesetStyle()
; in fact,setStyleSheet()
creates an internal QStyleSheetStyle for all affected widgets, but still uses, to some extent, the QStyle set (for the widget or application wide), that's why it's normally suggested to useQApplication.setStyle('fusion')
in order to get consistent/reliable QSS behavior. 2. While I understand the need for indentation and tidiness, I'd suggest you to use triple quotes when writing QSS, as it makes it easier to read and edit them.