QTableWidget Copy & Paste 사용해보기
개요
최근 QTableWidget Class를 사용하는 중,
Excel 파일 값 복사, QTableWidget에 붙여넣기
QTableWidget의 값 복사 Excel에 붙여넣기
를 할 필요가 생겼습니다.
혹시나 해서, 코드를 따로 작성하지 않고 빈 QTableWidget을 만들고 엑셀 데이터를 복사(Copy)해 붙여넣기(Paste) 해보니 역시나 동작하지 않습니다. 세상에 공짜는 없습니다. 😅
아마도 QWidget에서 Ctrl + C, V 키보드 이벤트 발생을 감지하고, 복사된 클립보드의 내용을 따로 처리해주는 코드가 필요할 것으로 예상됩니다.
간단하게 생각하고 바로 코드를 작성하기 진행하였지만 생각보다 복잡해 그 과정을 정리해 보았습니다.
목표
Copy data from Excel file to QTableWidget
Copy data from QTableWidget to Excel
소스코드
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTableWidget, QTableWidgetItem from PyQt5.QtCore import Qt import sys QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True) class Window(QWidget): def __init__(self): super().__init__() self.initUi() self.resize(400,600) def initUi(self): self.setWindowTitle('Ocean Coding School') self.tw = QTableWidget() row = 10 col = 3 self.tw.setRowCount(row) self.tw.setColumnCount(col) self.tw.cellClicked.connect(self.onCellClicked) vbox = QVBoxLayout() vbox.addWidget(self.tw) self.setLayout(vbox) self.sel_row = 0 self.sel_col = 0 def onCellClicked(self, r, c): #print(r, c) self.sel_row = r self.sel_col = c def keyPressEvent(self, e): super().keyPressEvent(e) if e.key() == Qt.Key_C and (e.modifiers() & Qt.ControlModifier): indexes = sorted(self.tw.selectedIndexes()) txt = '' col_num = indexes[-1].column() for idx in indexes: item = self.tw.item(idx.row(), idx.column()) txt += item.text() if idx.column() == col_num: txt += '\n' else: txt += '\t' QApplication.clipboard().setText(txt) elif e.key() == Qt.Key_V and (e.modifiers() & Qt.ControlModifier): cb = QApplication.clipboard() data = cb.text() lines = data.split('\n') for r, line in enumerate(lines): items = line.split('\t') for c, item in enumerate(items): self.tw.setItem(r+self.sel_row, c+self.sel_col, QTableWidgetItem(item)) if __name__ == '__main__': app = QApplication(sys.argv) w = Window() w.show() sys.exit(app.exec_())
위 코드는 QWidget 위에 빈 QTableWidget (10행 3열) 을 생성하고, Excel 데이터를 Copy & Paste 하도록 구성한 예제입니다.
일반적인 위젯 생성 코드는 설명을 생략하고
복사 & 붙여넣기 기능이 구현된 keyPressEvent() 함수만
설명하겠습니다.
참고로 해당 함수는 QWidget에서 상속받은 클래스에 오버라이딩된 함수이며, 키보드가 입력되면 함수가 호출됩니다.
[라인 37~48, Copy]
e.key() 함수를 사용하여 키보드 입력의 키를 확인.
(e.modifiers() & Qt.ControlModifier) 를 사용, Ctrl 키가 눌렸는지 확인.
self.tw.selectedIndexes() 함수를 사용하여 선택된 셀의 인덱스 목록을 얻기
sorted() 함수를 사용하여 인덱스 목록을 정렬.
for 루프를 사용하여 선택된 셀들의 텍스트를 txt 변수에 저장.
idx.column() 함수를 사용하여 셀의 열 번호를 얻고 if 문을 사용하여 마지막 열에 있는 셀인지 확인.
마지막 열에 있는 셀이면 \n 문자 추가 or 아니면 \t 문자를 추가
QApplication.clipboard().setText() 함수를 사용하여 클립보드에 텍스트를 설정
[라인 50~58, Paste]
e.key() 함수를 사용 키보드 입력 키를 확인.
(e.modifiers() & Qt.ControlModifier) 를 사용 Ctrl 키가 눌렸는지 확인.
QApplication.clipboard() 함수를 사용 클립보드에 액세스.
cb.text() 함수를 사용하여 클립보드의 텍스트를 가져오고, split() 으로 행별로 분리.
for 루프를 사용하여 각 행의 데이터를 처리.
line.split() 함수를 사용하여 행의 데이터를 열별로 분리.
이중 for 루프를 사용하여 각 열의 데이터를 처리.
r+self.sel_row 와 c+self.sel_col 을 사용하여 테이블 위젯에서 붙여넣을 위치를 계산
(self.self_row, col 에는 clicked cell 의 행,열 번호가 저장)
QTableWidgetItem() 클래스를 사용하여 셀에 텍스트를 설정.
개발환경
Windows 11 Pro 64bit, Visual Studio 2022 Community
Python 3.9.13 (64bit)
PyQt5 5.15.9
이상으로 모든 설명을 마칩니다.
감사합니다.
선생님 제가만든 웹브라우저에요! 조환이고 import sys
답글삭제from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication, QMainWindow, QLineEdit, QVBoxLayout, QWidget
from PyQt5.QtWebEngineWidgets import QWebEngineView
class WebBrowser(QMainWindow):
def __init__(self):
super().__init__()
# 주소 입력창 생성
self.address_bar = QLineEdit()
self.address_bar.returnPressed.connect(self.load_url)
# 웹뷰 생성
self.webview = QWebEngineView()
# 레이아웃 설정
layout = QVBoxLayout()
layout.addWidget(self.address_bar)
layout.addWidget(self.webview)
# 위젯 생성 및 설정
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
# 초기 URL 로드
self.load_url()
def load_url(self):
url = self.address_bar.text()
if not url.startswith("http"):
url = "https://www.google.com/search?q=" + url
self.webview.load(QUrl(url))
if __name__ == "__main__":
app = QApplication(sys.argv)
browser = WebBrowser()
browser.show()
sys.exit(app.exec_())
소스코드에요
조가아니고 저에요
답글삭제어 환아, 초등 4학년에게 많이 어려운 예제인데 잘 만들었네.
삭제아래는 선생님이 만들어서 올려둔 비슷한 예제야.
https://oceancoding.blogspot.com/2021/02/pdf.html
네!
삭제