1

With a simple QPushButton, if I want to use custom images while the size of the button is determined by a layout (so it can be scaled freely), the only possibility is to override border-image in the style sheet. If I add the image as an image attribute instead of border-image, then the images are not scaled down.

However, if I use a QRadioButton and override the image or border-image, the circle of the radio button remains visible. I found no way of hiding it or overriding it.

A possibility would be to ignore the label, and change the circle icon itself. This can be done by overriding QRadioButton:indicator, however, it doesn't accept border-image, it only accepts image which will not scale.

Is there any way to solve this, or am I stuck with using QPushButton with setCheckable(true), and handle the other buttons manually whenever one of them is pressed?

I tried specifying a border-image for the label, and a non-existing image for the indicator:

ui->radioButton->setStyleSheet(
"QRadioButton { border-image: url(:/img/off.png) 0 0 0 0 stretch stretch; }"
"QRadioButton:checked { border-image: url(:/img/on.png) 0 0 0 0 stretch stretch; }"
"QRadioButton:pressed { border-image: url(:/img/off_pressed.png) 0 0 0 0 stretch stretch; }"
"QRadioButton:checked:pressed { border-image: url(:/img/on_pressed.png) 0 0 0 0 stretch stretch; }"
"QRadioButton:indicator:unchecked {image: url()}"
"QRadioButton:indicator:checked {image: url()}"
"QRadioButton:indicator:unchecked:pressed  {image: url()}"
"QRadioButton:indicator:checked:pressed {image: url()}"
);

The problem is, that although the circle is now not visible, it still takes up space, so the image doesn't fill up the entire available space.

vsz
  • 4,811
  • 7
  • 41
  • 78
  • 1
    What do you mean by "scaling" here? `image` and `border-image` (and `background` images) have different use cases. Any SVG image is smoothly scalable, raster images are not. And what does "custom images" mean in regards to push buttons... do you mean the icon? The radio button icon is [customized](https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qradiobutton) with `::indicator` subcontrol, and like any button the image should "scale" to fit the current `iconSize` property. Also, use `image: null;` to get rid of icons, not a blank URL (which causes painter warnings as you saw). – Maxim Paperno Jan 11 '20 at 08:34

1 Answers1

1

Reducing the size of the indicator to zero seems to work. It's still an ugly hack (as Qt still doesn't support scalable images for buttons and labels unless they are defined as border image), but it works.

ui->radioButton->setStyleSheet(
"QRadioButton { border-image: url(:/img/off.png) 0 0 0 0 stretch stretch; }"
"QRadioButton:checked { border-image: url(:/img/on.png) 0 0 0 0 stretch stretch; }"
"QRadioButton:pressed { border-image: url(:/img/off_pressed.png) 0 0 0 0 stretch stretch; }"
"QRadioButton:checked:pressed { border-image: url(:/img/on_pressed.png) 0 0 0 0 stretch stretch; }"
"QRadioButton:indicator {width: 0px; height: 0px;}"
);

A disadvantage of this solution is that a bunch of QPianter errors are printed to stdout, seemingly because of the non-existent indicator:

QPainter::begin: Paint device returned engine == 0, type: 3

To avoid this, I created an 1x1 pixel completely transparent png image

"QRadioButton:indicator {width: 1px; height: 1px; image: url(:/img/empty.png)}"

This works just as well, without generating QPainter error messages.

Edit:

As Maxim Paperno commented, this also works:

"QRadioButton:indicator {image: null}"
vsz
  • 4,811
  • 7
  • 41
  • 78