How to Style Qpushbutton's Checked State to Remove Grey Dots

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:

Sample Image

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



Leave a reply



Submit