참고 ; http://doc.qt.io/qt-5/qwidget.html#mouseTracking-prop
http://doc.qt.io/qt-5/qwidget.html#mouseMoveEvent
http://doc.qt.io/qt-5/qmouseevent.html
def setupUi(self, mainWindow):
가계부 메인 UI
def table_to_csv(self, cnt_row, date, inout, category, money):
테이블에 insert될 때 마다 csv에 한줄 한줄 저장
def csv_insertItem(self, date, inout, category, money):
def csv_load(self):
이전에 저장된 csv file load
def insertItem(self, date, inout, category, money):
수입 지출에 대한 tableInsert
def setTableWidgetData(self):
tableWidget dataInit
def inputInc(self):
지출금액 기입을 위한 버튼액션
def delList(self):
수입/지출 목록 삭제를 위한 버튼액션
def setupUi(self, mainWindow):
expCat = ['식비', '주거', '통신', '의복', '건강', '교통', '오락', '세금', '기타']
incCat = ['주수입', '부수입', '기타수입']
mainWindow.setObjectName("mainWindow")
mainWindow.setWindowTitle("가계부")
mainWindow.resize(804, 600)
mainWindow.setMouseTracking(False)
self.centralwidget = QtWidgets.QWidget(mainWindow)
self.centralwidget.setObjectName("centralwidget")
두개의 파라미터를 받는다. (self,mainwindow)
expCat, inCat 변수는 사용자가 입력할 때 정보값을 제공한다.
mainwindow는 객체로 정의되고 밑에 init에 정의되어있다.
mainWindow.setObjectName 객체에 대한 메서드를 실행한다.
부모를 mainWindow로 하는 Qtwidgets모듈에서 Qwidget 클래스를 불러온다. self.centralwidget은 QtWidgets.QWidget의 인스턴스를 참조하는 변수로, 이를 통해 QWidget의 속성과 메서드를 사용할 수 있다.
self.centralwidget은 클래스 내에서 정의된 인스턴스 변수로, 메인 창의 중앙 위젯을 참조
self.centralwidget.setObjectName("centralwidget") 줄은 중앙 위젯의 객체 이름을 "centralwidget"으로 설정하여 애플리케이션에서 위젯을 식별
# 달력 UI
self.calendarWidget = QtWidgets.QCalendarWidget(self.centralwidget)
self.calendarWidget.setEnabled(True)
self.calendarWidget.setGeometry(QtCore.QRect(10, 10, 344, 236))
self.calendarWidget.setObjectName("calendarWidget")
QtWidgets.QCalendarWidget 클래스의 인스턴스인 calendarWidget 객체를 생성합니다. 이 위젯은 self.centralwidget을 부모 위젯으로 설정하여 중앙 위젯에 속하도록 한다.
self.centralwidget은 부모 위젯으로 사용될 QtWidgets.QWidget 인스턴스다. 따라서 QtWidgets.QCalendarWidget(self.centralwidget) 코드는 self.centralwidget을 부모로 하는 QtWidgets.QCalendarWidget 인스턴스를 생성한다.
이렇게 생성된 QCalendarWidget 인스턴스는 self.calendarWidget 변수에 할당되어 해당 변수를 통해 이후에 위젯을 조작하고 설정할 수 있습니다.
self.calendarWidget.setEnabled(True): calendarWidget 위젯을 활성화합니다. setEnabled(True)를 호출하여 사용자 상호작용을 가능하게한다. 다시 말하면, 이 코드는 QtWidgets.QCalendarWidget.setEnabled(True)를 의미한다.
[setEnabled은 버튼을 활성화 시켜주는 인스턴스다.]
self.calendarWidget.setGeometry(QtCore.QRect(10, 10, 344, 236)): calendarWidget 위젯의 위치와 크기를 설정 + QtCore.QRect 클래스의 인스턴스를 생성하여 (10, 10) 위치에서 시작하여 가로 344픽셀, 세로 236픽셀의 크기를 가진다. [setGeometry는 출력할 위치를 결정]
# 수입 UI
self.incLb = QtWidgets.QLabel(self.centralwidget)
self.incLb.setGeometry(QtCore.QRect(20, 250, 41, 41))
self.incLb.setObjectName("incLb")
self.incLb.setText("수입")
self.incComBx = QtWidgets.QComboBox(self.centralwidget)
self.incComBx.setGeometry(QtCore.QRect(30, 290, 71, 41))
self.incComBx.setObjectName("incComBx")
for value in incCat:
self.incComBx.addItem(value)
self.incLine = QtWidgets.QLineEdit(self.centralwidget)
self.incLine.setGeometry(QtCore.QRect(120, 290, 131, 41))
self.incLine.setValidator(QIntValidator(0, 9999999))
self.incLine.setObjectName("incLine")
self.won1 = QtWidgets.QLabel(self.centralwidget)
self.won1.setGeometry(QtCore.QRect(260, 300, 21, 16))
self.won1.setObjectName("won1")
self.won1.setText("\\")
self.incBtn = QtWidgets.QPushButton(self.centralwidget)
self.incBtn.setGeometry(QtCore.QRect(290, 290, 61, 41))
self.incBtn.clicked.connect(self.inputInc)
self.incBtn.setObjectName("incBtn")
self.incBtn.setText("기입")
self.incLb = QtWidgets.QLabel(self.centralwidget): QtWidgets.QLabel 클래스의 인스턴스인 incLb 객체를 생성
QtWidgets모듈에 있는 QLabel 클래스 참조 -> incLb 객체생성
이는 텍스트를 표시하는 레이블 위젯을 나타냄. self.centralwidget을 부모 위젯으로 설정하여 중앙 위젯에 설정
self.incLb.setGeometry(QtCore.QRect(20, 250, 41, 41)): incLb 레이블 위젯의 위치와 크기를 설정 (20, 250) 위치에서 시작하여 가로 41픽셀, 세로 41픽셀의 크기를 설정
self.incLb.setObjectName("incLb"): incLb 레이블 위젯의 객체 이름을 "incLb"로 설정
self.incLb.setText("수입"): incLb 레이블 위젯에 텍스트를 설정하여 "수입"이라고 표시
self.incComBx = QtWidgets.QComboBox(self.centralwidget)
self.incComBx.setGeometry(QtCore.QRect(30, 290, 71, 41))
self.incComBx.setObjectName("incComBx")
for value in incCat:
self.incComBx.addItem(value)
self.incComBx = QtWidgets.QComboBox(self.centralwidget): QtWidgets.QComboBox 클래스의 인스턴스인 incComBx 객체를 생성 이는 선택할 수 있는 드롭다운 목록을 나타내는 콤보 박스 위잿 self.centralwidget을 부모 위젯으로 설정하여 중앙 위젯에 속함
[QComboBox는 작은 공간을 차지하면서, 여러 옵션들을 제공하고 그 중 하나의 옵션을 선택할 수 있도록 해주는 위젯]
self.incComBx.setGeometry(QtCore.QRect(30, 290, 71, 41)): incComBx 콤보 박스 위젯의 위치와 크기를 설정
self.incComBx.setObjectName("incComBx"): incComBx 콤보 박스 위젯의 객체 이름을 "incComBx"로 설정
self.incLine = QtWidgets.QLineEdit(self.centralwidget)
self.incLine.setGeometry(QtCore.QRect(120, 290, 131, 41))
self.incLine.setValidator(QIntValidator(0, 9999999))
self.incLine.setObjectName("incLine")
self.incLine = QtWidgets.QLineEdit(self.centralwidget): QtWidgets.QLineEdit 클래스의 인스턴스인 incLine 객체를 생성합니다. 이는 사용자로부터 텍스트 입력을 받을 수 있는 한 줄 텍스트 상자 위젯 [QLineEdit이란, 한줄짜리 글자를 입력받을 수 있는 입력위젯]
QtWidgets모듈에 있는 QLineEdit 클래스 참조하여 incLine에 할당
self.incLine.setValidator(QIntValidator(0, 9999999)): incLine 텍스트 상자 위젯에 입력되는 값의 유효성을 검사하기 위해 QIntValidator를 설정 사용자는 0에서 9999999 사이의 정수만 입력 가능
Qt는 QIntValidator, QDoubleValidor, QRegExpValidator 등의 3 종류의 밸리데이터 클래스가 있음. 사용하는 방법은 밸리데이터를 생성한 후 QLineEdit나 QComboBox의 setValidator(validator) 함수를 호출해 주면 된다.
QIntValidator와 QDoubleValidator는 생성자 또는 setRange() 함수로 최소, 최대, 소수점(QDoubleValidator인 경우에만)을 동시에 설정
self.incLine.setObjectName("incLine"): incLine 텍스트 상자 위젯의 객체 이름을 "incLine"으로 설정
self.incBtn = QtWidgets.QPushButton(self.centralwidget)
self.incBtn.setGeometry(QtCore.QRect(290, 290, 61, 41))
self.incBtn.clicked.connect(self.inputInc)
self.incBtn.setObjectName("incBtn")
self.incBtn.setText("기입")
# 수입금액 기입을 위한 버튼액션
def inputInc(self):
date = self.calendarWidget.selectedDate()
date = str(date.toString())
money = str(self.incLine.text()) # 수입금액
category = str(self.incComBx.currentText()) # 수입 분류
current_inc = int(str(self.totalIncLb.text()).split(' ')[2])
print(current_inc)
current_inc += int(money)
self.totalIncLb.setText("총 수입: " + str(current_inc))
self.insertItem(date, "수입", category, money)
date = self.calendarWidget.selectedDate(): calendarWidget 위젯에서 선택된 날짜를 가져와서 date 변수에 저장
self.calendarWidget는 QCalendarWidget 클래스의 인스턴스인 calendarWidget 객체를 나타냅니다. selectedDate는 QCalendarWidget 클래스에서 제공되는 메서드
date = str(date.toString()): date 변수를 문자열로 변환하여 저장
date.toString()은 PyQt에서 사용되는 메서드로, QDate 객체인 date의 문자열 표현을 반환 그 후에 str() 함수를 사용하여 PyQt에서 반환된 문자열을 파이썬의 문자열로 변환
# 지출 UI
self.expLb = QtWidgets.QLabel(self.centralwidget)
self.expLb.setGeometry(QtCore.QRect(20, 350, 41, 41))
self.expLb.setObjectName("expLb")
self.expLb.setText("지출")
self.expComBx = QtWidgets.QComboBox(self.centralwidget)
self.expComBx.setGeometry(QtCore.QRect(30, 390, 71, 41))
self.expComBx.setObjectName("expComBx")
for value in expCat:
self.expComBx.addItem(value)
self.expLine = QtWidgets.QLineEdit(self.centralwidget)
self.expLine.setGeometry(QtCore.QRect(120, 390, 131, 41))
self.expLine.setValidator(QIntValidator(0, 9999999))
self.expLine.setObjectName("expLine")
self.won2 = QtWidgets.QLabel(self.centralwidget)
self.won2.setGeometry(QtCore.QRect(260, 400, 21, 16))
self.won2.setObjectName("won2")
self.won2.setText("\\")
self.expBtn = QtWidgets.QPushButton(self.centralwidget)
self.expBtn.setGeometry(QtCore.QRect(290, 390, 61, 41))
self.expBtn.clicked.connect(self.inputExp)
self.expBtn.setObjectName("expBtn")
self.expBtn.setText("기입")
self.explainLb = QtWidgets.QLabel(self.centralwidget)
self.explainLb.setGeometry(QtCore.QRect(20, 450, 101, 16))
self.explainLb.setObjectName("explainLb")
self.explainLb.setText("세부 설명")
self.expText = QtWidgets.QTextEdit(self.centralwidget)
self.expText.setGeometry(QtCore.QRect(30, 480, 321, 91))
self.expText.setObjectName("expText")
# 이번 달 소비, 지출 금액 합계 UI
self.totalLb = QtWidgets.QLabel(self.centralwidget)
self.totalLb.setGeometry(QtCore.QRect(380, 10, 170, 16))
self.totalLb.setObjectName("totalLb")
self.totalLb.setText("이번 달 소비 / 지출 합계")
self.totalExpLb = QtWidgets.QLabel(self.centralwidget)
self.totalExpLb.setGeometry(QtCore.QRect(410, 40, 250, 16))
self.totalExpLb.setObjectName("totalExpLb")
self.totalExpLb.setText("총 지출 ") # 지출 총 합 뒤에 + 로 붙이기
self.totalIncLb = QtWidgets.QLabel(self.centralwidget)
self.totalIncLb.setGeometry(QtCore.QRect(410, 140, 250, 16))
self.totalIncLb.setObjectName("totalIncLb")
self.totalIncLb.setText("총 수입 ") # 수입 총 합 뒤에 + 로 붙이기
# 소비, 지출 리스트 UI
self.listLb = QtWidgets.QLabel(self.centralwidget)
self.listLb.setGeometry(QtCore.QRect(380, 260, 130, 16))
self.listLb.setObjectName("listLb")
self.listLb.setText("수입 / 지출 리스트")
self.delBtn = QtWidgets.QPushButton(self.centralwidget)
self.delBtn.setGeometry(QtCore.QRect(710, 250, 61, 41))
self.delBtn.clicked.connect(self.delList)
self.delBtn.setObjectName("expBtn")
self.delBtn.setText("삭제")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(390, 290, 381, 281))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setRowCount(1)
self.tableWidget.setColumnCount(4)
self.setTableWidgetData()
mainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(mainWindow)
self.statusbar.setObjectName("statusbar")
mainWindow.setStatusBar(self.statusbar)
QtCore.QMetaObject.connectSlotsByName(mainWindow)
self.expComBx = QtWidgets.QComboBox(self.centralwidget)
self.expComBx.setGeometry(QtCore.QRect(30, 390, 71, 41))
self.expComBx.setObjectName("expComBx")
for value in expCat:
self.expComBx.addItem(value)
self.expLine = QtWidgets.QLineEdit(self.centralwidget)
self.expLine.setGeometry(QtCore.QRect(120, 390, 131, 41))
self.expLine.setValidator(QIntValidator(0, 9999999))
self.expLine.setObjectName("expLine")
self.won2 = QtWidgets.QLabel(self.centralwidget)
self.won2.setGeometry(QtCore.QRect(260, 400, 21, 16))
self.won2.setObjectName("won2")
self.won2.setText("\\")
self.expBtn = QtWidgets.QPushButton(self.centralwidget)
self.expBtn.setGeometry(QtCore.QRect(290, 390, 61, 41))
self.expBtn.clicked.connect(self.inputExp)
self.expBtn.setObjectName("expBtn")
self.expBtn.setText("기입")
self.explainLb = QtWidgets.QLabel(self.centralwidget)
self.explainLb.setGeometry(QtCore.QRect(20, 450, 101, 16))
self.explainLb.setObjectName("explainLb")
self.explainLb.setText("세부 설명")
self.expText = QtWidgets.QTextEdit(self.centralwidget)
self.expText.setGeometry(QtCore.QRect(30, 480, 321, 91))
self.expText.setObjectName("expText")
self.totalLb = QtWidgets.QLabel(self.centralwidget)
self.totalLb.setGeometry(QtCore.QRect(380, 10, 170, 16))
self.totalLb.setObjectName("totalLb")
self.totalLb.setText("이번 달 소비 / 지출 합계")
self.totalExpLb = QtWidgets.QLabel(self.centralwidget)
self.totalExpLb.setGeometry(QtCore.QRect(410, 40, 250, 16))
self.totalExpLb.setObjectName("totalExpLb")
self.totalExpLb.setText("총 지출 ") # 지출 총 합 뒤에 + 로 붙이기
self.totalIncLb = QtWidgets.QLabel(self.centralwidget)
self.totalIncLb.setGeometry(QtCore.QRect(410, 140, 250, 16))
self.totalIncLb.setObjectName("totalIncLb")
self.totalIncLb.setText("총 수입 ") # 수입 총 합 뒤에 + 로 붙이기
위 동작 원리와 동일하다.
self.listLb = QtWidgets.QLabel(self.centralwidget)
self.listLb.setGeometry(QtCore.QRect(380, 260, 130, 16))
self.listLb.setObjectName("listLb")
self.listLb.setText("수입 / 지출 리스트")
self.delBtn = QtWidgets.QPushButton(self.centralwidget)
self.delBtn.setGeometry(QtCore.QRect(710, 250, 61, 41))
self.delBtn.clicked.connect(self.delList)
self.delBtn.setObjectName("expBtn")
self.delBtn.setText("삭제")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(390, 290, 381, 281))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setRowCount(1)
self.tableWidget.setColumnCount(4)
self.setTableWidgetData()
mainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(mainWindow)
self.statusbar.setObjectName("statusbar")
mainWindow.setStatusBar(self.statusbar)
QtCore.QMetaObject.connectSlotsByName(mainWindow)
QtWidgets.QTableWidget(self.centralwidget): QtWidgets.QTableWidget 클래스의 인스턴스인 tableWidget 객체를 생성
self.tableWidget.setGeometry(QtCore.QRect(390, 290, 381, 281)): tableWidget 테이블 위젯의 위치와 크기를 설정
self.tableWidget.setObjectName("tableWidget"): tableWidget 테이블 위젯의 객체 이름을 "tableWidget"으로 설정
self.tableWidget.setRowCount(1): tableWidget 테이블 위젯의 행(row) 개수를 1로 설정
self.tableWidget.setColumnCount(4): tableWidget 테이블 위젯의 열(column) 개수를 4로 설정
self.setTableWidgetData(): setTableWidgetData() 메서드를 호출하여 테이블 위젯의 초기 데이터를 설정
#tableWidget dataInit
def setTableWidgetData(self):
column_headers = ['날짜', '수입/지출', '카테고리', '금액']
self.tableWidget.setHorizontalHeaderLabels(column_headers)
self.tableWidget.resizeColumnsToContents()
self.tableWidget.resizeRowsToContents()
column_headers = ['날짜', '수입/지출', '카테고리', '금액']: 테이블 위젯의 열 헤더에 해당하는 문자열 리스트를 생성
self.tableWidget.setHorizontalHeaderLabels(column_headers): column_headers
tableWidget 객체의 setHorizontalHeaderLabels() 메서드를 호출하여 테이블 위젯의 수평 방향 헤더에 column_headers 리스트에 저장된 열 헤더를 설정
self.tableWidget.resizeColumnsToContents(): 테이블 위젯의 열 너비를 열에 맞게 자동 조정
self.tableWidget.resizeRowsToContents(): 테이블 위젯의 행 높이를 행에 맞게 자동 조정
QtCore.QMetaObject.connectSlotsByName(mainWindow)
[저장된 csv file load]
# 이전에 저장된 csv file load
def csv_load(self):
f = open('household_ledger.csv', 'r', encoding = 'utf-8')
rdr = csv.reader(f)
income = 0
outcome = 0
for line in rdr:
self.csv_insertItem(line[1], line[2], line[3], line[4])
if '수입' in line[2]:
income += int(line[4])
elif '지출' in line[2]:
outcome += int(line[4])
self.totalIncLb.setText("총 수입: " + str(income))
self.totalExpLb.setText("총 지출: " + str(outcome))
f.close()
#테이블에 insert될 때 마다 csv에 한줄 한줄 저장
def table_to_csv(self, cnt_row, date, inout, category, money):
f = open("household_ledger.csv", 'a', encoding = "utf-8", newline = '')
wr = csv.writer(f)
wr.writerow([cnt_row, date, inout, category, money])
f.close()
f = open('household_ledger.csv', 'r', encoding='utf-8'): 'household_ledger.csv' 파일을 읽기 모드('r')로 열고 파일 객체 + 파일은 UTF-8 인코딩으로 처리
rdr = csv.reader(f): csv.reader() 함수를 사용하여 파일 객체를 CSV 리더 객체로 변환
income = 0 및 outcome = 0: 수입과 지출을 계산하기 위한 변수를 초기화
for line in rdr:: rdr은 csv.reader 객체로 생성된 것으로, 이를 반복문으로 순회하면서 CSV 파일의 각 줄을 처리한다.
self.csv_insertItem(line[1], line[2], line[3], line[4]): csv_insertItem 메서드를 호출하여 테이블 위젯에 새로운 행을 추가합니다. line[1], line[2], line[3], line[4]은 CSV 파일의 해당 줄에서 각 열의 데이터를 나타냅니다. 이 데이터를 인자로 전달하여 새로운 행을 추가하는 작업을 수행한다.
if '수입' in line[2]:: line[2]는 CSV 파일의 해당 줄에서 세 번째 열의 데이터를 나타냅니다. 이 부분에서 '수입'이라는 텍스트가 포함되어 있는지 확인합니다.
income += int(line[4]): '수입'이 포함되어 있다면, line[4]를 정수로 변환하여 income 변수에 더합니다. 이는 수입의 총합을 계산하기 위한 작업 + 지출도 동일하다.
self.totalIncLb.setText("총 수입: " + str(income)): 화면에 총 수입을 나타내는 레이블에 계산된 income 값을 설정
self.totalExpLb.setText("총 지출: " + str(outcome)): 화면에 총 지출을 나타내는 레이블에 계산된 outcome 값을 설정
CSV 리더 객체는 csv.reader() 함수에 의해 생성되는 객체다. 이 객체는 CSV 파일을 행 단위로 읽을 수 있는 기능을 제공한다. CSV 파일은 쉼표(,)로 구분된 데이터를 포함하고 있는 파일 형식이다.
CSV 리더 객체를 생성하기 위해서는 파일 객체가 필요합니다. 파일 객체는 open() 함수를 사용하여 파일을 열고 반환된 객체입니다. 이 파일 객체를 csv.reader() 함수에 전달하여 CSV 리더 객체를 생성합니다. CSV 리더 객체는 파일을 읽어 각 행을 리스트로 반환하며, 이를 반복하여 파일의 내용을 처리할 수 있습니다.
각 행은 CSV 파일의 한 줄에 해당하며, 리스트 내의 요소는 해당 줄의 데이터 열을 나타낸다.
테이블에 insert될 때 마다 csv에 한줄 한줄 저장
#테이블에 insert될 때 마다 csv에 한줄 한줄 저장
def table_to_csv(self, cnt_row, date, inout, category, money):
f = open("household_ledger.csv", 'a', encoding = "utf-8", newline = '')
wr = csv.writer(f)
wr.writerow([cnt_row, date, inout, category, money])
f.close()
"household_ledger.csv" 파일을 열고 파일 객체 f를 생성합니다. 'a' 모드는 파일을 이어쓰기 모드로 열기 위한 것입니다.
wr = csv.writer(f): csv.writer 객체 wr을 생성합니다. 이 객체를 사용하여 CSV 파일에 데이터를 작성할 수 있습니다.
wr.writerow([cnt_row, date, inout, category, money]): wr.writerow() 메서드를 사용하여 리스트 형태의 데이터를 CSV 파일의 한 줄로 작성합니다.
[cnt_row, date, inout, category, money]는 CSV 파일에 저장될 데이터입니다. cnt_row, date, inout, category, money는 각각 테이블 위젯에서 가져온 값입니다. 이를 한 줄로 만들어서 CSV 파일에 저장
table_to_csv() 메서드는 테이블 위젯에 행이 추가될 때마다 해당 행을 CSV 파일에 저장하는 역할
[테이블 위젯에 새로운 행을 추가하고 데이터를 설정]
def csv_insertItem(self, date, inout, category, money):
cnt_row = self.tableWidget.rowCount()
self.tableWidget.setItem(cnt_row - 1, 0, QtWidgets.QTableWidgetItem(date))
self.tableWidget.setItem(cnt_row - 1, 1, QtWidgets.QTableWidgetItem(inout))
self.tableWidget.setItem(cnt_row - 1, 2, QtWidgets.QTableWidgetItem(category))
self.tableWidget.setItem(cnt_row - 1, 3, QtWidgets.QTableWidgetItem(money))
self.tableWidget.setRowCount(cnt_row + 1)
self.tableWidget.resizeColumnsToContents()
self.tableWidget.resizeRowsToContents()
#수입 지출에 대한 tableInsert
def insertItem(self, date, inout, category, money):
cnt_row = self.tableWidget.rowCount()
if "수입" in inout:
self.table_to_csv(cnt_row, date, inout, category, money)
self.tableWidget.setItem(cnt_row - 1, 0, QtWidgets.QTableWidgetItem(date))
self.tableWidget.setItem(cnt_row - 1, 1, QtWidgets.QTableWidgetItem("수입"))
self.tableWidget.setItem(cnt_row - 1, 2, QtWidgets.QTableWidgetItem(category))
self.tableWidget.setItem(cnt_row - 1, 3, QtWidgets.QTableWidgetItem(money))
self.tableWidget.setRowCount(cnt_row + 1)
elif "지출" in inout:
self.table_to_csv(cnt_row, date, inout, category, money)
self.tableWidget.setItem(cnt_row - 1, 0, QtWidgets.QTableWidgetItem(date))
self.tableWidget.setItem(cnt_row - 1, 1, QtWidgets.QTableWidgetItem("지출"))
self.tableWidget.setItem(cnt_row - 1, 2, QtWidgets.QTableWidgetItem(category))
self.tableWidget.setItem(cnt_row - 1, 3, QtWidgets.QTableWidgetItem(money))
self.tableWidget.setRowCount(cnt_row + 1)
self.tableWidget.resizeColumnsToContents()
self.tableWidget.resizeRowsToContents()
csv_insertItem() 메서드는 테이블 위젯에 새로운 행을 추가하고 데이터를 설정하는 역할 + 이 메서드는 date, inout, category, money 매개변수다.
cnt_row = self.tableWidget.rowCount(): rowCount() 메서드를 사용하여 현재 테이블 위젯의 열 개수를 가져옵니다. cnt_row 변수에 저장
inout 값이 "수입"인지 "지출"인지 확인
def insertItem(self, date, inout, category, money):
cnt_row = self.tableWidget.rowCount()
if "수입" in inout:
self.table_to_csv(cnt_row, date, inout, category, money)
self.tableWidget.setItem(cnt_row - 1, 0, QtWidgets.QTableWidgetItem(date))
self.tableWidget.setItem(cnt_row - 1, 1, QtWidgets.QTableWidgetItem("수입"))
self.tableWidget.setItem(cnt_row - 1, 2, QtWidgets.QTableWidgetItem(category))
self.tableWidget.setItem(cnt_row - 1, 3, QtWidgets.QTableWidgetItem(money))
self.tableWidget.setRowCount(cnt_row + 1)
elif "지출" in inout:
self.table_to_csv(cnt_row, date, inout, category, money)
self.tableWidget.setItem(cnt_row - 1, 0, QtWidgets.QTableWidgetItem(date))
self.tableWidget.setItem(cnt_row - 1, 1, QtWidgets.QTableWidgetItem("지출"))
self.tableWidget.setItem(cnt_row - 1, 2, QtWidgets.QTableWidgetItem(category))
self.tableWidget.setItem(cnt_row - 1, 3, QtWidgets.QTableWidgetItem(money))
self.tableWidget.setRowCount(cnt_row + 1)
self.tableWidget.resizeColumnsToContents()
self.tableWidget.resizeRowsToContents()
self.table_to_csv(cnt_row, date, inout, category, money): table_to_csv() 메서드를 호출하여 CSV 파일에 해당 행을 저장
self.tableWidget.setRowCount(cnt_row + 1): 테이블 위젯의 행 개수를 증가시킨다.
self.tableWidget.resizeColumnsToContents(): 테이블 위젯의 열 너비를 콘텐츠에 맞게 조정
self.tableWidget.resizeRowsToContents(): 테이블 위젯의 행 높이를 콘텐츠에 맞게 조정
셀에 날짜, 지출/수입 표시, 카테고리, 금액을 설정하여 테이블에 데이터를 표시하는 역할
#tableWidget dataInit
def setTableWidgetData(self):
column_headers = ['날짜', '수입/지출', '카테고리', '금액']
self.tableWidget.setHorizontalHeaderLabels(column_headers)
self.tableWidget.resizeColumnsToContents()
self.tableWidget.resizeRowsToContents()
수입금액 기입을 위한 버튼액션
# 수입금액 기입을 위한 버튼액션
def inputInc(self):
date = self.calendarWidget.selectedDate()
date = str(date.toString())
money = str(self.incLine.text()) # 수입금액
category = str(self.incComBx.currentText()) # 수입 분류
current_inc = int(str(self.totalIncLb.text()).split(' ')[2])
print(current_inc)
current_inc += int(money)
self.totalIncLb.setText("총 수입: " + str(current_inc))
self.insertItem(date, "수입", category, money)
# 지출금액 기입을 위한 버튼액션
def inputExp(self):
date = self.calendarWidget.selectedDate()
date = str(date.toString())
money = str(self.expLine.text()) # 지출 금액
category = str(self.expComBx.currentText()) # 지출 분
current_out = int(str(self.totalExpLb.text()).split(' ')[2])
current_out += int(money)
self.totalExpLb.setText("총 지출: " + str(current_out))
self.insertItem(date, "지출", category, money)
tableWidget dataInit
#tableWidget dataInit
def setTableWidgetData(self):
column_headers = ['날짜', '수입/지출', '카테고리', '금액']
self.tableWidget.setHorizontalHeaderLabels(column_headers)
self.tableWidget.resizeColumnsToContents()
self.tableWidget.resizeRowsToContents()
수입금액 기입을 위한 버튼액션
def inputInc(self):
date = self.calendarWidget.selectedDate()
date = str(date.toString())
money = str(self.incLine.text()) # 수입금액
category = str(self.incComBx.currentText()) # 수입 분류
current_inc = int(str(self.totalIncLb.text()).split(' ')[2])
print(current_inc)
current_inc += int(money)
self.totalIncLb.setText("총 수입: " + str(current_inc))
self.insertItem(date, "수입", category, money)
date = self.calendarWidget.selectedDate(): calendarWidget 위젯에서 선택된 날짜를 가져와서 date 변수에 저장
(self는 자기자신을 뜻하지만, 객체의 고유한 속성값을 의미한다.)
self.calendarWidget는 QCalendarWidget 클래스의 인스턴스인 calendarWidget 객체를 나타냅니다. selectedDate는 QCalendarWidget 클래스에서 제공되는 메서드
date = str(date.toString()): date 변수를 문자열로 변환하여 저장
date.toString()은 PyQt에서 사용되는 메서드로, QDate 객체인 date의 문자열 표현을 반환 그 후에 str() 함수를 사용하여 PyQt에서 반환된 문자열을 파이썬의 문자열로 변환
# 지출금액 기입을 위한 버튼액션
def inputExp(self):
date = self.calendarWidget.selectedDate()
date = str(date.toString())
money = str(self.expLine.text()) # 지출 금액
category = str(self.expComBx.currentText()) # 지출 분
current_out = int(str(self.totalExpLb.text()).split(' ')[2])
current_out += int(money)
self.totalExpLb.setText("총 지출: " + str(current_out))
self.insertItem(date, "지출", category, money)
category : expComBx는 지출 분류가 선택되는 콤보 박스 위젯
self.totalExpLb.text(): totalExpLb 레이블 위젯의 텍스트 값을 가져옵니다. text()는 해당 위젯의 텍스트 값을 반환하는 메서드다. + str(...): 텍스트 값을 문자열로 변환
-> .split(' '): 문자열을 공백을 기준으로 분할
-> split 함수는 인자로 전달된 구분자를 기준으로 문자열을 분할하고, 분할된 부분 문자열을 리스트로 반환합니다. 위 코드에서는 공백을 구분자로 사용하여 텍스트를 분할하고, 분할된 부분 문자열 중에서 두 번째 부분을 선택
-> [2]: 리스트에서 두 번째 요소를 선택합니다. 리스트의 인덱스는 0부터 시작하므로, [2]는 세 번째 요소를 의미합니다. 위 코드에서는 split 함수로 분할된 부분 문자열 중에서 세 번째 요소를 선택
요약하면, self.totalExpLb 레이블 위젯의 텍스트 값을 가져와서 공백으로 분할한 후, 그 중에서 세 번째 요소를 정수로 변환하여 current_out 변수에 저장
현재 총 지출 금액을 업데이트한다. totalExpLb는 총 지출 금액을 표시하는 레이블 위젯
self.insertItem(date, "지출", category, money)
수입/지출 목록 삭제를 위한 버튼액션
# 수입/지출 목록 삭제를 위한 버튼액션
def delList(self):
# print("cnt_row" , cnt_row)
if self.tableWidget.rowCount() > 1:
self.tableWidget.removeRow(self.tableWidget.currentRow())
cnt_row = self.tableWidget.rowCount()
f = open("household_ledger.csv", 'w', encoding = 'utf-8', newline = '')
f.close()
income, outcome = 0, 0
for i in range(0, cnt_row - 1):
date = self.tableWidget.item(i, 0).text()
inout = self.tableWidget.item(i, 1).text()
category = self.tableWidget.item(i, 2).text()
money = self.tableWidget.item(i, 3).text()
if '수입' in inout:
income += int(money)
elif '지출' in inout:
outcome += int(money)
self.table_to_csv(i, date, inout, category, money)
self.totalIncLb.setText("총 수입: " + str(income))
self.totalExpLb.setText("총 지출: " + str(outcome))
행(row) 개수가 1보다 큰 경우에만 삭제 작업을 수행한다. [최소한 1개의 행을 유지하려는 작업이다.]
self.tableWidget.removeRow(self.tableWidget.currentRow())는 현재 선택된 행을 테이블 위젯에서 삭제 + self.tableWidget.currentRow()는 현재 선택된 행의 인덱스를 반환
cnt_row = self.tableWidget.rowCount()는 삭제 후 남은 행의 개수를 cnt_row 변수에 저장
f = open("household_ledger.csv", 'w', encoding='utf-8', newline='')는 'household_ledger.csv' 파일을 쓰기 모드로 연다. 이 파일은 가계부 정보를 저장하는 용도다.
for i in range(0, cnt_row - 1):은 0부터 cnt_row - 1까지의 범위에서 반복문을 실행한다. 이 범위는 삭제 후 남은 행의 개수를 기준으로 한다.
반복문 내부에서는 각 행의 날짜, 수입/지출 내용, 카테고리, 금액을 변수에 저장하고, 해당 정보를 CSV 파일에 기록 self.table_to_csv() 함수를 사용하여 테이블의 정보를 CSV 파일로 저장
self.totalIncLb.setText("총 수입: " + str(income))과 self.totalExpLb.setText("총 지출: " + str(outcome))은 수입과 지출의 총합을 나타내는 레이블을 갱신합니다. setText() 함수를 사용하여 총 수입과 총 지출을 문자열로 설정
위의 코드는 주어진 테이블 위젯에서 선택된 행을 삭제하고, 남은 행들의 정보를 CSV 파일에 다시 저장하며, 수입과 지출의 총합을 계산하여 화면에 출력하는 역할
if __name__ == "__main__": # 현재 모듈의 이름이 저장되는 내장 변수 이 한 줄의 코드를 통해 프로그램이 직접 실행되는지 혹은 모듈을 통해 실행되는지를 확인
app = QtWidgets.QApplication(sys.argv) #모든 PyQt5 어플리케이션은 어플리케이션 객체를 생성해야한다.
mainWindow = QtWidgets.QMainWindow()
ui = Ui_mainWindow()#인스턴스 생성
ui.setupUi(mainWindow)#ui라는 객체에서 setupui메서드 실행 + mainwindow라는 객체를 전달한다.
mainWindow.show()
ui.csv_load()#메서드 실행
sys.exit(app.exec_())
QtWidgets.QApplication(sys.argv) 부분은 QtWidgets이라는 모듈에서 QApplication 클래스를 가져와 app이라는 객체를 생성했다.
이 부분은 인스턴스가 아니라 모듈에서 클래스를 가져와 객체를 생성한 부분이다. 헷갈리기 x
mainWindow도 동일하다. QtWidgets.QMainWindow() 부분도 QtWidgets 모듈에서 QMainWindow() 클래스를 참조해 mainwindow라는 객체를 생성했다.
ui는 위 클래스인 Ui_mainWindow() 인스턴스를 생성했다.
ui.setupUi(mainWindow)는 ui라는 객체에서 setupUi메서드 실행 -> mainwindow는 객체다 [상속 x]
이 코드에서는 setupUi() 메서드가 생성자 역할이다.
생성자는 클래스가 인스턴스화될 때 자동으로 호출되는 메서드로서, 클래스의 초기화 작업을 담당한다.
Ui_mainWindow 클래스의 setupUi() 메서드는 mainWindow 객체를 전달받아 UI를 초기화하고 구성 요소를 설정한다.
이 메서드 내에서 UI 요소들이 생성되고 초기 설정이 이루어진다. 그래서 setupUi() 메서드가 생성자 역할을 하며, mainWindow 객체를 전달하여 UI를 초기화하는 역할을 수행한다.