개발/PyQt&Python

PyQt tablewidget에 checkbox 추가 / 정렬되게 만들기

알 수 없는 사용자 2022. 11. 11.
반응형

테이블위젯에 체크박스를 추가하고 체크 유무에 따른 정렬기능까지 추가한 소스입니다.

class checkboxItem(QTableWidgetItem):
    def __init__(self):
        super().__init__()
    #정렬시 발생 이벤트
    def __lt__(self, other):
        if self.checkState() == other.checkState() or self.checkState() == Qt.Checked:
            return False
        return True

QTableWidgetItem은 텍스트로 비교를 수행하기 때문에 새로운 checkboxItem을 만들어 __lt__에 비교 이벤트를 넣었습니다.

 

item = checkboxItem()
item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Checked)
item.setData(Qt.UserRole, item.checkState())

self.tableWidget.setItem(idx, 0, item)

새로운 아이템을 할당하고 체크상태를 넣어주었습니다.

이 소스에서는 기본값이 체크된 상태이지만 체크가 되지 않은 상태를 기본값으로 넣고 싶으면 item.setCheckState(QtCore.Qt.Unchecked)로 넣어주면 됩니다.

 

#체크박스 클릭이벤트 추가
self.tableWidget.cellChanged.connect(self.onCellChanged)

#체크박스 클릭 이벤트
def onCellChanged(self, row, column):
    item = self.tableWidget.item(row, column)
    lastState = item.data(Qt.UserRole)
    currentState = item.checkState()
    if currentState != lastState:
        if currentState == QtCore.Qt.Checked:
            print("체크됨")
        else:
            print("체크 해제")
        item.setData(Qt.UserRole, currentState)

체크박스가 클릭되면 이벤트가 발생합니다. 정확하게는 셀이 바뀌었을 때 이벤트가 동작하는데, 체크박스 값이 바뀌면 셀이 바뀌었다고 인식되어 onCellChanged 이벤트가 발생합니다.

체크/체크해제시 동작은 print("체크됨") / print("체크 해제") 부분에 넣어주시면 됩니다.

 

#셀 정렬기능 해제
self.tableWidget.setSortingEnabled(False)

#헤더 클릭시 정렬이벤트 추가
header.sectionClicked.connect(self.headerSorting)

#헤더 클릭시 정렬이벤트
def headerSorting(self):
    self.tableWidget.setSortingEnabled(True)
    self.tableWidget.setSortingEnabled(False)

테이블의 기본 정렬기능을 해제하고 헤더를 클릭할 때만 정렬이 되게 설정했습니다.

기본 정렬기능을 켜게 되면 체크박스를 누를 때마다 데이터 정렬이 바뀌기 때문에 보기 불편합니다.

 

전체 소스입니다.

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

class checkboxItem(QTableWidgetItem):
    def __init__(self):
        super().__init__()
    #정렬시 발생 이벤트
    def __lt__(self, other):
        if self.checkState() == other.checkState() or self.checkState() == Qt.Checked:
            return False
        return True

class MyApp(QWidget):

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

    def initUI(self):
        layout = QVBoxLayout()

        self.tableWidget = QTableWidget()
        self.tableWidget.setColumnCount(2)
        self.tableWidget.setRowCount(3)
        self.tableWidget.setHorizontalHeaderLabels(["col1", "col2"])
        self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)

        for idx in range(3):
            #체크박스 넣는 부분
            item = checkboxItem()
            item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
            item.setCheckState(QtCore.Qt.Checked)
            item.setData(Qt.UserRole, item.checkState())

            self.tableWidget.setItem(idx, 0, item)
            self.tableWidget.setItem(idx, 1, QTableWidgetItem(str(idx)))
        
        #체크박스 클릭이벤트 추가
        self.tableWidget.cellChanged.connect(self.onCellChanged)
        #셀 정렬기능 해제
        self.tableWidget.setSortingEnabled(False)

        header = self.tableWidget.horizontalHeader()
        #헤더 클릭시 정렬이벤트 추가
        header.sectionClicked.connect(self.headerSorting)

        layout.addWidget(self.tableWidget)

        self.setLayout(layout)
        self.setWindowTitle('MyApp')
        self.resize(300, 300)
        self.show()
    #헤더 클릭시 정렬이벤트
    def headerSorting(self):
        self.tableWidget.setSortingEnabled(True)
        self.tableWidget.setSortingEnabled(False)
    #체크박스 클릭 이벤트
    def onCellChanged(self, row, column):
        item = self.tableWidget.item(row, column)
        lastState = item.data(Qt.UserRole)
        currentState = item.checkState()
        if currentState != lastState:
            if currentState == QtCore.Qt.Checked:
                print("체크됨")
            else:
                print("체크 해제")
            item.setData(Qt.UserRole, currentState)


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

 

반응형

댓글

💲 추천 글