본문 바로가기
프로그래밍 관련/PyQt

PyQt TableWidget (심화2) table pushbutton,combobox 등등 넣기

by 존버매니아.임베디드 개발자 2021. 12. 3.
반응형
  • 테이블의 셀에 PushButton, ComboBox,LineEdit 등등 넣기(기본)
  •         테이블의 특정 셀에 존재하는 아이템에 접근
  • 테이블의 셀에 PushButton 넣어서 사용하기(응용,심화)
  • Table에 유저가 데이터 입력할 때, 입력값 제한하기

테이블의 셀에 PushButton, ComboBox,LineEdit 등등 넣기(기본)

여태까지는 셀에 문자열 데이터만 넣어봤는데 셀에다 버튼 등도 넣을 수가 있다.

아래 메소드를 사용하면 된다.

def setCellWidget(self, row: int, column: int, widget: QWidget) -> None: ...

 

참고로, 테이블의 특정 셀에 존재하는 아이템에 접근 할 때 사용하는 메소드가 2개 있는데

def item(self, row: int, column: int) -> QTableWidgetItem: ...
def cellWidget(self, row: int, column: int) -> QWidget: ...

위 2가지이다.

근데 item 메소드는 return tye이 QTableWidgetItem 이라서

테이블의 셀에 QTableWidgetItem을 추가하지않고 예시와 같은 다른 Widget을 넣어놓으면 None을 return한다.

따라서, CellWidget 을 사용한 셀에 접근할때는 cellWidget 을 사용해서 접근해야한다.


테이블의 셀에 PushButton 넣어서 사용하기(응용,심화)

위 그림과 같은 상황에서 각 버튼을 눌렀을 때, 해당 버튼이 속해있는 행의 첫번째 데이터를 출력하고 싶다

어떻게 해야될까?

 

sender() 메소드를 알 필요가 있다.

sender() 메소드는 뭐냐면

슬롯이 실행될 때, 이 슬롯을 발생시킨 시그널을 누가보냈는지?를 알려주는 메소드이다.

 

우리가 PushButton을 사용할 때

self.btn1 = QPushButton("버튼")

self.btn1.clicked.connect(self.btn_fun)

이런식으로 많이 사용하는데,

저 버튼을 클릭하면 btn_fun 이라는 메소드가 실행될 것이다.

 

btn_fun 메소드 안에서 self.sender() 메소드를 호출하면

btn_fun을 호출한 버튼 정보를 return 하는 것이다.

위 그림을 보면,

btn1, bnt2 라고 서로 다른 버튼 2개를 만들었다.

하지만 clicked 이벤트에 연길시킨 메소드는 동일한 메소드이다. (btn_fun)

 

btn_fun 메소드에서 self.sender() 를 호출한 결과값을 print 하도록 하였다.

 

이제 우리는 sender() 메소드를 통해서

버튼을 클릭했을 때, 이게 어떤 버튼에 의해서 클릭 된 것인지를 알 수 있다.

 

한편, QPushButton 클래스에는 아래와 같은 객체가 있다.

def pos(self) -> QtCore.QPointF: ...

이게 뭐냐면 해당 버튼이 프로그램상에서 위치한 좌표값을 리턴해주는 것이다.

 

한편,

TableView Class에는

def indexAt(self, p: QtCore.QPoint) -> QtCore.QModelIndex: ...

라는 메소드가 있는데, 이게 뭐냐면

특정한 좌표값을 줬을 때, 그 좌표값에 해당하는 셀 정보를 리턴해주는 것이다.

 

QPushButton 클래스의 pos 메소드와

TableView 클래스의 indexAt 메소드를 섞어서 쓰면

앞의 예시의 테이블에서 버튼을 눌렀을 때,

해당 버튼이 속한 테이블의 row 정보를 얻어 올 수 있게 되는 것이다.

 

 

아래 예시 코드 참고

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

class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setupUI()

    def setupUI(self):
        self.setGeometry(800, 200, 800, 300)       

        self.ta1 = QTableWidget(self)
        self.ta1.resize(400, 500)
        self.ta1.setColumnCount(3)       

        table_column=["첫번째 열" , "두번째 열" , "Third 열"]
        self.ta1.setHorizontalHeaderLabels(table_column)      
        
        #행 2개 추가
        self.ta1.setRowCount(2)
        
        #추가된 행에 데이터 채워넣음
        self.ta1.setItem(0, 0, QTableWidgetItem("(0,0)"))
        self.ta1.setItem(0, 1, QTableWidgetItem("(0,1)"))
        self.ta1.setItem(1, 0, QTableWidgetItem("(1,0)"))
        self.ta1.setItem(1, 1, QTableWidgetItem("(1,1)"))

        self.btn1 = QPushButton("버튼")
        self.btn2 = QPushButton("버튼")

        self.btn1.clicked.connect(self.btn_fun)
        self.btn2.clicked.connect(self.btn_fun)

        self.ta1.setCellWidget(0,2,self.btn1)
        self.ta1.setCellWidget(1,2,self.btn2)
    
    def btn_fun(self):
        button = self.sender()

        item = self.ta1.indexAt(button.pos())        
        print( self.ta1.item( item.row(),0 ).text()  )

                
if __name__ == "__main__":
    app = QApplication(sys.argv)
    mywindow = MyWindow()
    mywindow.show()
    app.exec_()

Table에 유저가 데이터 입력할 때, 입력값 제한하기

Table의 셀이 Edit 가능할 경우, 유저가 직접 키보드로 값을 입력해서 넣을 수 있다.

근데 이 때 여기에 입력되는 값을 제한하고 싶을 수 있다.

(ex : 숫자만 쓰게 한다던지..)

 

구글링 검색 결과 delegate 라는 것을 사용하는 것이 정석적인 해결책 같다.

근데 delegate가 뭔지 잘 모르겠고

일단 간단한 해결책으로 QlineEdit를 이용하는 방법을 생각해 볼 수 있다.

QLineEdit를 이용하면 입력값을 제한할 수 있으므로,

우리는 setCellWidget 메소드를 사용해서

셀에다가 입력범위가 제한된 QLineEdit를 넣는식으로 해결 할 수 있다.

QLineEdit 관련해서는 다른 글 참조

2021.12.04 - [프로그래밍 관련/PyQt] - PyQt QLineEdit 입력 제한하기 (숫자만 넣기,문자만 넣기 등등)

반응형