MangoCat
MangoCat

Reputation: 89

Problem with Tristate QCheckBox not repainting itself when set programmatically

When I have a QCheckBox with tristate set true, it does not repaint itself when transitioning from Qt:PartiallyChecked to setChecked(true) programatically.

A minimal example built in QDesigner places a QCheckBox and QPushButton on the central widget of the default MainWindow. The QCheckBox is default configured except tristate is checked. In code, the ui checkBox is set to Qt::PartiallyChecked in the constructor, and an on_pushButton_clicked() function calls ui->checkBox->setChecked( true );

Expected behavior: when pushButton is clicked, checkBox should change from partially checked to checked appearance.

Observed behavior: checkBox appearance does not change until moused over.

Note: it's even worse when the checkbox has been restyled to be used as a tri-state indicator and is not enabled for user input... the disabled checkbox doesn't repaint on mouseover then.

I discovered this behavior in Ubuntu 18.04 default using the native 5.9.5 Qt libraries running in release mode, but it is also reproducible in 5.14.2 and many other library versions.

The sample code below is 99% the default Qt Widgets application with modification as described above.

The only workaround I have found so far is to repaint the QCheckBox widget anytime its state is changed... not great, but at least it works.

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{   ui->setupUi(this);
    ui->checkBox->setCheckState( Qt::PartiallyChecked );
}

MainWindow::~MainWindow()
{ delete ui; }

void MainWindow::on_pushButton_clicked()
{ ui->checkBox->setChecked( true ); 
  // Uncomment the repaint() for a kludgey fix
  // ui->checkBox->repaint();
}

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

public slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

main.cpp:

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.ui:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>173</width>
    <height>98</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QCheckBox" name="checkBox">
    <property name="geometry">
     <rect>
      <x>40</x>
      <y>10</y>
      <width>92</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>CheckBox</string>
    </property>
    <property name="tristate">
     <bool>true</bool>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>40</x>
      <y>50</y>
      <width>89</width>
      <height>25</height>
     </rect>
    </property>
    <property name="text">
     <string>PushButton</string>
    </property>
   </widget>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

Tristate.pro:

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

Upvotes: 0

Views: 392

Answers (1)

MangoCat
MangoCat

Reputation: 89

Best patch I know so far is to repaint the QCheckBox whenever its state is changed.

Upvotes: 0

Related Questions