madasionka
madasionka

Reputation: 922

Qt text alignment in QCheckBox

I am looking for a way to align text in a QCheckBox to both the right and left side. I cannot seems to find any ways to modify just the alignment of the text and not the checkbox itself.

Upvotes: 1

Views: 3637

Answers (2)

Hong승원
Hong승원

Reputation: 136

I solved it using a trick.

Create a QCheckBox without putting any text in it.

And create a QLable so that you can center the text and click it.

Then it's possible.

Below is the example code. You can refer to it.

import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *


class MyApp(QWidget):
    ###### Define StyleSheet ######
    DEFAULT_COLOR = {
        'border': '#000000',
        'hover': '#29adff'
    }

    CP_DEFAULT_STYLE = '''
        QCheckBox::indicator:hover {{
            border: 1px solid {hover};
            background: white;
        }}
        QCheckBox::indicator {{
            border: 1px solid {border};
            background: white;
        }}
    '''

    CP_DEFAULT_STYLE_SET_VALUE = CP_DEFAULT_STYLE.format(**DEFAULT_COLOR)
    ################################

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.cb = QCheckBox(self)
        cp_label = QLabel('Click\nHere Me!!', self)

        self.cb.setStyleSheet(self.CP_DEFAULT_STYLE_SET_VALUE)
        cp_label.setAlignment(Qt.AlignmentFlag.AlignCenter)

        cp_label.setGeometry(75+30, 50+15, 60, 30)
        self.cb.move(75+90, 50+20)

        self.cb.clicked.connect(self.cpClick)

        cp_label.mousePressEvent = self.cpLabelClick
        cp_label.leaveEvent = self.cpLabelLeave
        cp_label.enterEvent = self.cpLabelEnter

        self.setWindowTitle('QCheckBox')
        self.setGeometry(300, 300, 300, 200)
        self.show()

    def cpClick(self):
        if not self.cb.isChecked():
            self.cb.setStyleSheet(
                self.CP_DEFAULT_STYLE_SET_VALUE
            )
        else:
            self.cb.setStyleSheet('')

    def cpLabelClick(self, _):
        self.cb.setStyleSheet('')

        self.cb.setChecked(
            not self.cb.isChecked()
        )

    def cpLabelLeave(self, _):
        self.cb.setStyleSheet('')

    def cpLabelEnter(self, _):
        if not self.cb.isChecked():
            setColer = self.DEFAULT_COLOR.copy()
            setColer['border'] = self.DEFAULT_COLOR['hover']
            self.cb.setStyleSheet(
                self.CP_DEFAULT_STYLE.format(**setColer)
            )


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyApp()
    sys.exit(app.exec_())

or

If you use Qt Designer, After creating one Qwidget, make QCheckBox and QLabel inside Bring the QLabel to the front and make the QCheckBox deselected. And if you write it like the code below, it works perfectly!

import os
import sys

from PyQt5.uic import loadUi

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *


def resource_path(*relative_Path_AND_File):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = getattr(sys, '_MEIPASS', os.path.dirname(
            os.path.abspath(__file__)))
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, '/'.join(relative_Path_AND_File))


class MyApp_Define:
    cb: QCheckBox
    cb_label: QLabel


class MyApp(QMainWindow, MyApp_Define):
    ###### Define StyleSheet ######
    DEFAULT_COLOR = {
        'border': '#000000',
        'hover': '#29adff'
    }

    CP_DEFAULT_STYLE = '''
        QCheckBox::indicator:hover {{
            border: 1px solid {hover};
            background: white;
        }}
        QCheckBox::indicator {{
            border: 1px solid {border};
            background: white;
        }}
    '''

    CP_DEFAULT_STYLE_SET_VALUE = CP_DEFAULT_STYLE.format(**DEFAULT_COLOR)
    ################################

    def __init__(self):
        super().__init__()
        loadUi(resource_path("TEST.ui"), self)

        self.cb_label.installEventFilter(self)
        self.cb_label.leaveEvent = self.cbLabelLeave
        self.cb_label.mousePressEvent = self.cbLabelClick

    def eventFilter(self, source: QObject, event: QEvent):
        # 자동 종료 체크박스 안에 들어갈시
        if (
            source is self.cb_label and
            event.type() == QEvent.Type.MouseMove and
            not self.cb.isChecked()
        ):
            self.cbLabelEnter()

        return super().eventFilter(source, event)

    def cbLabelClick(self, _):
        self.cb.setStyleSheet('')

        self.cb.setChecked(
            not self.cb.isChecked()
        )

        if not self.cb.isChecked():
            self.cbLabelEnter()

    def cbLabelLeave(self, _):
        self.cb.setStyleSheet('')

    def cbLabelEnter(self, _=None):
        if not self.cb.isChecked():
            setColer = self.DEFAULT_COLOR.copy()
            setColer['border'] = self.DEFAULT_COLOR['hover']
            self.cb.setStyleSheet(
                self.CP_DEFAULT_STYLE.format(**setColer)
            )


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyApp()
    ex.show()
    sys.exit(app.exec_())

The image below is an example of QtDesigner.

enter image description here

Upvotes: 0

nmud
nmud

Reputation: 175

I don't know if you can access the label associated with the checkbox or not, but if you cannot, a hack would be to set the checkbox label with an empty string and use another QLabel where you can use setAlignment(Qt::AlignJustify) to adjust your text to both the right and left side.

But then I don't know if you consider this modify the checkbox itself and not just the alignement.

Upvotes: 3

Related Questions