How to style QPushButton's checked state to remove grey dots?
I'm able to remove the dots by simply set border: none;
on the QPushButton:checked
property of stylesheet.
On your example, it should be like this:
w.setStyleSheet("\
QPushButton { \
color:white; \
} \
QPushButton:checked{\
background-color: rgb(80, 80, 80);\
border: none; \
}\
QPushButton:hover{ \
background-color: grey; \
border-style: outset; \
} \
");
And here you can see the result when the button is checked:
How can background color be changed for checkable QPushButton descendant?
The way to go is to use stylesheets. As you see in getStyleOption()
the state QStyle::State_On
is set when the button is checked which corresponds to the :on
pseudo state. In case of the push button the pseudo state :checked
may apply too.
QStyle::State_Off 0x00000008 Used to indicate if the widget is not
checked.QStyle::State_On 0x00000020 Used to indicate if the widget is
checked.
So your stylesheet could look like:
RichTextPushButton:checked {
background-color: red;
}
If your isRichText
variable is a dynamic property (QObject::property) you can restrict your stylesheet further:
RichTextPushButton[isRichText="true"]:checked {
background-color: red;
}
Remove checkered border around QPushButton when clicked
That "border" is actually the focus rectangle, which is shown whenever a widget has keyboard focus. In case of push buttons, it means that it can be pressed using the spacebar on the keyboard.
There are two ways to "remove" the focus rectangle: by using setFocusPolicy()
with QtCore.Qt.NoFocus
to disable any focus on the widget, or by preventing its painting.
Consider that either possibilities will make keyboard navigation (via tab and arrow keys) and interaction (with the space bar) impossible or, at least, less usable.
To disable the focus policy, just use this:
self.someButton.setFocusPolicy(QtCore.Qt.NoFocus)
Consider that disabling the focus in most styles it also disables the automatic mnemonic underscore accelerator shortcuts (for Alt+<letter> shortcuts); while on MacOS those are automatically disabled, this might be a problem on other platforms, as in this case all mnemonics need to be set manually using &
before the letter for the shortcut.
In that case, the painting approach might be useful, with the catch that if the user inadvertently presses the spacebar at any moment, the currently focused button will be pressed, which is certainly not a good thing from the UX perspective.
There are two main ways to prevent the painting: via stylesheet or via custom painting.
Using stylesheets gives complete control on the painting, but has the downsides of requiring to provide the stylesheet at least for the normal and pressed states (but possibly for the checked and hovered states also) and will not respect the platform default size hints and margins for buttons. Also, for some specific platform styles (especially on some Linux distros) there is no guarantee that the focus won't be painted if the style also mixes stylesheets internally; in those cases it is possible that the focus rectangle might be disabled by setting outline: none;
.
button.setStyleSheet('''
QPushButton {
border: 1px outset green;
border-radius: 2px;
background: lightgreen;
}
QPushButton:pressed {
border: 1px inset green;
}
''')
Custom painting can be done by subclassing QPushButton and reimplementing the paintEvent()
; by using QStylePainter() and QStyleOptionButton() we can ensure that the button will always be painted according to the current style while controlling some of its aspect before actually painting it:
class NoFocusRectButton(QtWidgets.QPushButton):
def paintEvent(self, event):
qp = QtWidgets.QStylePainter(self)
opt = QtWidgets.QStyleOptionButton()
# initialize the style option for the current button
self.initStyleOption(opt)
# remove the focus state flag if it exists
opt.state &= ~QtWidgets.QStyle.State_HasFocus
# paint the button
qp.drawControl(QtWidgets.QStyle.CE_PushButton, opt)
An alternative is to use a QProxyStyle that can be installed on the button or on the whole application (unfortunately, setting a style on a parent widget won't propagate the style on its children).
class NoFocusProxyStyle(QtWidgets.QProxyStyle):
def drawControl(self, control, opt, painter, widget=None):
if control in (self.CE_PushButton, self.CE_PushButtonBevel):
opt.state &= ~self.State_HasFocus
super().drawControl(control, opt, painter, widget)
def drawPrimitive(self, element, opt, painter, widget=None):
if element == self.PE_FrameFocusRect and isinstance(widget, QtWidgets.QPushButton):
opt.state &= ~self.State_HasFocus
super().drawPrimitive(element, opt, painter, widget)
# ...
app = QtWidgets.QApplication(sys.argv)
proxyStyle = NoFocusProxyStyle()
app.setStyle(proxyStyle)
# or, alternatively
someButton.setStyle(proxyStyle)
Note that when setting stylesheets on widgets the style is partially bypassed in some cases (depending on the style, the widget, the current default style and the properties set in the stylesheet).
Is there a way to change the external border of a QPushButton?
You could set a default margin (which sets the margins between the effective widget rectangle and its drawn contents), and set it to 0 for the focus
selector:
QPushButton {
...
margin: 1px;
}
QPushButton:focus {
...
margin: 0px;
}
QT QSS selector by part of the ID
The correct syntax is
QPushButton[objectName*="BTN"]
Find out whether PyQt QPushButton is checked using self.sender()
following the @Matho comment I have modified your code a little bit.
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
import sys
class Screen(QMainWindow):
def __init__(self):
super(Screen, self).__init__()
self.initUI()
def initUI(self):
self.lightsBtn= QPushButton('Turn On')
self.lightsBtn.setCheckable(True)
self.lightsBtn.setStyleSheet("QPushButton:checked {color: white; background-color: green;}")
self.lightsBtn.clicked.connect(self.lightsBtnHandler)
# probaply you will want to set self.lightsBtn
# at certain spot using layouts
self.setCentralWidget(self.lightsBtn)
def lightsBtnHandler(self):
if self.lightsBtn.isChecked():
self.turnOnLights()
else:
self.turnOffLights()
def turnOnLights(self):
print("truned on")
def turnOffLights(self):
print("truned off")
app = QApplication(sys.argv)
window = Screen()
window.show()
sys.exit(app.exec_())
QPushButton with an alpha level of 0% turns solid when moused over. How to fix Qt with C++ (with stylesheets?)
You don't need to use signals, stylesheet is enough.
Try this one:
QPushButton {
background-color: rgba( 35, 35, 35, 0% );
border: 1px solid black;
}
QPushButton:pressed {
background-color: rgba( 0, 255, 0, 50% );
}
Related Topics
Global CSS Variables VS Local Variables in Terms of Efficiency
Move Multiple Backgrounds Infinitely Using CSS
100% Width Divs Not Spanning Entire Width of the Browser in Webkit
Scale an Image to Maximally Fit Available Space and Center It
Animating a Smooth CSS Grid-Column Change
CSS - Mozilla Bug? Box-Shadow:Inset Not Working Properly
CSS Spread <Li> Horizontally Across <Ul>
Align Checkboxgroupinput Vertically and Horizontally
Browser Handling of CSS "Transparent" in Gradients
Inline CSS Background-Size Cover
Shape-Outside of an Image Centered Between Two Text Blocks
CSS Grid - Number of Columns Can Be Different in the First Row Than Second Row
Hide Content for Small and Extra Small Screen Size Devices
Wrap Text Around an Image on Bootstrap 3
How to Use CSS to Distort Borders So They Look Like Sketched
Is There an Ideal Size for Background Images
Image Button Displaying 'Submit Query' Over the Top of Image in Firefox
Styling HTML and Body Selector to Height: 100%; Vs Using 100Vh