1. 기업맞춤형 빅데이터 분석가 양성과정 소개
2. 기업맞춤형 빅데이터 분석가 양성과정 노트목록
https://crosefrog.tistory.com/entry/20210104-%EB%B9%85%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D%EA%B0%80-%EC%96%91%EC%84%B1%EA%B3%BC%EC%A0%95-4%EC%9D%BC%EC%B0%A8-%EB%85%B8%ED%8A%B8
https://crosefrog.tistory.com/entry/20240105-%EB%B9%85%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D%EA%B0%80-%EC%96%91%EC%84%B1%EA%B3%BC%EC%A0%95-5%EC%9D%BC%EC%B0%A8-%EB%85%B8%ED%8A%B8
https://crosefrog.tistory.com/entry/20240109-%EB%B9%85%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D%EA%B0%80-%EC%96%91%EC%84%B1%EA%B3%BC%EC%A0%95-7%EC%9D%BC%EC%B0%A8-%EB%85%B8%ED%8A%B8
https://crosefrog.tistory.com/entry/20240111-%EB%B9%85%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D%EA%B0%80-%EC%96%91%EC%84%B1%EA%B3%BC%EC%A0%95-9%EC%9D%BC%EC%B0%A8-%EB%85%B8%ED%8A%B8
3. PyQt.py / Python Basic.py
4. Notion 일과 삶 & 빅데이터 분석가 양성과정 대시보드
https://lifemoment.notion.site/497bff9488aa4dec9171d08224a7a978?pvs=4
5. Naver 블로그 포스팅
https://blog.naver.com/moment_by_moment/223323478571
6. 필기노트
PyQt를 활용한 GUI 프로그램
PyQt로 뭘 하기보단, 파이썬 기본문법에서 클래스에 대한 이해
클래스를 바탕으로 작성된 코드를 응용할 일에 대비해 적응하는 시간을 가지자는 의미에서 PyQt를 배운다.
예를 들어서, 경제학과 나오면 꼭 경제학 관련 일을 하는 것이 아니니 프로그램을 배울 때도 넓은 시야로 시작하면 좋다.
신입 엔지니어에게 10대 코딩 中 블록코딩을 시켰었다.
신입 사원은 엔지니어가 되고 싶은 사람이다.
다루는 범위는 제법 많다.
Graphic User Interface
함수를 통해서 값을 가져오도록 한다.
문자열로 하면 error가 나온다.
프로그램이 돌다가 문제없을 거라 여겼던, error가 생기기도 한다.
sys module
import sys
# sys.argv - 명령 행에서 입력된 인수가 저장되어 있음
# $ python sys_module_test.py hello.py
# ['sys_module_test.py', 'hello.py']
print(sys.argv)
#sys.exit() - 스크립트 강제 종료
x = 0
while True:
if x == 5:
sys.exit()
else:
print(x)
x += 1
- 출력결과
- 프롬프트: 박근혜 대통령 당시부터 나온 단어
아나운서가 말을 할 때, 스크립트가 카메라 밑에 붙어져 있다.
(살짝 시선이 떨어진다.)
→ 카메라 렌즈 밑에 붙여둔다. (프롬프트라고 부른다.)
이런 프롬프트가 아닌, 명령을 대기하는 것도 프롬프트라고 부른다.
‘.’ ⇒ 현재 디렉토리에 있다.
\\ ⇒
경로, 소스코드 이름, 옵션
- PyQt란 무엇인가?
Python + Qt를 합쳤다는 의미에서 PyQt라고 이름을 붙였으며, C++ 기반의 GUI Framework인 Qt를 Python에서 사용할 수 있게 만든 패키지(Qt의 레이아웃에 Python의 코드를 연결하여 GUI 프로그램을 만들 수 있게 해주는 프레임워크).
PyQt는 C++의 Cross Platform GUI Franwork인 Qt를 영국의 Riverbank Computing에서 Python 모듈로 변환해 주는 툴을 만들면서 시작 되었음.
(PyQt4 버전과 PyQt 5버전이 주로 사용되고 있음.)
- PyQt의 특징
Python에도 PyGTK, PySide, Tkinter 등 다양한 GUI Framework가 존재하지만 이러한 GUI Frame은 사용하기 어렵고 시각적으로 이쁘지 않다는 단점이 있음.
app = 프로그램 = 객체
→ 프로그램 객체, 윈도우 객체 각각 하나씩 만들어서 실행한다.
창 하나, 프로그램 하나 만들면 유기적으로 돌아간다.
프로그램 하나 실행해서 출력되는 결과가 당연하다고 생각하지만, 많은 것들이 들어가 있다.
라이브러리: 전체적인 흐름을 따라가게 만들어져 있다.
프레임워크: 속에 보이지 않는 구조물이 있다. (보이지 않는 손이 있다.)
myWindow 안에 QWidget() 클래스 지정한 뒤, 새로운 생성자로 지정하였다.
- MyWindow 클래스 생성
MyWindow 클래스 생성
: QMainWindow 클래스로부터 상속을 받아 MyWindow 클래스 정의
: MyWindow 클래스의 인스턴스 생성
→ myWindow = MyWindow()
: ‘PyQt 첫 번째 코딩’ 에서는 Qwidget 클래스의 인스턴스 생성
PyQt 세 번째 코딩
: 클래스 초기화 함수
init(self)
super().init()
: 윈도우 타이틀 지정
setWindowTitle(’My PyQt Window’)
: 윈도우 크기 지정(변경)
setGeometry(x, y, width, height)
→ x, y : 모니터 좌표
→ width, height : ‘윈도우’의 폭의 높이
폭: 320
높이: 180
#빔 프로젝트는 가로 1,024px 세로 684px로 나눠서 보여준다.
클래스 개념으로 프로그램을 짜면 어떤가?
- PyQt - Hello World!
: 필요한 클래스만 import 함
: myWindow 인스턴스
QtWidget을 상속 받은 HelloWorldWindow 클래스로 생성함
QtWidget 클래스가 가지고 있는 여러 메서드를 사용할 수 있음
setWindowTitle(), setGeometry()
QLabel()
: 라벨 객체를 생성
setText()
: 객체의 텍스트 속성 값을 지정
move()
: 객체를 지정된 위치로 이동
앞으로 어떤 객체에 텍스트를 쓰고 싶다.
class 정의: 파이썬 인터프리터가 이렇게 설계했다는 부분
Qt Designer 설치
- Qt Designer
: PyQt를 이용하여 GUI 프로그래밍을 할 때 손쉽게 프로그램의 레이아웃을 편집할 수 있게 해주는 편집기
- PyQt 및 Qt Designer 설치
→ Windows의 cmd 창에서 실행
-> pip install pyqt5
-> pip install pyqt5-tools
⇒ PyQt를 이용해서 사용자 인터페이스를 제작할 수 있다.
템플릿(templates)
위젯(Widgets)
geometry
- x, y: 위치값
- 너비, 높이: 조정값
Qt Designer 위젯의 속성
: 위젯 마다 속성이 조금씩 다르지만 공통적으로 가지고 있는 속성이 다수 있음.
자주 사용되는 속성들
- ObjectName : Python 코드에서 사용될 위젯의 이름을 설정.
- Gemometry : 위젯의 x, y 좌표와 폭과 높이를 지정
- Palette : 위젯의 색상을 지정
- Font : 글자의 폰트와 크기 지정
- ToolTip : 위젯 위에 마우스를 올려 놓았을 때 해당 위젯에 대한 정보를 제공하는 글자 출력
- TooTipDuration : tooltip이 얼마 동안 보여질지 시간 지정, 단위는 millisecond
- TooTipDration이 1이면 해당 위젯에 마우스가 올려져 있으면 지속적으로 tooltip를 출력
UI와 Python 코드의 연결하는 방법
: UI 파일을 Python 코드에서 import하는 방법
# filename - PushButtonTest.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
# UI 파일 연결
# UI 파일이 "현재 작업 디렉토리/ui" 디렉토리에 있다고 가정
form_class = uic.loadUiType('./ui/PushButtenTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
# filename – PushButtonTest.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
# UI 파일 연결
# UI 파일이 "현재 작업 디렉토리/ui" 디렉토리에 있다고 가정
form_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
정리: PyQt 시작
- PyQt란 무엇인가?
Python + Qt를 합쳤다는 의미에서 PyQt라고 이름을 붙였으며, C++ 기반의 GUI Framework인 Qt를 Python에서 사용할 수 있게 만든 패키지(Qt의 레이아웃에 Python의 코드를 연결하여 GUI 프로그램을 만들 수 있게 해주는 프레임워크).
특징: Python에도 PyGTK, PySide, Tkinter 등 다양한 GUI Framework가 존재하지만 이러한 GUI Frame은 사용하기 어렵고 시각적으로 이쁘지 않다는 단점이 있음.
- Qt Designer의 설치
- Qt Designer의 화면 구성
- Qt Designer를 이용한 UI 제작과 연결
일을 시켜서 하는 사람이 있다.
컴퓨터없이 수업 하는 사람은 프린터물을 나눠주고 수업을 진행
빔 프로젝트도 없이 수업을 진행하다.
→ 조직이 원하는 것과 내가 원하는 것이 같으면 좋다.
자기가 하고싶은 일과 회사가 요구하는 일이 맞으면 시너지효과다.
프로그램은 안 시키는 것은 하지 않는다.
⇒ 명령하지 않은 것이 나타나거나, 실행되지 않으면 작성자의 잘못이다.
객체 입장에서는 이벤트(사건)가 발생한 것이다.
→ 지시를 해줘야 한다.
시그널(Signal)과 슬롯(Slot)
- 시그널(Signal)
위젯의 성태가 바뀌었을 때 위젯에서 특정 시그널(이벤트)이 발생
→ 위젯에서 신호를 내보냄
Ex) 버튼 위젯이 클릭되었을 때 어떤 동작(함수)을 수행하거나 다이얼 위젯을 돌렸을 때 화면에 다른 값이 출력되게 하는 동작(함수)을 지정
#시그널이 발생했을 때 신호를 내보내고, 어떤 기능을 하라고 짝을 지어주는데, 이것을 슬록이라고 부른다.
[예전에는 (시그널 = 이벤트)와 (슬롯 = 이벤트 핸들러)라고 불렀다.]
⇒ 슬롯은 시그널과 연결된 함수이다.
- 슬롯(Slot)
: 함수 개념
: 위젯에서 특정 신호(시그널)가 발생 했을 때 해당 시그널(이벤트)을 처리할 슬롯(이벤트 핸들러)을 지정할 수 있음
: 시그널에 처리를 위해 특정 시그널에 대해 슬롯(함수) 지정할 수 있음
- 함수 vs 슬롯
어떤 변화(이벤트, 시그널)가 없더라도 실행될 수 있는 코드
함수는 보통 위젯의 값을 설정하거나 위젯의 값을 가져오거나 위젯의 속성을 변경할 때 사용
PyQt에서 대부분의 위젯들이 공통적으로 사용하는 함수들이 몇 가지 있음.
- “Qt Designer를 이용한 UI 제작” 부분에서 어떻게 Qt Designer를 이용하여 UI 파일과 Python 코드를 연결하는지에 대해서 살펴 봤음(그때는 화면에 보인 위젯들은 아무런 기능을 하지 않았음).
- 위젯이 변화했을 때 어떤 동작을 하게 하기 위해서는 무엇을 해야 하는가?
위젯에서 발생한 시그널을 처리하는 슬롯이 있어야 함
시그널과 슬롯을 연결해야 함
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uicform_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
# 이 부분에 시그널과 슬롯을 연결하는 코드
# 여기에 슬롯(함수) 정의
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
# filename – PushButtonSignal.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
# QPushButton 위젯(btnA)에서 클릭 시그널이 발생하면
# btnA_function() 슬롯에 연결
self.btnA.clicked.connect(self.btnA_function)
# btnA_function() 슬롯 정의
def btnA_function(self):
print('Button A Clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
클릭하면 클릭했다는 신호가 발생한다.
#원래 선생의 말은 30% 정도만 들리더라.
강사는 노가다 = 움직이는 만큼 돈을 번다.
→ 회사는 아니다.
- 사업과 장사의 차이는 무엇인가?
백종원: 사업
사업: 시스템이 하는 것
장사: 자신이 직접 하는 것
알아서 하라고 하면 싫어한다.
(일을 맡긴다는 것은, 책임과 권한을 주는 것이다.)
같이 고민해서 ‘중학교 2학년’ 대상으로 어떤 것을 먹을지 생각한다.
자신이 없어도 돌아가는 시스템을 구축해야 한다.
→ 다시 끌어올리기 위해 고민하는 중이다.
내가 연봉을 그만큼 받기 위해선, 그런 능력이 있어야하고, 증명해서 동의해야 한다.
문제가 있으면, 스스로 얘기를 해서 해결해야 한다.
요점: 나의 연봉을 증가시키려면 어떻게 해야 하는가?
→ 방법을 찾고 있다.
- 구체적으로 행동하면서 실패해봐야 안다.
QRadioButton vs QCheckButton
n개 중에 1개를 선택할 때, Radio버튼으로 구현한다.
위젯 상자의 Containers 안에 있는 GroupBox
위젯 상자의 Button 안에 있는 Radio Button
물어볼 때는 라디오 버튼 중 1개만 잡는다.
→ n개 중에서 하나를 선택하라는 질문을 할 때 일반적으로 많이 사용하는 방법이다.
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/RadioButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.rBtn1.clicked.connect(self.groupBox_rbtn_function)
self.rBtn2.clicked.connect(self.groupBox_rbtn_function)
self.rBtn3.clicked.connect(self.groupBox_rbtn_function)
def groupBox_rbtn_function(self):
if self.rBtn1.isChecked():
print('RadioButtin1 Checked')
elif self.rBtn2.isChecked():
print('RadioButten2 Checked')
elif self.rBtn3.isChecked():
print("RadioButton3 Checked")
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
실행결과
PPT를 한번 만들었다가, 다시 만들었다.
기본구조 잡아보기 → 라벨 붙여보기 → 버튼 넣어보기 → 디자인을 써서 버튼을 하나 달고, 반응을 하기 위해 signal과 slot이 연결된다.
위젯, Buttons / Push Button
- UI 파일 생성 - QPushButton 위젯 두 개를 Dialog 창에 올려 놓기
텍스트 속성, 위치는 바꿔도 영향 X
**import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType("PushButtons.ui")[0]
class WindowClass(QMainWindow, form_class) :
def __init__(self) :
super().__init__()
self.setupUi(self)
self.btnA.clicked.connect(self.btnAFunction)
self.btnB.clicked.connect(self.btnBFunction)
def btnAFunction(self) :
print(self.btnA.text() + " Clicked")
QMessageBox.information(self, "Info", "Button A Clicked")
def btnBFunction(self) :
print(self.btnB.text() + " Clicked")
QMessageBox.information(self, "Info", "Button B Clicked")
if __name__ == "__main__" :
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()**
- QCheckBox
계층 구조
: Dialog > Button
: Dialog > Containers > Button
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/CheckBoxTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.groupChkBox1.stateChanged.connect(self.group_chk_function)
self.groupChkBox2.stateChanged.connect(self.group_chk_function)
self.ChkBox1.stateChanged.connect(self.chk_function)
self.ChkBox2.stateChanged.connect(self.chk_function)
def group_chk_function(self):
if self.groupChkBox1.isChecked() : print('CheckBox1 in group is Checked')
if self.groupChkBox2.isChecked() : print('CheckBox2 in group is Checked')
def chk_function(self):
if self.ChkBox1.isChecked() : print('CheckBox1 is Checked')
if self.ChkBox2.isChecked() : print('CheckBox2 is Checked')
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
⇒ 출력결과
- 체크박스 안에 1번만 클릭하면, 1번에 대한 출력결과가 나오고
- 체크박스 안에 1번 클릭 후 2번을 클릭하면, 둘 다에 대한 출력결과가 나오고
- 체크박스 밖에 1번만 클릭하면, 밖에 1번에 대한 출력결과가 나오고
- 체크박스 밖에 1번 클릭 후 2번을 클릭하면, 밖에 있는 둘 다에 대한 출력결과가 나온다.
체크박스 안과 밖을 클릭하면, 나중에 클릭한 것에 대한 출력결과가 나온다.
(안을 먼저 클릭하면 밖에 대한 결과가 나오고, 밖을 먼저 클릭하면 밖에 대한 결과가 나온다.)
주문 시스템 만들기
- Window 디자인
GroupBox, CheckBox (GroupBox와 CheckBox의 텍스트(test) 속성 설정)
예전에 주문시스템을 만들면 어떨까?
→ 이용객들이 키오스크 문화에 익숙하지 않았다.
객체 이름
- 자장면 → chkBox_A0
- 짬뽕 → chkBox_A1
- 탕수육 → chkBox_B0
- 양장피 → chkBox_B1
- 팔보채 → chkBox_B2
동작
- 주문 내역을 주방에 출력
→ Terminal 창에 주문 내역을 print 하시오.
클릭 후, 주문버튼을 누르면 주문이 되는 방식으로 구상해야 한다.
- 가위바위보 게임 샘플
import sys
from random import randint
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
# from PyQt5.QtWid
class MainWindow(QDialog):
def __init__(self):
super().__init__()
self.setup_ui()
def setup_ui(self):
main_layout = QVBoxLayout() #메인 레이아웃
user_choose_layout = QHBoxLayout() #버튼 담길 레이아웃
#타이틀 지정
title = QLabel("허접한 가위바위보")
title_font = title.font()
# title_font.setPointSize(25)
title_font = QFont("나눔고딕코딩", 25, QFont.Bold)
title.setFont(title_font)
title.setAlignment(Qt.AlignCenter)
# 이미지 불러오기 및 이미지 사이즈 강제조정
rock_image = QPixmap('주먹.png')
rock_image = rock_image.scaled(50,50,Qt.IgnoreAspectRatio)
scissor_image = QPixmap('가위.png')
scissor_image = scissor_image.scaled(50, 50, Qt.IgnoreAspectRatio)
paper_image = QPixmap('보.png')
paper_image = paper_image.scaled(50, 50, Qt.IgnoreAspectRatio)
# 가위바위보 버튼 , 종료 버튼
self.scissor_btn = QPushButton('가위')
self.rock_btn = QPushButton('바위')
self.paper_btn = QPushButton('보')
quit_btn = QPushButton("종료하기", self)
#버튼 이름 숨기기
# self.scissor_btn.setProperty("orgtext", scissor_btn)
# self.scissor_btn.setText("가위")
#종료버튼 눌렀을 때 종료하기
quit_btn.clicked.connect(self.close)
#버튼에 이미지 넣기 및 버튼 사이즈 조정
self.scissor_btn.setIcon(QIcon(scissor_image))
self.scissor_btn.setIconSize(QSize(70, 70))
self.rock_btn.setIcon(QIcon(rock_image))
self.rock_btn.setIconSize(QSize(70, 70))
self.paper_btn.setIcon(QIcon(paper_image))
self.paper_btn.setIconSize(QSize(70, 70))
#버튼 누르면 이벤트
self.scissor_btn.clicked.connect(self.game_play)
self.rock_btn.clicked.connect(self.game_play)
self.paper_btn.clicked.connect(self.game_play)
#화면 나올 창
# self.image = QLabel()
#레이아웃 담아주기
user_choose_layout.addWidget(self.rock_btn)
user_choose_layout.addWidget(self.paper_btn)
user_choose_layout.addWidget(self.scissor_btn)
main_layout.addWidget(title)
# main_layout.addWidget(image)
main_layout.addLayout(user_choose_layout)
main_layout.addWidget(quit_btn)
self.setWindowTitle("가위바위보게임")
self.setLayout(main_layout)
self.show()
def game_play(self):
# global com_guess
random_num = randint(1, 3)
print(random_num)
if random_num == 1:
com_guess = '가위'
elif random_num == 2:
com_guess = '바위'
if random_num == 3:
com_guess = '보'
reply = QMessageBox() #응답이 받아질 메세지박스
reply.setWindowTitle('결과는!') #메세지박스 상단 텍스트
sender = self.sender() #눌린 버튼을 가져옴
btn_name = sender.text() #눌린 버튼의 이름을 가져옴
if (random_num == 1 and btn_name == '가위') or \\
(random_num == 2 and btn_name == '바위') or \\
(random_num == 3 and btn_name == '보'):
# draw_img = QPixmap('yelled_pingu.jpg')
# draw_img.
reply.setIconPixmap(QPixmap('yelled_pingu.jpg'))
reply.setText(f"비겼습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
elif (random_num == 1 and btn_name == '바위') or \\
(random_num == 2 and btn_name == '보') or \\
(random_num == 3 and btn_name == '가위'):
reply.setIconPixmap(QPixmap('smile_pingu.jpg'))
reply.setText(f"이겼습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
else:
reply.setIconPixmap(QPixmap('angry_pingu2.png'))
reply.setText(f"졌습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
def closeEvent(self, event):
# 종료 대화상자 표시
reply = QMessageBox.question(self, '종료확인', '종료하시겠습니까?',
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
# '예' 버튼을 클릭하면 종료
event.accept()
else:
# '아니오' 버튼을 클릭하면 이벤트 무시
event.ignore()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainWindow()
# MainWindow.show()
sys.exit(app.exec_())
이번주 월, 화는 PyQt수업
수, 목, 금은 데이터 분석 기초
다음주 월, 화, 수는 박태우 강사님 수업
다음 주 목, 금은 데이터 분석 기초
다다음주는 MySQL
이후, 웹 서버로 넘어간다.
- 자바 스크립트 → Node.js(자바 스크립트 업그레아드 버전)
이후 데이터분석으로 본격적으로 들어간다.
(원래 날짜가 정해져있지만, 상황에 따라 탄력적으로 운영한다.)
3월 초에도 데이터분석을 이어간다.
웹 크롤링도 하기 나름이다.
(일단, 파이썬에 적응해야 한다.)
보통 웹 크롤링으로 데이터를 모으려고 하진 않는다.
웹 크롤링은 시간이 많이 걸린다.
(여력 있으면 하고, 없으면 넘어가도 된다.)
데이터베이스 수업이 일주일 정도 잡혀있지만, Node.js에서 사용하는 데이터베이스와 MySQL 데이터베이스가 조금 다르다.
작년에는 여름에 시작해서 가을이었다.
추석끼고 나서 조금 분위기가 해이해졌다.
우리는 설날을 잘 보내야 탄력이 유지되지 않을까싶다.
터미널 창에 주문내역을 프린트하는데,
클릭할 때마다 프린트하는 건 아니다.
→ 이번에는 주문 눌렀을 때 프린트하면 된다.
(체크상태를 보고 주문을 해야한다.)
주문한 리스트가 있어야 하는데, 언제 주문리스트를 만들 것인가?
(프린트한 내용은 언제 만들면 좋을까?)
- 주문리스트를 만들고 프린트 할 것인가?
(주문 버튼을 눌렀을 때, 주문리스트를 만들면 된다.)
→ 리스트를 어떻게 뽑을 것인가?
버튼 클릭하면, 주문내역을 프린트한다.
프로그램에 익숙하다면, 반복문으로 바꿔보자.
위젯과 레이아웃
- 위젯, Display / Qlabel
PyQt 책은 서점에 없다.
(교보문고에 전자책으로 있다.)
→ PyQt를 인터넷에 검색하면 잘 나온다.
PyQt를 활용한 GUI 프로그램
PyQt로 뭘 하기보단, 파이썬 기본문법에서 클래스에 대한 이해
클래스를 바탕으로 작성된 코드를 응용할 일에 대비해 적응하는 시간을 가지자는 의미에서 PyQt를 배운다.
예를 들어서, 경제학과 나오면 꼭 경제학 관련 일을 하는 것이 아니니 프로그램을 배울 때도 넓은 시야로 시작하면 좋다.
신입 엔지니어에게 10대 코딩 中 블록코딩을 시켰었다.
신입 사원은 엔지니어가 되고 싶은 사람이다.
다루는 범위는 제법 많다.
Graphic User Interface
함수를 통해서 값을 가져오도록 한다.
문자열로 하면 error가 나온다.
프로그램이 돌다가 문제없을 거라 여겼던, error가 생기기도 한다.
sys module
import sys
# sys.argv - 명령 행에서 입력된 인수가 저장되어 있음
# $ python sys_module_test.py hello.py
# ['sys_module_test.py', 'hello.py']
print(sys.argv)
#sys.exit() - 스크립트 강제 종료
x = 0
while True:
if x == 5:
sys.exit()
else:
print(x)
x += 1
- 출력결과
- 프롬프트: 박근혜 대통령 당시부터 나온 단어
아나운서가 말을 할 때, 스크립트가 카메라 밑에 붙어져 있다.
(살짝 시선이 떨어진다.)
→ 카메라 렌즈 밑에 붙여둔다. (프롬프트라고 부른다.)
이런 프롬프트가 아닌, 명령을 대기하는 것도 프롬프트라고 부른다.
‘.’ ⇒ 현재 디렉토리에 있다.
\\ ⇒
경로, 소스코드 이름, 옵션
- PyQt란 무엇인가?
Python + Qt를 합쳤다는 의미에서 PyQt라고 이름을 붙였으며, C++ 기반의 GUI Framework인 Qt를 Python에서 사용할 수 있게 만든 패키지(Qt의 레이아웃에 Python의 코드를 연결하여 GUI 프로그램을 만들 수 있게 해주는 프레임워크).
PyQt는 C++의 Cross Platform GUI Franwork인 Qt를 영국의 Riverbank Computing에서 Python 모듈로 변환해 주는 툴을 만들면서 시작 되었음.
(PyQt4 버전과 PyQt 5버전이 주로 사용되고 있음.)
- PyQt의 특징
Python에도 PyGTK, PySide, Tkinter 등 다양한 GUI Framework가 존재하지만 이러한 GUI Frame은 사용하기 어렵고 시각적으로 이쁘지 않다는 단점이 있음.
app = 프로그램 = 객체
→ 프로그램 객체, 윈도우 객체 각각 하나씩 만들어서 실행한다.
창 하나, 프로그램 하나 만들면 유기적으로 돌아간다.
프로그램 하나 실행해서 출력되는 결과가 당연하다고 생각하지만, 많은 것들이 들어가 있다.
라이브러리: 전체적인 흐름을 따라가게 만들어져 있다.
프레임워크: 속에 보이지 않는 구조물이 있다. (보이지 않는 손이 있다.)
myWindow 안에 QWidget() 클래스 지정한 뒤, 새로운 생성자로 지정하였다.
- MyWindow 클래스 생성
MyWindow 클래스 생성
: QMainWindow 클래스로부터 상속을 받아 MyWindow 클래스 정의
: MyWindow 클래스의 인스턴스 생성
→ myWindow = MyWindow()
: ‘PyQt 첫 번째 코딩’ 에서는 Qwidget 클래스의 인스턴스 생성
PyQt 세 번째 코딩
: 클래스 초기화 함수
init(self)
super().init()
: 윈도우 타이틀 지정
setWindowTitle(’My PyQt Window’)
: 윈도우 크기 지정(변경)
setGeometry(x, y, width, height)
→ x, y : 모니터 좌표
→ width, height : ‘윈도우’의 폭의 높이
폭: 320
높이: 180
#빔 프로젝트는 가로 1,024px 세로 684px로 나눠서 보여준다.
클래스 개념으로 프로그램을 짜면 어떤가?
- PyQt - Hello World!
: 필요한 클래스만 import 함
: myWindow 인스턴스
QtWidget을 상속 받은 HelloWorldWindow 클래스로 생성함
QtWidget 클래스가 가지고 있는 여러 메서드를 사용할 수 있음
setWindowTitle(), setGeometry()
QLabel()
: 라벨 객체를 생성
setText()
: 객체의 텍스트 속성 값을 지정
move()
: 객체를 지정된 위치로 이동
앞으로 어떤 객체에 텍스트를 쓰고 싶다.
class 정의: 파이썬 인터프리터가 이렇게 설계했다는 부분
Qt Designer 설치
- Qt Designer
: PyQt를 이용하여 GUI 프로그래밍을 할 때 손쉽게 프로그램의 레이아웃을 편집할 수 있게 해주는 편집기
- PyQt 및 Qt Designer 설치
→ Windows의 cmd 창에서 실행
-> pip install pyqt5
-> pip install pyqt5-tools
⇒ PyQt를 이용해서 사용자 인터페이스를 제작할 수 있다.
템플릿(templates)
위젯(Widgets)
geometry
- x, y: 위치값
- 너비, 높이: 조정값
Qt Designer 위젯의 속성
: 위젯 마다 속성이 조금씩 다르지만 공통적으로 가지고 있는 속성이 다수 있음.
자주 사용되는 속성들
- ObjectName : Python 코드에서 사용될 위젯의 이름을 설정.
- Gemometry : 위젯의 x, y 좌표와 폭과 높이를 지정
- Palette : 위젯의 색상을 지정
- Font : 글자의 폰트와 크기 지정
- ToolTip : 위젯 위에 마우스를 올려 놓았을 때 해당 위젯에 대한 정보를 제공하는 글자 출력
- TooTipDuration : tooltip이 얼마 동안 보여질지 시간 지정, 단위는 millisecond
- TooTipDration이 1이면 해당 위젯에 마우스가 올려져 있으면 지속적으로 tooltip를 출력
UI와 Python 코드의 연결하는 방법
: UI 파일을 Python 코드에서 import하는 방법
# filename - PushButtonTest.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
# UI 파일 연결
# UI 파일이 "현재 작업 디렉토리/ui" 디렉토리에 있다고 가정
form_class = uic.loadUiType('./ui/PushButtenTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
# filename – PushButtonTest.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
# UI 파일 연결
# UI 파일이 "현재 작업 디렉토리/ui" 디렉토리에 있다고 가정
form_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
정리: PyQt 시작
- PyQt란 무엇인가?
Python + Qt를 합쳤다는 의미에서 PyQt라고 이름을 붙였으며, C++ 기반의 GUI Framework인 Qt를 Python에서 사용할 수 있게 만든 패키지(Qt의 레이아웃에 Python의 코드를 연결하여 GUI 프로그램을 만들 수 있게 해주는 프레임워크).
특징: Python에도 PyGTK, PySide, Tkinter 등 다양한 GUI Framework가 존재하지만 이러한 GUI Frame은 사용하기 어렵고 시각적으로 이쁘지 않다는 단점이 있음.
- Qt Designer의 설치
- Qt Designer의 화면 구성
- Qt Designer를 이용한 UI 제작과 연결
일을 시켜서 하는 사람이 있다.
컴퓨터없이 수업 하는 사람은 프린터물을 나눠주고 수업을 진행
빔 프로젝트도 없이 수업을 진행하다.
→ 조직이 원하는 것과 내가 원하는 것이 같으면 좋다.
자기가 하고싶은 일과 회사가 요구하는 일이 맞으면 시너지효과다.
프로그램은 안 시키는 것은 하지 않는다.
⇒ 명령하지 않은 것이 나타나거나, 실행되지 않으면 작성자의 잘못이다.
객체 입장에서는 이벤트(사건)가 발생한 것이다.
→ 지시를 해줘야 한다.
시그널(Signal)과 슬롯(Slot)
- 시그널(Signal)
위젯의 성태가 바뀌었을 때 위젯에서 특정 시그널(이벤트)이 발생
→ 위젯에서 신호를 내보냄
Ex) 버튼 위젯이 클릭되었을 때 어떤 동작(함수)을 수행하거나 다이얼 위젯을 돌렸을 때 화면에 다른 값이 출력되게 하는 동작(함수)을 지정
#시그널이 발생했을 때 신호를 내보내고, 어떤 기능을 하라고 짝을 지어주는데, 이것을 슬록이라고 부른다.
[예전에는 (시그널 = 이벤트)와 (슬롯 = 이벤트 핸들러)라고 불렀다.]
⇒ 슬롯은 시그널과 연결된 함수이다.
- 슬롯(Slot)
: 함수 개념
: 위젯에서 특정 신호(시그널)가 발생 했을 때 해당 시그널(이벤트)을 처리할 슬롯(이벤트 핸들러)을 지정할 수 있음
: 시그널에 처리를 위해 특정 시그널에 대해 슬롯(함수) 지정할 수 있음
- 함수 vs 슬롯
어떤 변화(이벤트, 시그널)가 없더라도 실행될 수 있는 코드
함수는 보통 위젯의 값을 설정하거나 위젯의 값을 가져오거나 위젯의 속성을 변경할 때 사용
PyQt에서 대부분의 위젯들이 공통적으로 사용하는 함수들이 몇 가지 있음.
- “Qt Designer를 이용한 UI 제작” 부분에서 어떻게 Qt Designer를 이용하여 UI 파일과 Python 코드를 연결하는지에 대해서 살펴 봤음(그때는 화면에 보인 위젯들은 아무런 기능을 하지 않았음).
- 위젯이 변화했을 때 어떤 동작을 하게 하기 위해서는 무엇을 해야 하는가?
위젯에서 발생한 시그널을 처리하는 슬롯이 있어야 함
시그널과 슬롯을 연결해야 함
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uicform_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
# 이 부분에 시그널과 슬롯을 연결하는 코드
# 여기에 슬롯(함수) 정의
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
# filename – PushButtonSignal.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
# QPushButton 위젯(btnA)에서 클릭 시그널이 발생하면
# btnA_function() 슬롯에 연결
self.btnA.clicked.connect(self.btnA_function)
# btnA_function() 슬롯 정의
def btnA_function(self):
print('Button A Clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
클릭하면 클릭했다는 신호가 발생한다.
#원래 선생의 말은 30% 정도만 들리더라.
강사는 노가다 = 움직이는 만큼 돈을 번다.
→ 회사는 아니다.
- 사업과 장사의 차이는 무엇인가?
백종원: 사업
사업: 시스템이 하는 것
장사: 자신이 직접 하는 것
알아서 하라고 하면 싫어한다.
(일을 맡긴다는 것은, 책임과 권한을 주는 것이다.)
같이 고민해서 ‘중학교 2학년’ 대상으로 어떤 것을 먹을지 생각한다.
자신이 없어도 돌아가는 시스템을 구축해야 한다.
→ 다시 끌어올리기 위해 고민하는 중이다.
내가 연봉을 그만큼 받기 위해선, 그런 능력이 있어야하고, 증명해서 동의해야 한다.
문제가 있으면, 스스로 얘기를 해서 해결해야 한다.
요점: 나의 연봉을 증가시키려면 어떻게 해야 하는가?
→ 방법을 찾고 있다.
- 구체적으로 행동하면서 실패해봐야 안다.
QRadioButton vs QCheckButton
n개 중에 1개를 선택할 때, Radio버튼으로 구현한다.
위젯 상자의 Containers 안에 있는 GroupBox
위젯 상자의 Button 안에 있는 Radio Button
물어볼 때는 라디오 버튼 중 1개만 잡는다.
→ n개 중에서 하나를 선택하라는 질문을 할 때 일반적으로 많이 사용하는 방법이다.
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/RadioButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.rBtn1.clicked.connect(self.groupBox_rbtn_function)
self.rBtn2.clicked.connect(self.groupBox_rbtn_function)
self.rBtn3.clicked.connect(self.groupBox_rbtn_function)
def groupBox_rbtn_function(self):
if self.rBtn1.isChecked():
print('RadioButtin1 Checked')
elif self.rBtn2.isChecked():
print('RadioButten2 Checked')
elif self.rBtn3.isChecked():
print("RadioButton3 Checked")
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
실행결과
PPT를 한번 만들었다가, 다시 만들었다.
기본구조 잡아보기 → 라벨 붙여보기 → 버튼 넣어보기 → 디자인을 써서 버튼을 하나 달고, 반응을 하기 위해 signal과 slot이 연결된다.
위젯, Buttons / Push Button
- UI 파일 생성 - QPushButton 위젯 두 개를 Dialog 창에 올려 놓기
텍스트 속성, 위치는 바꿔도 영향 X
**import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType("PushButtons.ui")[0]
class WindowClass(QMainWindow, form_class) :
def __init__(self) :
super().__init__()
self.setupUi(self)
self.btnA.clicked.connect(self.btnAFunction)
self.btnB.clicked.connect(self.btnBFunction)
def btnAFunction(self) :
print(self.btnA.text() + " Clicked")
QMessageBox.information(self, "Info", "Button A Clicked")
def btnBFunction(self) :
print(self.btnB.text() + " Clicked")
QMessageBox.information(self, "Info", "Button B Clicked")
if __name__ == "__main__" :
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()**
- QCheckBox
계층 구조
: Dialog > Button
: Dialog > Containers > Button
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/CheckBoxTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.groupChkBox1.stateChanged.connect(self.group_chk_function)
self.groupChkBox2.stateChanged.connect(self.group_chk_function)
self.ChkBox1.stateChanged.connect(self.chk_function)
self.ChkBox2.stateChanged.connect(self.chk_function)
def group_chk_function(self):
if self.groupChkBox1.isChecked() : print('CheckBox1 in group is Checked')
if self.groupChkBox2.isChecked() : print('CheckBox2 in group is Checked')
def chk_function(self):
if self.ChkBox1.isChecked() : print('CheckBox1 is Checked')
if self.ChkBox2.isChecked() : print('CheckBox2 is Checked')
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
⇒ 출력결과
- 체크박스 안에 1번만 클릭하면, 1번에 대한 출력결과가 나오고
- 체크박스 안에 1번 클릭 후 2번을 클릭하면, 둘 다에 대한 출력결과가 나오고
- 체크박스 밖에 1번만 클릭하면, 밖에 1번에 대한 출력결과가 나오고
- 체크박스 밖에 1번 클릭 후 2번을 클릭하면, 밖에 있는 둘 다에 대한 출력결과가 나온다.
체크박스 안과 밖을 클릭하면, 나중에 클릭한 것에 대한 출력결과가 나온다.
(안을 먼저 클릭하면 밖에 대한 결과가 나오고, 밖을 먼저 클릭하면 밖에 대한 결과가 나온다.)
주문 시스템 만들기
- Window 디자인
GroupBox, CheckBox (GroupBox와 CheckBox의 텍스트(test) 속성 설정)
예전에 주문시스템을 만들면 어떨까?
→ 이용객들이 키오스크 문화에 익숙하지 않았다.
객체 이름
- 자장면 → chkBox_A0
- 짬뽕 → chkBox_A1
- 탕수육 → chkBox_B0
- 양장피 → chkBox_B1
- 팔보채 → chkBox_B2
동작
- 주문 내역을 주방에 출력
→ Terminal 창에 주문 내역을 print 하시오.
클릭 후, 주문버튼을 누르면 주문이 되는 방식으로 구상해야 한다.
- 가위바위보 게임 샘플
import sys
from random import randint
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
# from PyQt5.QtWid
class MainWindow(QDialog):
def __init__(self):
super().__init__()
self.setup_ui()
def setup_ui(self):
main_layout = QVBoxLayout() #메인 레이아웃
user_choose_layout = QHBoxLayout() #버튼 담길 레이아웃
#타이틀 지정
title = QLabel("허접한 가위바위보")
title_font = title.font()
# title_font.setPointSize(25)
title_font = QFont("나눔고딕코딩", 25, QFont.Bold)
title.setFont(title_font)
title.setAlignment(Qt.AlignCenter)
# 이미지 불러오기 및 이미지 사이즈 강제조정
rock_image = QPixmap('주먹.png')
rock_image = rock_image.scaled(50,50,Qt.IgnoreAspectRatio)
scissor_image = QPixmap('가위.png')
scissor_image = scissor_image.scaled(50, 50, Qt.IgnoreAspectRatio)
paper_image = QPixmap('보.png')
paper_image = paper_image.scaled(50, 50, Qt.IgnoreAspectRatio)
# 가위바위보 버튼 , 종료 버튼
self.scissor_btn = QPushButton('가위')
self.rock_btn = QPushButton('바위')
self.paper_btn = QPushButton('보')
quit_btn = QPushButton("종료하기", self)
#버튼 이름 숨기기
# self.scissor_btn.setProperty("orgtext", scissor_btn)
# self.scissor_btn.setText("가위")
#종료버튼 눌렀을 때 종료하기
quit_btn.clicked.connect(self.close)
#버튼에 이미지 넣기 및 버튼 사이즈 조정
self.scissor_btn.setIcon(QIcon(scissor_image))
self.scissor_btn.setIconSize(QSize(70, 70))
self.rock_btn.setIcon(QIcon(rock_image))
self.rock_btn.setIconSize(QSize(70, 70))
self.paper_btn.setIcon(QIcon(paper_image))
self.paper_btn.setIconSize(QSize(70, 70))
#버튼 누르면 이벤트
self.scissor_btn.clicked.connect(self.game_play)
self.rock_btn.clicked.connect(self.game_play)
self.paper_btn.clicked.connect(self.game_play)
#화면 나올 창
# self.image = QLabel()
#레이아웃 담아주기
user_choose_layout.addWidget(self.rock_btn)
user_choose_layout.addWidget(self.paper_btn)
user_choose_layout.addWidget(self.scissor_btn)
main_layout.addWidget(title)
# main_layout.addWidget(image)
main_layout.addLayout(user_choose_layout)
main_layout.addWidget(quit_btn)
self.setWindowTitle("가위바위보게임")
self.setLayout(main_layout)
self.show()
def game_play(self):
# global com_guess
random_num = randint(1, 3)
print(random_num)
if random_num == 1:
com_guess = '가위'
elif random_num == 2:
com_guess = '바위'
if random_num == 3:
com_guess = '보'
reply = QMessageBox() #응답이 받아질 메세지박스
reply.setWindowTitle('결과는!') #메세지박스 상단 텍스트
sender = self.sender() #눌린 버튼을 가져옴
btn_name = sender.text() #눌린 버튼의 이름을 가져옴
if (random_num == 1 and btn_name == '가위') or \\
(random_num == 2 and btn_name == '바위') or \\
(random_num == 3 and btn_name == '보'):
# draw_img = QPixmap('yelled_pingu.jpg')
# draw_img.
reply.setIconPixmap(QPixmap('yelled_pingu.jpg'))
reply.setText(f"비겼습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
elif (random_num == 1 and btn_name == '바위') or \\
(random_num == 2 and btn_name == '보') or \\
(random_num == 3 and btn_name == '가위'):
reply.setIconPixmap(QPixmap('smile_pingu.jpg'))
reply.setText(f"이겼습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
else:
reply.setIconPixmap(QPixmap('angry_pingu2.png'))
reply.setText(f"졌습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
def closeEvent(self, event):
# 종료 대화상자 표시
reply = QMessageBox.question(self, '종료확인', '종료하시겠습니까?',
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
# '예' 버튼을 클릭하면 종료
event.accept()
else:
# '아니오' 버튼을 클릭하면 이벤트 무시
event.ignore()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainWindow()
# MainWindow.show()
sys.exit(app.exec_())
이번주 월, 화는 PyQt수업
수, 목, 금은 데이터 분석 기초
다음주 월, 화, 수는 박태우 강사님 수업
다음 주 목, 금은 데이터 분석 기초
다다음주는 MySQL
이후, 웹 서버로 넘어간다.
- 자바 스크립트 → Node.js(자바 스크립트 업그레아드 버전)
이후 데이터분석으로 본격적으로 들어간다.
(원래 날짜가 정해져있지만, 상황에 따라 탄력적으로 운영한다.)
3월 초에도 데이터분석을 이어간다.
웹 크롤링도 하기 나름이다.
(일단, 파이썬에 적응해야 한다.)
보통 웹 크롤링으로 데이터를 모으려고 하진 않는다.
웹 크롤링은 시간이 많이 걸린다.
(여력 있으면 하고, 없으면 넘어가도 된다.)
데이터베이스 수업이 일주일 정도 잡혀있지만, Node.js에서 사용하는 데이터베이스와 MySQL 데이터베이스가 조금 다르다.
작년에는 여름에 시작해서 가을이었다.
추석끼고 나서 조금 분위기가 해이해졌다.
우리는 설날을 잘 보내야 탄력이 유지되지 않을까싶다.
터미널 창에 주문내역을 프린트하는데,
클릭할 때마다 프린트하는 건 아니다.
→ 이번에는 주문 눌렀을 때 프린트하면 된다.
(체크상태를 보고 주문을 해야한다.)
주문한 리스트가 있어야 하는데, 언제 주문리스트를 만들 것인가?
(프린트한 내용은 언제 만들면 좋을까?)
- 주문리스트를 만들고 프린트 할 것인가?
(주문 버튼을 눌렀을 때, 주문리스트를 만들면 된다.)
→ 리스트를 어떻게 뽑을 것인가?
버튼 클릭하면, 주문내역을 프린트한다.
프로그램에 익숙하다면, 반복문으로 바꿔보자.
위젯과 레이아웃
- 위젯, Display / Qlabel
PyQt 책은 서점에 없다.
(교보문고에 전자책으로 있다.)
→ PyQt를 인터넷에 검색하면 잘 나온다.
PyQt를 활용한 GUI 프로그램
PyQt로 뭘 하기보단, 파이썬 기본문법에서 클래스에 대한 이해
클래스를 바탕으로 작성된 코드를 응용할 일에 대비해 적응하는 시간을 가지자는 의미에서 PyQt를 배운다.
예를 들어서, 경제학과 나오면 꼭 경제학 관련 일을 하는 것이 아니니 프로그램을 배울 때도 넓은 시야로 시작하면 좋다.
신입 엔지니어에게 10대 코딩 中 블록코딩을 시켰었다.
신입 사원은 엔지니어가 되고 싶은 사람이다.
다루는 범위는 제법 많다.
Graphic User Interface
함수를 통해서 값을 가져오도록 한다.
문자열로 하면 error가 나온다.
프로그램이 돌다가 문제없을 거라 여겼던, error가 생기기도 한다.
sys module
import sys
# sys.argv - 명령 행에서 입력된 인수가 저장되어 있음
# $ python sys_module_test.py hello.py
# ['sys_module_test.py', 'hello.py']
print(sys.argv)
#sys.exit() - 스크립트 강제 종료
x = 0
while True:
if x == 5:
sys.exit()
else:
print(x)
x += 1
- 출력결과
- 프롬프트: 박근혜 대통령 당시부터 나온 단어
아나운서가 말을 할 때, 스크립트가 카메라 밑에 붙어져 있다.
(살짝 시선이 떨어진다.)
→ 카메라 렌즈 밑에 붙여둔다. (프롬프트라고 부른다.)
이런 프롬프트가 아닌, 명령을 대기하는 것도 프롬프트라고 부른다.
‘.’ ⇒ 현재 디렉토리에 있다.
\\ ⇒
경로, 소스코드 이름, 옵션
- PyQt란 무엇인가?
Python + Qt를 합쳤다는 의미에서 PyQt라고 이름을 붙였으며, C++ 기반의 GUI Framework인 Qt를 Python에서 사용할 수 있게 만든 패키지(Qt의 레이아웃에 Python의 코드를 연결하여 GUI 프로그램을 만들 수 있게 해주는 프레임워크).
PyQt는 C++의 Cross Platform GUI Franwork인 Qt를 영국의 Riverbank Computing에서 Python 모듈로 변환해 주는 툴을 만들면서 시작 되었음.
(PyQt4 버전과 PyQt 5버전이 주로 사용되고 있음.)
- PyQt의 특징
Python에도 PyGTK, PySide, Tkinter 등 다양한 GUI Framework가 존재하지만 이러한 GUI Frame은 사용하기 어렵고 시각적으로 이쁘지 않다는 단점이 있음.
app = 프로그램 = 객체
→ 프로그램 객체, 윈도우 객체 각각 하나씩 만들어서 실행한다.
창 하나, 프로그램 하나 만들면 유기적으로 돌아간다.
프로그램 하나 실행해서 출력되는 결과가 당연하다고 생각하지만, 많은 것들이 들어가 있다.
라이브러리: 전체적인 흐름을 따라가게 만들어져 있다.
프레임워크: 속에 보이지 않는 구조물이 있다. (보이지 않는 손이 있다.)
myWindow 안에 QWidget() 클래스 지정한 뒤, 새로운 생성자로 지정하였다.
- MyWindow 클래스 생성
MyWindow 클래스 생성
: QMainWindow 클래스로부터 상속을 받아 MyWindow 클래스 정의
: MyWindow 클래스의 인스턴스 생성
→ myWindow = MyWindow()
: ‘PyQt 첫 번째 코딩’ 에서는 Qwidget 클래스의 인스턴스 생성
PyQt 세 번째 코딩
: 클래스 초기화 함수
init(self)
super().init()
: 윈도우 타이틀 지정
setWindowTitle(’My PyQt Window’)
: 윈도우 크기 지정(변경)
setGeometry(x, y, width, height)
→ x, y : 모니터 좌표
→ width, height : ‘윈도우’의 폭의 높이
폭: 320
높이: 180
#빔 프로젝트는 가로 1,024px 세로 684px로 나눠서 보여준다.
클래스 개념으로 프로그램을 짜면 어떤가?
- PyQt - Hello World!
: 필요한 클래스만 import 함
: myWindow 인스턴스
QtWidget을 상속 받은 HelloWorldWindow 클래스로 생성함
QtWidget 클래스가 가지고 있는 여러 메서드를 사용할 수 있음
setWindowTitle(), setGeometry()
QLabel()
: 라벨 객체를 생성
setText()
: 객체의 텍스트 속성 값을 지정
move()
: 객체를 지정된 위치로 이동
앞으로 어떤 객체에 텍스트를 쓰고 싶다.
class 정의: 파이썬 인터프리터가 이렇게 설계했다는 부분
Qt Designer 설치
- Qt Designer
: PyQt를 이용하여 GUI 프로그래밍을 할 때 손쉽게 프로그램의 레이아웃을 편집할 수 있게 해주는 편집기
- PyQt 및 Qt Designer 설치
→ Windows의 cmd 창에서 실행
-> pip install pyqt5
-> pip install pyqt5-tools
⇒ PyQt를 이용해서 사용자 인터페이스를 제작할 수 있다.
템플릿(templates)
위젯(Widgets)
geometry
- x, y: 위치값
- 너비, 높이: 조정값
Qt Designer 위젯의 속성
: 위젯 마다 속성이 조금씩 다르지만 공통적으로 가지고 있는 속성이 다수 있음.
자주 사용되는 속성들
- ObjectName : Python 코드에서 사용될 위젯의 이름을 설정.
- Gemometry : 위젯의 x, y 좌표와 폭과 높이를 지정
- Palette : 위젯의 색상을 지정
- Font : 글자의 폰트와 크기 지정
- ToolTip : 위젯 위에 마우스를 올려 놓았을 때 해당 위젯에 대한 정보를 제공하는 글자 출력
- TooTipDuration : tooltip이 얼마 동안 보여질지 시간 지정, 단위는 millisecond
- TooTipDration이 1이면 해당 위젯에 마우스가 올려져 있으면 지속적으로 tooltip를 출력
UI와 Python 코드의 연결하는 방법
: UI 파일을 Python 코드에서 import하는 방법
# filename - PushButtonTest.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
# UI 파일 연결
# UI 파일이 "현재 작업 디렉토리/ui" 디렉토리에 있다고 가정
form_class = uic.loadUiType('./ui/PushButtenTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
# filename – PushButtonTest.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
# UI 파일 연결
# UI 파일이 "현재 작업 디렉토리/ui" 디렉토리에 있다고 가정
form_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
정리: PyQt 시작
- PyQt란 무엇인가?
Python + Qt를 합쳤다는 의미에서 PyQt라고 이름을 붙였으며, C++ 기반의 GUI Framework인 Qt를 Python에서 사용할 수 있게 만든 패키지(Qt의 레이아웃에 Python의 코드를 연결하여 GUI 프로그램을 만들 수 있게 해주는 프레임워크).
특징: Python에도 PyGTK, PySide, Tkinter 등 다양한 GUI Framework가 존재하지만 이러한 GUI Frame은 사용하기 어렵고 시각적으로 이쁘지 않다는 단점이 있음.
- Qt Designer의 설치
- Qt Designer의 화면 구성
- Qt Designer를 이용한 UI 제작과 연결
일을 시켜서 하는 사람이 있다.
컴퓨터없이 수업 하는 사람은 프린터물을 나눠주고 수업을 진행
빔 프로젝트도 없이 수업을 진행하다.
→ 조직이 원하는 것과 내가 원하는 것이 같으면 좋다.
자기가 하고싶은 일과 회사가 요구하는 일이 맞으면 시너지효과다.
프로그램은 안 시키는 것은 하지 않는다.
⇒ 명령하지 않은 것이 나타나거나, 실행되지 않으면 작성자의 잘못이다.
객체 입장에서는 이벤트(사건)가 발생한 것이다.
→ 지시를 해줘야 한다.
시그널(Signal)과 슬롯(Slot)
- 시그널(Signal)
위젯의 성태가 바뀌었을 때 위젯에서 특정 시그널(이벤트)이 발생
→ 위젯에서 신호를 내보냄
Ex) 버튼 위젯이 클릭되었을 때 어떤 동작(함수)을 수행하거나 다이얼 위젯을 돌렸을 때 화면에 다른 값이 출력되게 하는 동작(함수)을 지정
#시그널이 발생했을 때 신호를 내보내고, 어떤 기능을 하라고 짝을 지어주는데, 이것을 슬록이라고 부른다.
[예전에는 (시그널 = 이벤트)와 (슬롯 = 이벤트 핸들러)라고 불렀다.]
⇒ 슬롯은 시그널과 연결된 함수이다.
- 슬롯(Slot)
: 함수 개념
: 위젯에서 특정 신호(시그널)가 발생 했을 때 해당 시그널(이벤트)을 처리할 슬롯(이벤트 핸들러)을 지정할 수 있음
: 시그널에 처리를 위해 특정 시그널에 대해 슬롯(함수) 지정할 수 있음
- 함수 vs 슬롯
어떤 변화(이벤트, 시그널)가 없더라도 실행될 수 있는 코드
함수는 보통 위젯의 값을 설정하거나 위젯의 값을 가져오거나 위젯의 속성을 변경할 때 사용
PyQt에서 대부분의 위젯들이 공통적으로 사용하는 함수들이 몇 가지 있음.
- “Qt Designer를 이용한 UI 제작” 부분에서 어떻게 Qt Designer를 이용하여 UI 파일과 Python 코드를 연결하는지에 대해서 살펴 봤음(그때는 화면에 보인 위젯들은 아무런 기능을 하지 않았음).
- 위젯이 변화했을 때 어떤 동작을 하게 하기 위해서는 무엇을 해야 하는가?
위젯에서 발생한 시그널을 처리하는 슬롯이 있어야 함
시그널과 슬롯을 연결해야 함
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uicform_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
# 이 부분에 시그널과 슬롯을 연결하는 코드
# 여기에 슬롯(함수) 정의
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
# filename – PushButtonSignal.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
# QPushButton 위젯(btnA)에서 클릭 시그널이 발생하면
# btnA_function() 슬롯에 연결
self.btnA.clicked.connect(self.btnA_function)
# btnA_function() 슬롯 정의
def btnA_function(self):
print('Button A Clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
클릭하면 클릭했다는 신호가 발생한다.
#원래 선생의 말은 30% 정도만 들리더라.
강사는 노가다 = 움직이는 만큼 돈을 번다.
→ 회사는 아니다.
- 사업과 장사의 차이는 무엇인가?
백종원: 사업
사업: 시스템이 하는 것
장사: 자신이 직접 하는 것
알아서 하라고 하면 싫어한다.
(일을 맡긴다는 것은, 책임과 권한을 주는 것이다.)
같이 고민해서 ‘중학교 2학년’ 대상으로 어떤 것을 먹을지 생각한다.
자신이 없어도 돌아가는 시스템을 구축해야 한다.
→ 다시 끌어올리기 위해 고민하는 중이다.
내가 연봉을 그만큼 받기 위해선, 그런 능력이 있어야하고, 증명해서 동의해야 한다.
문제가 있으면, 스스로 얘기를 해서 해결해야 한다.
요점: 나의 연봉을 증가시키려면 어떻게 해야 하는가?
→ 방법을 찾고 있다.
- 구체적으로 행동하면서 실패해봐야 안다.
QRadioButton vs QCheckButton
n개 중에 1개를 선택할 때, Radio버튼으로 구현한다.
위젯 상자의 Containers 안에 있는 GroupBox
위젯 상자의 Button 안에 있는 Radio Button
물어볼 때는 라디오 버튼 중 1개만 잡는다.
→ n개 중에서 하나를 선택하라는 질문을 할 때 일반적으로 많이 사용하는 방법이다.
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/RadioButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.rBtn1.clicked.connect(self.groupBox_rbtn_function)
self.rBtn2.clicked.connect(self.groupBox_rbtn_function)
self.rBtn3.clicked.connect(self.groupBox_rbtn_function)
def groupBox_rbtn_function(self):
if self.rBtn1.isChecked():
print('RadioButtin1 Checked')
elif self.rBtn2.isChecked():
print('RadioButten2 Checked')
elif self.rBtn3.isChecked():
print("RadioButton3 Checked")
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
실행결과
PPT를 한번 만들었다가, 다시 만들었다.
기본구조 잡아보기 → 라벨 붙여보기 → 버튼 넣어보기 → 디자인을 써서 버튼을 하나 달고, 반응을 하기 위해 signal과 slot이 연결된다.
위젯, Buttons / Push Button
- UI 파일 생성 - QPushButton 위젯 두 개를 Dialog 창에 올려 놓기
텍스트 속성, 위치는 바꿔도 영향 X
**import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType("PushButtons.ui")[0]
class WindowClass(QMainWindow, form_class) :
def __init__(self) :
super().__init__()
self.setupUi(self)
self.btnA.clicked.connect(self.btnAFunction)
self.btnB.clicked.connect(self.btnBFunction)
def btnAFunction(self) :
print(self.btnA.text() + " Clicked")
QMessageBox.information(self, "Info", "Button A Clicked")
def btnBFunction(self) :
print(self.btnB.text() + " Clicked")
QMessageBox.information(self, "Info", "Button B Clicked")
if __name__ == "__main__" :
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()**
- QCheckBox
계층 구조
: Dialog > Button
: Dialog > Containers > Button
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/CheckBoxTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.groupChkBox1.stateChanged.connect(self.group_chk_function)
self.groupChkBox2.stateChanged.connect(self.group_chk_function)
self.ChkBox1.stateChanged.connect(self.chk_function)
self.ChkBox2.stateChanged.connect(self.chk_function)
def group_chk_function(self):
if self.groupChkBox1.isChecked() : print('CheckBox1 in group is Checked')
if self.groupChkBox2.isChecked() : print('CheckBox2 in group is Checked')
def chk_function(self):
if self.ChkBox1.isChecked() : print('CheckBox1 is Checked')
if self.ChkBox2.isChecked() : print('CheckBox2 is Checked')
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
⇒ 출력결과
- 체크박스 안에 1번만 클릭하면, 1번에 대한 출력결과가 나오고
- 체크박스 안에 1번 클릭 후 2번을 클릭하면, 둘 다에 대한 출력결과가 나오고
- 체크박스 밖에 1번만 클릭하면, 밖에 1번에 대한 출력결과가 나오고
- 체크박스 밖에 1번 클릭 후 2번을 클릭하면, 밖에 있는 둘 다에 대한 출력결과가 나온다.
체크박스 안과 밖을 클릭하면, 나중에 클릭한 것에 대한 출력결과가 나온다.
(안을 먼저 클릭하면 밖에 대한 결과가 나오고, 밖을 먼저 클릭하면 밖에 대한 결과가 나온다.)
주문 시스템 만들기
- Window 디자인
GroupBox, CheckBox (GroupBox와 CheckBox의 텍스트(test) 속성 설정)
예전에 주문시스템을 만들면 어떨까?
→ 이용객들이 키오스크 문화에 익숙하지 않았다.
객체 이름
- 자장면 → chkBox_A0
- 짬뽕 → chkBox_A1
- 탕수육 → chkBox_B0
- 양장피 → chkBox_B1
- 팔보채 → chkBox_B2
동작
- 주문 내역을 주방에 출력
→ Terminal 창에 주문 내역을 print 하시오.
클릭 후, 주문버튼을 누르면 주문이 되는 방식으로 구상해야 한다.
- 가위바위보 게임 샘플
import sys
from random import randint
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
# from PyQt5.QtWid
class MainWindow(QDialog):
def __init__(self):
super().__init__()
self.setup_ui()
def setup_ui(self):
main_layout = QVBoxLayout() #메인 레이아웃
user_choose_layout = QHBoxLayout() #버튼 담길 레이아웃
#타이틀 지정
title = QLabel("허접한 가위바위보")
title_font = title.font()
# title_font.setPointSize(25)
title_font = QFont("나눔고딕코딩", 25, QFont.Bold)
title.setFont(title_font)
title.setAlignment(Qt.AlignCenter)
# 이미지 불러오기 및 이미지 사이즈 강제조정
rock_image = QPixmap('주먹.png')
rock_image = rock_image.scaled(50,50,Qt.IgnoreAspectRatio)
scissor_image = QPixmap('가위.png')
scissor_image = scissor_image.scaled(50, 50, Qt.IgnoreAspectRatio)
paper_image = QPixmap('보.png')
paper_image = paper_image.scaled(50, 50, Qt.IgnoreAspectRatio)
# 가위바위보 버튼 , 종료 버튼
self.scissor_btn = QPushButton('가위')
self.rock_btn = QPushButton('바위')
self.paper_btn = QPushButton('보')
quit_btn = QPushButton("종료하기", self)
#버튼 이름 숨기기
# self.scissor_btn.setProperty("orgtext", scissor_btn)
# self.scissor_btn.setText("가위")
#종료버튼 눌렀을 때 종료하기
quit_btn.clicked.connect(self.close)
#버튼에 이미지 넣기 및 버튼 사이즈 조정
self.scissor_btn.setIcon(QIcon(scissor_image))
self.scissor_btn.setIconSize(QSize(70, 70))
self.rock_btn.setIcon(QIcon(rock_image))
self.rock_btn.setIconSize(QSize(70, 70))
self.paper_btn.setIcon(QIcon(paper_image))
self.paper_btn.setIconSize(QSize(70, 70))
#버튼 누르면 이벤트
self.scissor_btn.clicked.connect(self.game_play)
self.rock_btn.clicked.connect(self.game_play)
self.paper_btn.clicked.connect(self.game_play)
#화면 나올 창
# self.image = QLabel()
#레이아웃 담아주기
user_choose_layout.addWidget(self.rock_btn)
user_choose_layout.addWidget(self.paper_btn)
user_choose_layout.addWidget(self.scissor_btn)
main_layout.addWidget(title)
# main_layout.addWidget(image)
main_layout.addLayout(user_choose_layout)
main_layout.addWidget(quit_btn)
self.setWindowTitle("가위바위보게임")
self.setLayout(main_layout)
self.show()
def game_play(self):
# global com_guess
random_num = randint(1, 3)
print(random_num)
if random_num == 1:
com_guess = '가위'
elif random_num == 2:
com_guess = '바위'
if random_num == 3:
com_guess = '보'
reply = QMessageBox() #응답이 받아질 메세지박스
reply.setWindowTitle('결과는!') #메세지박스 상단 텍스트
sender = self.sender() #눌린 버튼을 가져옴
btn_name = sender.text() #눌린 버튼의 이름을 가져옴
if (random_num == 1 and btn_name == '가위') or \\
(random_num == 2 and btn_name == '바위') or \\
(random_num == 3 and btn_name == '보'):
# draw_img = QPixmap('yelled_pingu.jpg')
# draw_img.
reply.setIconPixmap(QPixmap('yelled_pingu.jpg'))
reply.setText(f"비겼습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
elif (random_num == 1 and btn_name == '바위') or \\
(random_num == 2 and btn_name == '보') or \\
(random_num == 3 and btn_name == '가위'):
reply.setIconPixmap(QPixmap('smile_pingu.jpg'))
reply.setText(f"이겼습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
else:
reply.setIconPixmap(QPixmap('angry_pingu2.png'))
reply.setText(f"졌습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
def closeEvent(self, event):
# 종료 대화상자 표시
reply = QMessageBox.question(self, '종료확인', '종료하시겠습니까?',
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
# '예' 버튼을 클릭하면 종료
event.accept()
else:
# '아니오' 버튼을 클릭하면 이벤트 무시
event.ignore()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainWindow()
# MainWindow.show()
sys.exit(app.exec_())
이번주 월, 화는 PyQt수업
수, 목, 금은 데이터 분석 기초
다음주 월, 화, 수는 박태우 강사님 수업
다음 주 목, 금은 데이터 분석 기초
다다음주는 MySQL
이후, 웹 서버로 넘어간다.
- 자바 스크립트 → Node.js(자바 스크립트 업그레아드 버전)
이후 데이터분석으로 본격적으로 들어간다.
(원래 날짜가 정해져있지만, 상황에 따라 탄력적으로 운영한다.)
3월 초에도 데이터분석을 이어간다.
웹 크롤링도 하기 나름이다.
(일단, 파이썬에 적응해야 한다.)
보통 웹 크롤링으로 데이터를 모으려고 하진 않는다.
웹 크롤링은 시간이 많이 걸린다.
(여력 있으면 하고, 없으면 넘어가도 된다.)
데이터베이스 수업이 일주일 정도 잡혀있지만, Node.js에서 사용하는 데이터베이스와 MySQL 데이터베이스가 조금 다르다.
작년에는 여름에 시작해서 가을이었다.
추석끼고 나서 조금 분위기가 해이해졌다.
우리는 설날을 잘 보내야 탄력이 유지되지 않을까싶다.
터미널 창에 주문내역을 프린트하는데,
클릭할 때마다 프린트하는 건 아니다.
→ 이번에는 주문 눌렀을 때 프린트하면 된다.
(체크상태를 보고 주문을 해야한다.)
주문한 리스트가 있어야 하는데, 언제 주문리스트를 만들 것인가?
(프린트한 내용은 언제 만들면 좋을까?)
- 주문리스트를 만들고 프린트 할 것인가?
(주문 버튼을 눌렀을 때, 주문리스트를 만들면 된다.)
→ 리스트를 어떻게 뽑을 것인가?
버튼 클릭하면, 주문내역을 프린트한다.
프로그램에 익숙하다면, 반복문으로 바꿔보자.
위젯과 레이아웃
- 위젯, Display / Qlabel
PyQt 책은 서점에 없다.
(교보문고에 전자책으로 있다.)
→ PyQt를 인터넷에 검색하면 잘 나온다.
PyQt를 활용한 GUI 프로그램
PyQt로 뭘 하기보단, 파이썬 기본문법에서 클래스에 대한 이해
클래스를 바탕으로 작성된 코드를 응용할 일에 대비해 적응하는 시간을 가지자는 의미에서 PyQt를 배운다.
예를 들어서, 경제학과 나오면 꼭 경제학 관련 일을 하는 것이 아니니 프로그램을 배울 때도 넓은 시야로 시작하면 좋다.
신입 엔지니어에게 10대 코딩 中 블록코딩을 시켰었다.
신입 사원은 엔지니어가 되고 싶은 사람이다.
다루는 범위는 제법 많다.
Graphic User Interface
함수를 통해서 값을 가져오도록 한다.
문자열로 하면 error가 나온다.
프로그램이 돌다가 문제없을 거라 여겼던, error가 생기기도 한다.
sys module
import sys
# sys.argv - 명령 행에서 입력된 인수가 저장되어 있음
# $ python sys_module_test.py hello.py
# ['sys_module_test.py', 'hello.py']
print(sys.argv)
#sys.exit() - 스크립트 강제 종료
x = 0
while True:
if x == 5:
sys.exit()
else:
print(x)
x += 1
- 출력결과
- 프롬프트: 박근혜 대통령 당시부터 나온 단어
아나운서가 말을 할 때, 스크립트가 카메라 밑에 붙어져 있다.
(살짝 시선이 떨어진다.)
→ 카메라 렌즈 밑에 붙여둔다. (프롬프트라고 부른다.)
이런 프롬프트가 아닌, 명령을 대기하는 것도 프롬프트라고 부른다.
‘.’ ⇒ 현재 디렉토리에 있다.
\\ ⇒
경로, 소스코드 이름, 옵션
- PyQt란 무엇인가?
Python + Qt를 합쳤다는 의미에서 PyQt라고 이름을 붙였으며, C++ 기반의 GUI Framework인 Qt를 Python에서 사용할 수 있게 만든 패키지(Qt의 레이아웃에 Python의 코드를 연결하여 GUI 프로그램을 만들 수 있게 해주는 프레임워크).
PyQt는 C++의 Cross Platform GUI Franwork인 Qt를 영국의 Riverbank Computing에서 Python 모듈로 변환해 주는 툴을 만들면서 시작 되었음.
(PyQt4 버전과 PyQt 5버전이 주로 사용되고 있음.)
- PyQt의 특징
Python에도 PyGTK, PySide, Tkinter 등 다양한 GUI Framework가 존재하지만 이러한 GUI Frame은 사용하기 어렵고 시각적으로 이쁘지 않다는 단점이 있음.
app = 프로그램 = 객체
→ 프로그램 객체, 윈도우 객체 각각 하나씩 만들어서 실행한다.
창 하나, 프로그램 하나 만들면 유기적으로 돌아간다.
프로그램 하나 실행해서 출력되는 결과가 당연하다고 생각하지만, 많은 것들이 들어가 있다.
라이브러리: 전체적인 흐름을 따라가게 만들어져 있다.
프레임워크: 속에 보이지 않는 구조물이 있다. (보이지 않는 손이 있다.)
myWindow 안에 QWidget() 클래스 지정한 뒤, 새로운 생성자로 지정하였다.
- MyWindow 클래스 생성
MyWindow 클래스 생성
: QMainWindow 클래스로부터 상속을 받아 MyWindow 클래스 정의
: MyWindow 클래스의 인스턴스 생성
→ myWindow = MyWindow()
: ‘PyQt 첫 번째 코딩’ 에서는 Qwidget 클래스의 인스턴스 생성
PyQt 세 번째 코딩
: 클래스 초기화 함수
init(self)
super().init()
: 윈도우 타이틀 지정
setWindowTitle(’My PyQt Window’)
: 윈도우 크기 지정(변경)
setGeometry(x, y, width, height)
→ x, y : 모니터 좌표
→ width, height : ‘윈도우’의 폭의 높이
폭: 320
높이: 180
#빔 프로젝트는 가로 1,024px 세로 684px로 나눠서 보여준다.
클래스 개념으로 프로그램을 짜면 어떤가?
- PyQt - Hello World!
: 필요한 클래스만 import 함
: myWindow 인스턴스
QtWidget을 상속 받은 HelloWorldWindow 클래스로 생성함
QtWidget 클래스가 가지고 있는 여러 메서드를 사용할 수 있음
setWindowTitle(), setGeometry()
QLabel()
: 라벨 객체를 생성
setText()
: 객체의 텍스트 속성 값을 지정
move()
: 객체를 지정된 위치로 이동
앞으로 어떤 객체에 텍스트를 쓰고 싶다.
class 정의: 파이썬 인터프리터가 이렇게 설계했다는 부분
Qt Designer 설치
- Qt Designer
: PyQt를 이용하여 GUI 프로그래밍을 할 때 손쉽게 프로그램의 레이아웃을 편집할 수 있게 해주는 편집기
- PyQt 및 Qt Designer 설치
→ Windows의 cmd 창에서 실행
-> pip install pyqt5
-> pip install pyqt5-tools
⇒ PyQt를 이용해서 사용자 인터페이스를 제작할 수 있다.
템플릿(templates)
위젯(Widgets)
geometry
- x, y: 위치값
- 너비, 높이: 조정값
Qt Designer 위젯의 속성
: 위젯 마다 속성이 조금씩 다르지만 공통적으로 가지고 있는 속성이 다수 있음.
자주 사용되는 속성들
- ObjectName : Python 코드에서 사용될 위젯의 이름을 설정.
- Gemometry : 위젯의 x, y 좌표와 폭과 높이를 지정
- Palette : 위젯의 색상을 지정
- Font : 글자의 폰트와 크기 지정
- ToolTip : 위젯 위에 마우스를 올려 놓았을 때 해당 위젯에 대한 정보를 제공하는 글자 출력
- TooTipDuration : tooltip이 얼마 동안 보여질지 시간 지정, 단위는 millisecond
- TooTipDration이 1이면 해당 위젯에 마우스가 올려져 있으면 지속적으로 tooltip를 출력
UI와 Python 코드의 연결하는 방법
: UI 파일을 Python 코드에서 import하는 방법
# filename - PushButtonTest.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
# UI 파일 연결
# UI 파일이 "현재 작업 디렉토리/ui" 디렉토리에 있다고 가정
form_class = uic.loadUiType('./ui/PushButtenTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
# filename – PushButtonTest.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
# UI 파일 연결
# UI 파일이 "현재 작업 디렉토리/ui" 디렉토리에 있다고 가정
form_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
정리: PyQt 시작
- PyQt란 무엇인가?
Python + Qt를 합쳤다는 의미에서 PyQt라고 이름을 붙였으며, C++ 기반의 GUI Framework인 Qt를 Python에서 사용할 수 있게 만든 패키지(Qt의 레이아웃에 Python의 코드를 연결하여 GUI 프로그램을 만들 수 있게 해주는 프레임워크).
특징: Python에도 PyGTK, PySide, Tkinter 등 다양한 GUI Framework가 존재하지만 이러한 GUI Frame은 사용하기 어렵고 시각적으로 이쁘지 않다는 단점이 있음.
- Qt Designer의 설치
- Qt Designer의 화면 구성
- Qt Designer를 이용한 UI 제작과 연결
일을 시켜서 하는 사람이 있다.
컴퓨터없이 수업 하는 사람은 프린터물을 나눠주고 수업을 진행
빔 프로젝트도 없이 수업을 진행하다.
→ 조직이 원하는 것과 내가 원하는 것이 같으면 좋다.
자기가 하고싶은 일과 회사가 요구하는 일이 맞으면 시너지효과다.
프로그램은 안 시키는 것은 하지 않는다.
⇒ 명령하지 않은 것이 나타나거나, 실행되지 않으면 작성자의 잘못이다.
객체 입장에서는 이벤트(사건)가 발생한 것이다.
→ 지시를 해줘야 한다.
시그널(Signal)과 슬롯(Slot)
- 시그널(Signal)
위젯의 성태가 바뀌었을 때 위젯에서 특정 시그널(이벤트)이 발생
→ 위젯에서 신호를 내보냄
Ex) 버튼 위젯이 클릭되었을 때 어떤 동작(함수)을 수행하거나 다이얼 위젯을 돌렸을 때 화면에 다른 값이 출력되게 하는 동작(함수)을 지정
#시그널이 발생했을 때 신호를 내보내고, 어떤 기능을 하라고 짝을 지어주는데, 이것을 슬록이라고 부른다.
[예전에는 (시그널 = 이벤트)와 (슬롯 = 이벤트 핸들러)라고 불렀다.]
⇒ 슬롯은 시그널과 연결된 함수이다.
- 슬롯(Slot)
: 함수 개념
: 위젯에서 특정 신호(시그널)가 발생 했을 때 해당 시그널(이벤트)을 처리할 슬롯(이벤트 핸들러)을 지정할 수 있음
: 시그널에 처리를 위해 특정 시그널에 대해 슬롯(함수) 지정할 수 있음
- 함수 vs 슬롯
어떤 변화(이벤트, 시그널)가 없더라도 실행될 수 있는 코드
함수는 보통 위젯의 값을 설정하거나 위젯의 값을 가져오거나 위젯의 속성을 변경할 때 사용
PyQt에서 대부분의 위젯들이 공통적으로 사용하는 함수들이 몇 가지 있음.
- “Qt Designer를 이용한 UI 제작” 부분에서 어떻게 Qt Designer를 이용하여 UI 파일과 Python 코드를 연결하는지에 대해서 살펴 봤음(그때는 화면에 보인 위젯들은 아무런 기능을 하지 않았음).
- 위젯이 변화했을 때 어떤 동작을 하게 하기 위해서는 무엇을 해야 하는가?
위젯에서 발생한 시그널을 처리하는 슬롯이 있어야 함
시그널과 슬롯을 연결해야 함
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uicform_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
# 이 부분에 시그널과 슬롯을 연결하는 코드
# 여기에 슬롯(함수) 정의
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
# filename – PushButtonSignal.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
# QPushButton 위젯(btnA)에서 클릭 시그널이 발생하면
# btnA_function() 슬롯에 연결
self.btnA.clicked.connect(self.btnA_function)
# btnA_function() 슬롯 정의
def btnA_function(self):
print('Button A Clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
클릭하면 클릭했다는 신호가 발생한다.
#원래 선생의 말은 30% 정도만 들리더라.
강사는 노가다 = 움직이는 만큼 돈을 번다.
→ 회사는 아니다.
- 사업과 장사의 차이는 무엇인가?
백종원: 사업
사업: 시스템이 하는 것
장사: 자신이 직접 하는 것
알아서 하라고 하면 싫어한다.
(일을 맡긴다는 것은, 책임과 권한을 주는 것이다.)
같이 고민해서 ‘중학교 2학년’ 대상으로 어떤 것을 먹을지 생각한다.
자신이 없어도 돌아가는 시스템을 구축해야 한다.
→ 다시 끌어올리기 위해 고민하는 중이다.
내가 연봉을 그만큼 받기 위해선, 그런 능력이 있어야하고, 증명해서 동의해야 한다.
문제가 있으면, 스스로 얘기를 해서 해결해야 한다.
요점: 나의 연봉을 증가시키려면 어떻게 해야 하는가?
→ 방법을 찾고 있다.
- 구체적으로 행동하면서 실패해봐야 안다.
QRadioButton vs QCheckButton
n개 중에 1개를 선택할 때, Radio버튼으로 구현한다.
위젯 상자의 Containers 안에 있는 GroupBox
위젯 상자의 Button 안에 있는 Radio Button
물어볼 때는 라디오 버튼 중 1개만 잡는다.
→ n개 중에서 하나를 선택하라는 질문을 할 때 일반적으로 많이 사용하는 방법이다.
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/RadioButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.rBtn1.clicked.connect(self.groupBox_rbtn_function)
self.rBtn2.clicked.connect(self.groupBox_rbtn_function)
self.rBtn3.clicked.connect(self.groupBox_rbtn_function)
def groupBox_rbtn_function(self):
if self.rBtn1.isChecked():
print('RadioButtin1 Checked')
elif self.rBtn2.isChecked():
print('RadioButten2 Checked')
elif self.rBtn3.isChecked():
print("RadioButton3 Checked")
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
실행결과
PPT를 한번 만들었다가, 다시 만들었다.
기본구조 잡아보기 → 라벨 붙여보기 → 버튼 넣어보기 → 디자인을 써서 버튼을 하나 달고, 반응을 하기 위해 signal과 slot이 연결된다.
위젯, Buttons / Push Button
- UI 파일 생성 - QPushButton 위젯 두 개를 Dialog 창에 올려 놓기
텍스트 속성, 위치는 바꿔도 영향 X
**import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType("PushButtons.ui")[0]
class WindowClass(QMainWindow, form_class) :
def __init__(self) :
super().__init__()
self.setupUi(self)
self.btnA.clicked.connect(self.btnAFunction)
self.btnB.clicked.connect(self.btnBFunction)
def btnAFunction(self) :
print(self.btnA.text() + " Clicked")
QMessageBox.information(self, "Info", "Button A Clicked")
def btnBFunction(self) :
print(self.btnB.text() + " Clicked")
QMessageBox.information(self, "Info", "Button B Clicked")
if __name__ == "__main__" :
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()**
- QCheckBox
계층 구조
: Dialog > Button
: Dialog > Containers > Button
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/CheckBoxTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.groupChkBox1.stateChanged.connect(self.group_chk_function)
self.groupChkBox2.stateChanged.connect(self.group_chk_function)
self.ChkBox1.stateChanged.connect(self.chk_function)
self.ChkBox2.stateChanged.connect(self.chk_function)
def group_chk_function(self):
if self.groupChkBox1.isChecked() : print('CheckBox1 in group is Checked')
if self.groupChkBox2.isChecked() : print('CheckBox2 in group is Checked')
def chk_function(self):
if self.ChkBox1.isChecked() : print('CheckBox1 is Checked')
if self.ChkBox2.isChecked() : print('CheckBox2 is Checked')
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
⇒ 출력결과
- 체크박스 안에 1번만 클릭하면, 1번에 대한 출력결과가 나오고
- 체크박스 안에 1번 클릭 후 2번을 클릭하면, 둘 다에 대한 출력결과가 나오고
- 체크박스 밖에 1번만 클릭하면, 밖에 1번에 대한 출력결과가 나오고
- 체크박스 밖에 1번 클릭 후 2번을 클릭하면, 밖에 있는 둘 다에 대한 출력결과가 나온다.
체크박스 안과 밖을 클릭하면, 나중에 클릭한 것에 대한 출력결과가 나온다.
(안을 먼저 클릭하면 밖에 대한 결과가 나오고, 밖을 먼저 클릭하면 밖에 대한 결과가 나온다.)
주문 시스템 만들기
- Window 디자인
GroupBox, CheckBox (GroupBox와 CheckBox의 텍스트(test) 속성 설정)
예전에 주문시스템을 만들면 어떨까?
→ 이용객들이 키오스크 문화에 익숙하지 않았다.
객체 이름
- 자장면 → chkBox_A0
- 짬뽕 → chkBox_A1
- 탕수육 → chkBox_B0
- 양장피 → chkBox_B1
- 팔보채 → chkBox_B2
동작
- 주문 내역을 주방에 출력
→ Terminal 창에 주문 내역을 print 하시오.
클릭 후, 주문버튼을 누르면 주문이 되는 방식으로 구상해야 한다.
- 가위바위보 게임 샘플
import sys
from random import randint
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
# from PyQt5.QtWid
class MainWindow(QDialog):
def __init__(self):
super().__init__()
self.setup_ui()
def setup_ui(self):
main_layout = QVBoxLayout() #메인 레이아웃
user_choose_layout = QHBoxLayout() #버튼 담길 레이아웃
#타이틀 지정
title = QLabel("허접한 가위바위보")
title_font = title.font()
# title_font.setPointSize(25)
title_font = QFont("나눔고딕코딩", 25, QFont.Bold)
title.setFont(title_font)
title.setAlignment(Qt.AlignCenter)
# 이미지 불러오기 및 이미지 사이즈 강제조정
rock_image = QPixmap('주먹.png')
rock_image = rock_image.scaled(50,50,Qt.IgnoreAspectRatio)
scissor_image = QPixmap('가위.png')
scissor_image = scissor_image.scaled(50, 50, Qt.IgnoreAspectRatio)
paper_image = QPixmap('보.png')
paper_image = paper_image.scaled(50, 50, Qt.IgnoreAspectRatio)
# 가위바위보 버튼 , 종료 버튼
self.scissor_btn = QPushButton('가위')
self.rock_btn = QPushButton('바위')
self.paper_btn = QPushButton('보')
quit_btn = QPushButton("종료하기", self)
#버튼 이름 숨기기
# self.scissor_btn.setProperty("orgtext", scissor_btn)
# self.scissor_btn.setText("가위")
#종료버튼 눌렀을 때 종료하기
quit_btn.clicked.connect(self.close)
#버튼에 이미지 넣기 및 버튼 사이즈 조정
self.scissor_btn.setIcon(QIcon(scissor_image))
self.scissor_btn.setIconSize(QSize(70, 70))
self.rock_btn.setIcon(QIcon(rock_image))
self.rock_btn.setIconSize(QSize(70, 70))
self.paper_btn.setIcon(QIcon(paper_image))
self.paper_btn.setIconSize(QSize(70, 70))
#버튼 누르면 이벤트
self.scissor_btn.clicked.connect(self.game_play)
self.rock_btn.clicked.connect(self.game_play)
self.paper_btn.clicked.connect(self.game_play)
#화면 나올 창
# self.image = QLabel()
#레이아웃 담아주기
user_choose_layout.addWidget(self.rock_btn)
user_choose_layout.addWidget(self.paper_btn)
user_choose_layout.addWidget(self.scissor_btn)
main_layout.addWidget(title)
# main_layout.addWidget(image)
main_layout.addLayout(user_choose_layout)
main_layout.addWidget(quit_btn)
self.setWindowTitle("가위바위보게임")
self.setLayout(main_layout)
self.show()
def game_play(self):
# global com_guess
random_num = randint(1, 3)
print(random_num)
if random_num == 1:
com_guess = '가위'
elif random_num == 2:
com_guess = '바위'
if random_num == 3:
com_guess = '보'
reply = QMessageBox() #응답이 받아질 메세지박스
reply.setWindowTitle('결과는!') #메세지박스 상단 텍스트
sender = self.sender() #눌린 버튼을 가져옴
btn_name = sender.text() #눌린 버튼의 이름을 가져옴
if (random_num == 1 and btn_name == '가위') or \\
(random_num == 2 and btn_name == '바위') or \\
(random_num == 3 and btn_name == '보'):
# draw_img = QPixmap('yelled_pingu.jpg')
# draw_img.
reply.setIconPixmap(QPixmap('yelled_pingu.jpg'))
reply.setText(f"비겼습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
elif (random_num == 1 and btn_name == '바위') or \\
(random_num == 2 and btn_name == '보') or \\
(random_num == 3 and btn_name == '가위'):
reply.setIconPixmap(QPixmap('smile_pingu.jpg'))
reply.setText(f"이겼습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
else:
reply.setIconPixmap(QPixmap('angry_pingu2.png'))
reply.setText(f"졌습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
def closeEvent(self, event):
# 종료 대화상자 표시
reply = QMessageBox.question(self, '종료확인', '종료하시겠습니까?',
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
# '예' 버튼을 클릭하면 종료
event.accept()
else:
# '아니오' 버튼을 클릭하면 이벤트 무시
event.ignore()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainWindow()
# MainWindow.show()
sys.exit(app.exec_())
이번주 월, 화는 PyQt수업
수, 목, 금은 데이터 분석 기초
다음주 월, 화, 수는 박태우 강사님 수업
다음 주 목, 금은 데이터 분석 기초
다다음주는 MySQL
이후, 웹 서버로 넘어간다.
- 자바 스크립트 → Node.js(자바 스크립트 업그레아드 버전)
이후 데이터분석으로 본격적으로 들어간다.
(원래 날짜가 정해져있지만, 상황에 따라 탄력적으로 운영한다.)
3월 초에도 데이터분석을 이어간다.
웹 크롤링도 하기 나름이다.
(일단, 파이썬에 적응해야 한다.)
보통 웹 크롤링으로 데이터를 모으려고 하진 않는다.
웹 크롤링은 시간이 많이 걸린다.
(여력 있으면 하고, 없으면 넘어가도 된다.)
데이터베이스 수업이 일주일 정도 잡혀있지만, Node.js에서 사용하는 데이터베이스와 MySQL 데이터베이스가 조금 다르다.
작년에는 여름에 시작해서 가을이었다.
추석끼고 나서 조금 분위기가 해이해졌다.
우리는 설날을 잘 보내야 탄력이 유지되지 않을까싶다.
터미널 창에 주문내역을 프린트하는데,
클릭할 때마다 프린트하는 건 아니다.
→ 이번에는 주문 눌렀을 때 프린트하면 된다.
(체크상태를 보고 주문을 해야한다.)
주문한 리스트가 있어야 하는데, 언제 주문리스트를 만들 것인가?
(프린트한 내용은 언제 만들면 좋을까?)
- 주문리스트를 만들고 프린트 할 것인가?
(주문 버튼을 눌렀을 때, 주문리스트를 만들면 된다.)
→ 리스트를 어떻게 뽑을 것인가?
버튼 클릭하면, 주문내역을 프린트한다.
프로그램에 익숙하다면, 반복문으로 바꿔보자.
위젯과 레이아웃
- 위젯, Display / Qlabel
PyQt 책은 서점에 없다.
(교보문고에 전자책으로 있다.)
→ PyQt를 인터넷에 검색하면 잘 나온다.
PyQt를 활용한 GUI 프로그램
PyQt로 뭘 하기보단, 파이썬 기본문법에서 클래스에 대한 이해
클래스를 바탕으로 작성된 코드를 응용할 일에 대비해 적응하는 시간을 가지자는 의미에서 PyQt를 배운다.
예를 들어서, 경제학과 나오면 꼭 경제학 관련 일을 하는 것이 아니니 프로그램을 배울 때도 넓은 시야로 시작하면 좋다.
신입 엔지니어에게 10대 코딩 中 블록코딩을 시켰었다.
신입 사원은 엔지니어가 되고 싶은 사람이다.
다루는 범위는 제법 많다.
Graphic User Interface
함수를 통해서 값을 가져오도록 한다.
문자열로 하면 error가 나온다.
프로그램이 돌다가 문제없을 거라 여겼던, error가 생기기도 한다.
sys module
import sys
# sys.argv - 명령 행에서 입력된 인수가 저장되어 있음
# $ python sys_module_test.py hello.py
# ['sys_module_test.py', 'hello.py']
print(sys.argv)
#sys.exit() - 스크립트 강제 종료
x = 0
while True:
if x == 5:
sys.exit()
else:
print(x)
x += 1
- 출력결과
- 프롬프트: 박근혜 대통령 당시부터 나온 단어
아나운서가 말을 할 때, 스크립트가 카메라 밑에 붙어져 있다.
(살짝 시선이 떨어진다.)
→ 카메라 렌즈 밑에 붙여둔다. (프롬프트라고 부른다.)
이런 프롬프트가 아닌, 명령을 대기하는 것도 프롬프트라고 부른다.
‘.’ ⇒ 현재 디렉토리에 있다.
\\ ⇒
경로, 소스코드 이름, 옵션
- PyQt란 무엇인가?
Python + Qt를 합쳤다는 의미에서 PyQt라고 이름을 붙였으며, C++ 기반의 GUI Framework인 Qt를 Python에서 사용할 수 있게 만든 패키지(Qt의 레이아웃에 Python의 코드를 연결하여 GUI 프로그램을 만들 수 있게 해주는 프레임워크).
PyQt는 C++의 Cross Platform GUI Franwork인 Qt를 영국의 Riverbank Computing에서 Python 모듈로 변환해 주는 툴을 만들면서 시작 되었음.
(PyQt4 버전과 PyQt 5버전이 주로 사용되고 있음.)
- PyQt의 특징
Python에도 PyGTK, PySide, Tkinter 등 다양한 GUI Framework가 존재하지만 이러한 GUI Frame은 사용하기 어렵고 시각적으로 이쁘지 않다는 단점이 있음.
app = 프로그램 = 객체
→ 프로그램 객체, 윈도우 객체 각각 하나씩 만들어서 실행한다.
창 하나, 프로그램 하나 만들면 유기적으로 돌아간다.
프로그램 하나 실행해서 출력되는 결과가 당연하다고 생각하지만, 많은 것들이 들어가 있다.
라이브러리: 전체적인 흐름을 따라가게 만들어져 있다.
프레임워크: 속에 보이지 않는 구조물이 있다. (보이지 않는 손이 있다.)
myWindow 안에 QWidget() 클래스 지정한 뒤, 새로운 생성자로 지정하였다.
- MyWindow 클래스 생성
MyWindow 클래스 생성
: QMainWindow 클래스로부터 상속을 받아 MyWindow 클래스 정의
: MyWindow 클래스의 인스턴스 생성
→ myWindow = MyWindow()
: ‘PyQt 첫 번째 코딩’ 에서는 Qwidget 클래스의 인스턴스 생성
PyQt 세 번째 코딩
: 클래스 초기화 함수
init(self)
super().init()
: 윈도우 타이틀 지정
setWindowTitle(’My PyQt Window’)
: 윈도우 크기 지정(변경)
setGeometry(x, y, width, height)
→ x, y : 모니터 좌표
→ width, height : ‘윈도우’의 폭의 높이
폭: 320
높이: 180
#빔 프로젝트는 가로 1,024px 세로 684px로 나눠서 보여준다.
클래스 개념으로 프로그램을 짜면 어떤가?
- PyQt - Hello World!
: 필요한 클래스만 import 함
: myWindow 인스턴스
QtWidget을 상속 받은 HelloWorldWindow 클래스로 생성함
QtWidget 클래스가 가지고 있는 여러 메서드를 사용할 수 있음
setWindowTitle(), setGeometry()
QLabel()
: 라벨 객체를 생성
setText()
: 객체의 텍스트 속성 값을 지정
move()
: 객체를 지정된 위치로 이동
앞으로 어떤 객체에 텍스트를 쓰고 싶다.
class 정의: 파이썬 인터프리터가 이렇게 설계했다는 부분
Qt Designer 설치
- Qt Designer
: PyQt를 이용하여 GUI 프로그래밍을 할 때 손쉽게 프로그램의 레이아웃을 편집할 수 있게 해주는 편집기
- PyQt 및 Qt Designer 설치
→ Windows의 cmd 창에서 실행
-> pip install pyqt5
-> pip install pyqt5-tools
⇒ PyQt를 이용해서 사용자 인터페이스를 제작할 수 있다.
템플릿(templates)
위젯(Widgets)
geometry
- x, y: 위치값
- 너비, 높이: 조정값
Qt Designer 위젯의 속성
: 위젯 마다 속성이 조금씩 다르지만 공통적으로 가지고 있는 속성이 다수 있음.
자주 사용되는 속성들
- ObjectName : Python 코드에서 사용될 위젯의 이름을 설정.
- Gemometry : 위젯의 x, y 좌표와 폭과 높이를 지정
- Palette : 위젯의 색상을 지정
- Font : 글자의 폰트와 크기 지정
- ToolTip : 위젯 위에 마우스를 올려 놓았을 때 해당 위젯에 대한 정보를 제공하는 글자 출력
- TooTipDuration : tooltip이 얼마 동안 보여질지 시간 지정, 단위는 millisecond
- TooTipDration이 1이면 해당 위젯에 마우스가 올려져 있으면 지속적으로 tooltip를 출력
UI와 Python 코드의 연결하는 방법
: UI 파일을 Python 코드에서 import하는 방법
# filename - PushButtonTest.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
# UI 파일 연결
# UI 파일이 "현재 작업 디렉토리/ui" 디렉토리에 있다고 가정
form_class = uic.loadUiType('./ui/PushButtenTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
# filename – PushButtonTest.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
# UI 파일 연결
# UI 파일이 "현재 작업 디렉토리/ui" 디렉토리에 있다고 가정
form_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
정리: PyQt 시작
- PyQt란 무엇인가?
Python + Qt를 합쳤다는 의미에서 PyQt라고 이름을 붙였으며, C++ 기반의 GUI Framework인 Qt를 Python에서 사용할 수 있게 만든 패키지(Qt의 레이아웃에 Python의 코드를 연결하여 GUI 프로그램을 만들 수 있게 해주는 프레임워크).
특징: Python에도 PyGTK, PySide, Tkinter 등 다양한 GUI Framework가 존재하지만 이러한 GUI Frame은 사용하기 어렵고 시각적으로 이쁘지 않다는 단점이 있음.
- Qt Designer의 설치
- Qt Designer의 화면 구성
- Qt Designer를 이용한 UI 제작과 연결
일을 시켜서 하는 사람이 있다.
컴퓨터없이 수업 하는 사람은 프린터물을 나눠주고 수업을 진행
빔 프로젝트도 없이 수업을 진행하다.
→ 조직이 원하는 것과 내가 원하는 것이 같으면 좋다.
자기가 하고싶은 일과 회사가 요구하는 일이 맞으면 시너지효과다.
프로그램은 안 시키는 것은 하지 않는다.
⇒ 명령하지 않은 것이 나타나거나, 실행되지 않으면 작성자의 잘못이다.
객체 입장에서는 이벤트(사건)가 발생한 것이다.
→ 지시를 해줘야 한다.
시그널(Signal)과 슬롯(Slot)
- 시그널(Signal)
위젯의 성태가 바뀌었을 때 위젯에서 특정 시그널(이벤트)이 발생
→ 위젯에서 신호를 내보냄
Ex) 버튼 위젯이 클릭되었을 때 어떤 동작(함수)을 수행하거나 다이얼 위젯을 돌렸을 때 화면에 다른 값이 출력되게 하는 동작(함수)을 지정
#시그널이 발생했을 때 신호를 내보내고, 어떤 기능을 하라고 짝을 지어주는데, 이것을 슬록이라고 부른다.
[예전에는 (시그널 = 이벤트)와 (슬롯 = 이벤트 핸들러)라고 불렀다.]
⇒ 슬롯은 시그널과 연결된 함수이다.
- 슬롯(Slot)
: 함수 개념
: 위젯에서 특정 신호(시그널)가 발생 했을 때 해당 시그널(이벤트)을 처리할 슬롯(이벤트 핸들러)을 지정할 수 있음
: 시그널에 처리를 위해 특정 시그널에 대해 슬롯(함수) 지정할 수 있음
- 함수 vs 슬롯
어떤 변화(이벤트, 시그널)가 없더라도 실행될 수 있는 코드
함수는 보통 위젯의 값을 설정하거나 위젯의 값을 가져오거나 위젯의 속성을 변경할 때 사용
PyQt에서 대부분의 위젯들이 공통적으로 사용하는 함수들이 몇 가지 있음.
- “Qt Designer를 이용한 UI 제작” 부분에서 어떻게 Qt Designer를 이용하여 UI 파일과 Python 코드를 연결하는지에 대해서 살펴 봤음(그때는 화면에 보인 위젯들은 아무런 기능을 하지 않았음).
- 위젯이 변화했을 때 어떤 동작을 하게 하기 위해서는 무엇을 해야 하는가?
위젯에서 발생한 시그널을 처리하는 슬롯이 있어야 함
시그널과 슬롯을 연결해야 함
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uicform_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
# 이 부분에 시그널과 슬롯을 연결하는 코드
# 여기에 슬롯(함수) 정의
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
# filename – PushButtonSignal.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
# QPushButton 위젯(btnA)에서 클릭 시그널이 발생하면
# btnA_function() 슬롯에 연결
self.btnA.clicked.connect(self.btnA_function)
# btnA_function() 슬롯 정의
def btnA_function(self):
print('Button A Clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
클릭하면 클릭했다는 신호가 발생한다.
#원래 선생의 말은 30% 정도만 들리더라.
강사는 노가다 = 움직이는 만큼 돈을 번다.
→ 회사는 아니다.
- 사업과 장사의 차이는 무엇인가?
백종원: 사업
사업: 시스템이 하는 것
장사: 자신이 직접 하는 것
알아서 하라고 하면 싫어한다.
(일을 맡긴다는 것은, 책임과 권한을 주는 것이다.)
같이 고민해서 ‘중학교 2학년’ 대상으로 어떤 것을 먹을지 생각한다.
자신이 없어도 돌아가는 시스템을 구축해야 한다.
→ 다시 끌어올리기 위해 고민하는 중이다.
내가 연봉을 그만큼 받기 위해선, 그런 능력이 있어야하고, 증명해서 동의해야 한다.
문제가 있으면, 스스로 얘기를 해서 해결해야 한다.
요점: 나의 연봉을 증가시키려면 어떻게 해야 하는가?
→ 방법을 찾고 있다.
- 구체적으로 행동하면서 실패해봐야 안다.
QRadioButton vs QCheckButton
n개 중에 1개를 선택할 때, Radio버튼으로 구현한다.
위젯 상자의 Containers 안에 있는 GroupBox
위젯 상자의 Button 안에 있는 Radio Button
물어볼 때는 라디오 버튼 중 1개만 잡는다.
→ n개 중에서 하나를 선택하라는 질문을 할 때 일반적으로 많이 사용하는 방법이다.
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/RadioButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.rBtn1.clicked.connect(self.groupBox_rbtn_function)
self.rBtn2.clicked.connect(self.groupBox_rbtn_function)
self.rBtn3.clicked.connect(self.groupBox_rbtn_function)
def groupBox_rbtn_function(self):
if self.rBtn1.isChecked():
print('RadioButtin1 Checked')
elif self.rBtn2.isChecked():
print('RadioButten2 Checked')
elif self.rBtn3.isChecked():
print("RadioButton3 Checked")
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
실행결과
PPT를 한번 만들었다가, 다시 만들었다.
기본구조 잡아보기 → 라벨 붙여보기 → 버튼 넣어보기 → 디자인을 써서 버튼을 하나 달고, 반응을 하기 위해 signal과 slot이 연결된다.
위젯, Buttons / Push Button
- UI 파일 생성 - QPushButton 위젯 두 개를 Dialog 창에 올려 놓기
텍스트 속성, 위치는 바꿔도 영향 X
**import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType("PushButtons.ui")[0]
class WindowClass(QMainWindow, form_class) :
def __init__(self) :
super().__init__()
self.setupUi(self)
self.btnA.clicked.connect(self.btnAFunction)
self.btnB.clicked.connect(self.btnBFunction)
def btnAFunction(self) :
print(self.btnA.text() + " Clicked")
QMessageBox.information(self, "Info", "Button A Clicked")
def btnBFunction(self) :
print(self.btnB.text() + " Clicked")
QMessageBox.information(self, "Info", "Button B Clicked")
if __name__ == "__main__" :
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()**
- QCheckBox
계층 구조
: Dialog > Button
: Dialog > Containers > Button
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/CheckBoxTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.groupChkBox1.stateChanged.connect(self.group_chk_function)
self.groupChkBox2.stateChanged.connect(self.group_chk_function)
self.ChkBox1.stateChanged.connect(self.chk_function)
self.ChkBox2.stateChanged.connect(self.chk_function)
def group_chk_function(self):
if self.groupChkBox1.isChecked() : print('CheckBox1 in group is Checked')
if self.groupChkBox2.isChecked() : print('CheckBox2 in group is Checked')
def chk_function(self):
if self.ChkBox1.isChecked() : print('CheckBox1 is Checked')
if self.ChkBox2.isChecked() : print('CheckBox2 is Checked')
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
⇒ 출력결과
- 체크박스 안에 1번만 클릭하면, 1번에 대한 출력결과가 나오고
- 체크박스 안에 1번 클릭 후 2번을 클릭하면, 둘 다에 대한 출력결과가 나오고
- 체크박스 밖에 1번만 클릭하면, 밖에 1번에 대한 출력결과가 나오고
- 체크박스 밖에 1번 클릭 후 2번을 클릭하면, 밖에 있는 둘 다에 대한 출력결과가 나온다.
체크박스 안과 밖을 클릭하면, 나중에 클릭한 것에 대한 출력결과가 나온다.
(안을 먼저 클릭하면 밖에 대한 결과가 나오고, 밖을 먼저 클릭하면 밖에 대한 결과가 나온다.)
주문 시스템 만들기
- Window 디자인
GroupBox, CheckBox (GroupBox와 CheckBox의 텍스트(test) 속성 설정)
예전에 주문시스템을 만들면 어떨까?
→ 이용객들이 키오스크 문화에 익숙하지 않았다.
객체 이름
- 자장면 → chkBox_A0
- 짬뽕 → chkBox_A1
- 탕수육 → chkBox_B0
- 양장피 → chkBox_B1
- 팔보채 → chkBox_B2
동작
- 주문 내역을 주방에 출력
→ Terminal 창에 주문 내역을 print 하시오.
클릭 후, 주문버튼을 누르면 주문이 되는 방식으로 구상해야 한다.
- 가위바위보 게임 샘플
import sys
from random import randint
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
# from PyQt5.QtWid
class MainWindow(QDialog):
def __init__(self):
super().__init__()
self.setup_ui()
def setup_ui(self):
main_layout = QVBoxLayout() #메인 레이아웃
user_choose_layout = QHBoxLayout() #버튼 담길 레이아웃
#타이틀 지정
title = QLabel("허접한 가위바위보")
title_font = title.font()
# title_font.setPointSize(25)
title_font = QFont("나눔고딕코딩", 25, QFont.Bold)
title.setFont(title_font)
title.setAlignment(Qt.AlignCenter)
# 이미지 불러오기 및 이미지 사이즈 강제조정
rock_image = QPixmap('주먹.png')
rock_image = rock_image.scaled(50,50,Qt.IgnoreAspectRatio)
scissor_image = QPixmap('가위.png')
scissor_image = scissor_image.scaled(50, 50, Qt.IgnoreAspectRatio)
paper_image = QPixmap('보.png')
paper_image = paper_image.scaled(50, 50, Qt.IgnoreAspectRatio)
# 가위바위보 버튼 , 종료 버튼
self.scissor_btn = QPushButton('가위')
self.rock_btn = QPushButton('바위')
self.paper_btn = QPushButton('보')
quit_btn = QPushButton("종료하기", self)
#버튼 이름 숨기기
# self.scissor_btn.setProperty("orgtext", scissor_btn)
# self.scissor_btn.setText("가위")
#종료버튼 눌렀을 때 종료하기
quit_btn.clicked.connect(self.close)
#버튼에 이미지 넣기 및 버튼 사이즈 조정
self.scissor_btn.setIcon(QIcon(scissor_image))
self.scissor_btn.setIconSize(QSize(70, 70))
self.rock_btn.setIcon(QIcon(rock_image))
self.rock_btn.setIconSize(QSize(70, 70))
self.paper_btn.setIcon(QIcon(paper_image))
self.paper_btn.setIconSize(QSize(70, 70))
#버튼 누르면 이벤트
self.scissor_btn.clicked.connect(self.game_play)
self.rock_btn.clicked.connect(self.game_play)
self.paper_btn.clicked.connect(self.game_play)
#화면 나올 창
# self.image = QLabel()
#레이아웃 담아주기
user_choose_layout.addWidget(self.rock_btn)
user_choose_layout.addWidget(self.paper_btn)
user_choose_layout.addWidget(self.scissor_btn)
main_layout.addWidget(title)
# main_layout.addWidget(image)
main_layout.addLayout(user_choose_layout)
main_layout.addWidget(quit_btn)
self.setWindowTitle("가위바위보게임")
self.setLayout(main_layout)
self.show()
def game_play(self):
# global com_guess
random_num = randint(1, 3)
print(random_num)
if random_num == 1:
com_guess = '가위'
elif random_num == 2:
com_guess = '바위'
if random_num == 3:
com_guess = '보'
reply = QMessageBox() #응답이 받아질 메세지박스
reply.setWindowTitle('결과는!') #메세지박스 상단 텍스트
sender = self.sender() #눌린 버튼을 가져옴
btn_name = sender.text() #눌린 버튼의 이름을 가져옴
if (random_num == 1 and btn_name == '가위') or \\
(random_num == 2 and btn_name == '바위') or \\
(random_num == 3 and btn_name == '보'):
# draw_img = QPixmap('yelled_pingu.jpg')
# draw_img.
reply.setIconPixmap(QPixmap('yelled_pingu.jpg'))
reply.setText(f"비겼습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
elif (random_num == 1 and btn_name == '바위') or \\
(random_num == 2 and btn_name == '보') or \\
(random_num == 3 and btn_name == '가위'):
reply.setIconPixmap(QPixmap('smile_pingu.jpg'))
reply.setText(f"이겼습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
else:
reply.setIconPixmap(QPixmap('angry_pingu2.png'))
reply.setText(f"졌습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
def closeEvent(self, event):
# 종료 대화상자 표시
reply = QMessageBox.question(self, '종료확인', '종료하시겠습니까?',
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
# '예' 버튼을 클릭하면 종료
event.accept()
else:
# '아니오' 버튼을 클릭하면 이벤트 무시
event.ignore()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainWindow()
# MainWindow.show()
sys.exit(app.exec_())
이번주 월, 화는 PyQt수업
수, 목, 금은 데이터 분석 기초
다음주 월, 화, 수는 박태우 강사님 수업
다음 주 목, 금은 데이터 분석 기초
다다음주는 MySQL
이후, 웹 서버로 넘어간다.
- 자바 스크립트 → Node.js(자바 스크립트 업그레아드 버전)
이후 데이터분석으로 본격적으로 들어간다.
(원래 날짜가 정해져있지만, 상황에 따라 탄력적으로 운영한다.)
3월 초에도 데이터분석을 이어간다.
웹 크롤링도 하기 나름이다.
(일단, 파이썬에 적응해야 한다.)
보통 웹 크롤링으로 데이터를 모으려고 하진 않는다.
웹 크롤링은 시간이 많이 걸린다.
(여력 있으면 하고, 없으면 넘어가도 된다.)
데이터베이스 수업이 일주일 정도 잡혀있지만, Node.js에서 사용하는 데이터베이스와 MySQL 데이터베이스가 조금 다르다.
작년에는 여름에 시작해서 가을이었다.
추석끼고 나서 조금 분위기가 해이해졌다.
우리는 설날을 잘 보내야 탄력이 유지되지 않을까싶다.
터미널 창에 주문내역을 프린트하는데,
클릭할 때마다 프린트하는 건 아니다.
→ 이번에는 주문 눌렀을 때 프린트하면 된다.
(체크상태를 보고 주문을 해야한다.)
주문한 리스트가 있어야 하는데, 언제 주문리스트를 만들 것인가?
(프린트한 내용은 언제 만들면 좋을까?)
- 주문리스트를 만들고 프린트 할 것인가?
(주문 버튼을 눌렀을 때, 주문리스트를 만들면 된다.)
→ 리스트를 어떻게 뽑을 것인가?
버튼 클릭하면, 주문내역을 프린트한다.
프로그램에 익숙하다면, 반복문으로 바꿔보자.
위젯과 레이아웃
- 위젯, Display / Qlabel
PyQt 책은 서점에 없다.
(교보문고에 전자책으로 있다.)
→ PyQt를 인터넷에 검색하면 잘 나온다.
PyQt를 활용한 GUI 프로그램
PyQt로 뭘 하기보단, 파이썬 기본문법에서 클래스에 대한 이해
클래스를 바탕으로 작성된 코드를 응용할 일에 대비해 적응하는 시간을 가지자는 의미에서 PyQt를 배운다.
예를 들어서, 경제학과 나오면 꼭 경제학 관련 일을 하는 것이 아니니 프로그램을 배울 때도 넓은 시야로 시작하면 좋다.
신입 엔지니어에게 10대 코딩 中 블록코딩을 시켰었다.
신입 사원은 엔지니어가 되고 싶은 사람이다.
다루는 범위는 제법 많다.
Graphic User Interface
함수를 통해서 값을 가져오도록 한다.
문자열로 하면 error가 나온다.
프로그램이 돌다가 문제없을 거라 여겼던, error가 생기기도 한다.
sys module
import sys
# sys.argv - 명령 행에서 입력된 인수가 저장되어 있음
# $ python sys_module_test.py hello.py
# ['sys_module_test.py', 'hello.py']
print(sys.argv)
#sys.exit() - 스크립트 강제 종료
x = 0
while True:
if x == 5:
sys.exit()
else:
print(x)
x += 1
- 출력결과
- 프롬프트: 박근혜 대통령 당시부터 나온 단어
아나운서가 말을 할 때, 스크립트가 카메라 밑에 붙어져 있다.
(살짝 시선이 떨어진다.)
→ 카메라 렌즈 밑에 붙여둔다. (프롬프트라고 부른다.)
이런 프롬프트가 아닌, 명령을 대기하는 것도 프롬프트라고 부른다.
‘.’ ⇒ 현재 디렉토리에 있다.
\\ ⇒
경로, 소스코드 이름, 옵션
- PyQt란 무엇인가?
Python + Qt를 합쳤다는 의미에서 PyQt라고 이름을 붙였으며, C++ 기반의 GUI Framework인 Qt를 Python에서 사용할 수 있게 만든 패키지(Qt의 레이아웃에 Python의 코드를 연결하여 GUI 프로그램을 만들 수 있게 해주는 프레임워크).
PyQt는 C++의 Cross Platform GUI Franwork인 Qt를 영국의 Riverbank Computing에서 Python 모듈로 변환해 주는 툴을 만들면서 시작 되었음.
(PyQt4 버전과 PyQt 5버전이 주로 사용되고 있음.)
- PyQt의 특징
Python에도 PyGTK, PySide, Tkinter 등 다양한 GUI Framework가 존재하지만 이러한 GUI Frame은 사용하기 어렵고 시각적으로 이쁘지 않다는 단점이 있음.
app = 프로그램 = 객체
→ 프로그램 객체, 윈도우 객체 각각 하나씩 만들어서 실행한다.
창 하나, 프로그램 하나 만들면 유기적으로 돌아간다.
프로그램 하나 실행해서 출력되는 결과가 당연하다고 생각하지만, 많은 것들이 들어가 있다.
라이브러리: 전체적인 흐름을 따라가게 만들어져 있다.
프레임워크: 속에 보이지 않는 구조물이 있다. (보이지 않는 손이 있다.)
myWindow 안에 QWidget() 클래스 지정한 뒤, 새로운 생성자로 지정하였다.
- MyWindow 클래스 생성
MyWindow 클래스 생성
: QMainWindow 클래스로부터 상속을 받아 MyWindow 클래스 정의
: MyWindow 클래스의 인스턴스 생성
→ myWindow = MyWindow()
: ‘PyQt 첫 번째 코딩’ 에서는 Qwidget 클래스의 인스턴스 생성
PyQt 세 번째 코딩
: 클래스 초기화 함수
init(self)
super().init()
: 윈도우 타이틀 지정
setWindowTitle(’My PyQt Window’)
: 윈도우 크기 지정(변경)
setGeometry(x, y, width, height)
→ x, y : 모니터 좌표
→ width, height : ‘윈도우’의 폭의 높이
폭: 320
높이: 180
#빔 프로젝트는 가로 1,024px 세로 684px로 나눠서 보여준다.
클래스 개념으로 프로그램을 짜면 어떤가?
- PyQt - Hello World!
: 필요한 클래스만 import 함
: myWindow 인스턴스
QtWidget을 상속 받은 HelloWorldWindow 클래스로 생성함
QtWidget 클래스가 가지고 있는 여러 메서드를 사용할 수 있음
setWindowTitle(), setGeometry()
QLabel()
: 라벨 객체를 생성
setText()
: 객체의 텍스트 속성 값을 지정
move()
: 객체를 지정된 위치로 이동
앞으로 어떤 객체에 텍스트를 쓰고 싶다.
class 정의: 파이썬 인터프리터가 이렇게 설계했다는 부분
Qt Designer 설치
- Qt Designer
: PyQt를 이용하여 GUI 프로그래밍을 할 때 손쉽게 프로그램의 레이아웃을 편집할 수 있게 해주는 편집기
- PyQt 및 Qt Designer 설치
→ Windows의 cmd 창에서 실행
-> pip install pyqt5
-> pip install pyqt5-tools
⇒ PyQt를 이용해서 사용자 인터페이스를 제작할 수 있다.
템플릿(templates)
위젯(Widgets)
geometry
- x, y: 위치값
- 너비, 높이: 조정값
Qt Designer 위젯의 속성
: 위젯 마다 속성이 조금씩 다르지만 공통적으로 가지고 있는 속성이 다수 있음.
자주 사용되는 속성들
- ObjectName : Python 코드에서 사용될 위젯의 이름을 설정.
- Gemometry : 위젯의 x, y 좌표와 폭과 높이를 지정
- Palette : 위젯의 색상을 지정
- Font : 글자의 폰트와 크기 지정
- ToolTip : 위젯 위에 마우스를 올려 놓았을 때 해당 위젯에 대한 정보를 제공하는 글자 출력
- TooTipDuration : tooltip이 얼마 동안 보여질지 시간 지정, 단위는 millisecond
- TooTipDration이 1이면 해당 위젯에 마우스가 올려져 있으면 지속적으로 tooltip를 출력
UI와 Python 코드의 연결하는 방법
: UI 파일을 Python 코드에서 import하는 방법
# filename - PushButtonTest.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
# UI 파일 연결
# UI 파일이 "현재 작업 디렉토리/ui" 디렉토리에 있다고 가정
form_class = uic.loadUiType('./ui/PushButtenTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
# filename – PushButtonTest.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
# UI 파일 연결
# UI 파일이 "현재 작업 디렉토리/ui" 디렉토리에 있다고 가정
form_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
정리: PyQt 시작
- PyQt란 무엇인가?
Python + Qt를 합쳤다는 의미에서 PyQt라고 이름을 붙였으며, C++ 기반의 GUI Framework인 Qt를 Python에서 사용할 수 있게 만든 패키지(Qt의 레이아웃에 Python의 코드를 연결하여 GUI 프로그램을 만들 수 있게 해주는 프레임워크).
특징: Python에도 PyGTK, PySide, Tkinter 등 다양한 GUI Framework가 존재하지만 이러한 GUI Frame은 사용하기 어렵고 시각적으로 이쁘지 않다는 단점이 있음.
- Qt Designer의 설치
- Qt Designer의 화면 구성
- Qt Designer를 이용한 UI 제작과 연결
일을 시켜서 하는 사람이 있다.
컴퓨터없이 수업 하는 사람은 프린터물을 나눠주고 수업을 진행
빔 프로젝트도 없이 수업을 진행하다.
→ 조직이 원하는 것과 내가 원하는 것이 같으면 좋다.
자기가 하고싶은 일과 회사가 요구하는 일이 맞으면 시너지효과다.
프로그램은 안 시키는 것은 하지 않는다.
⇒ 명령하지 않은 것이 나타나거나, 실행되지 않으면 작성자의 잘못이다.
객체 입장에서는 이벤트(사건)가 발생한 것이다.
→ 지시를 해줘야 한다.
시그널(Signal)과 슬롯(Slot)
- 시그널(Signal)
위젯의 성태가 바뀌었을 때 위젯에서 특정 시그널(이벤트)이 발생
→ 위젯에서 신호를 내보냄
Ex) 버튼 위젯이 클릭되었을 때 어떤 동작(함수)을 수행하거나 다이얼 위젯을 돌렸을 때 화면에 다른 값이 출력되게 하는 동작(함수)을 지정
#시그널이 발생했을 때 신호를 내보내고, 어떤 기능을 하라고 짝을 지어주는데, 이것을 슬록이라고 부른다.
[예전에는 (시그널 = 이벤트)와 (슬롯 = 이벤트 핸들러)라고 불렀다.]
⇒ 슬롯은 시그널과 연결된 함수이다.
- 슬롯(Slot)
: 함수 개념
: 위젯에서 특정 신호(시그널)가 발생 했을 때 해당 시그널(이벤트)을 처리할 슬롯(이벤트 핸들러)을 지정할 수 있음
: 시그널에 처리를 위해 특정 시그널에 대해 슬롯(함수) 지정할 수 있음
- 함수 vs 슬롯
어떤 변화(이벤트, 시그널)가 없더라도 실행될 수 있는 코드
함수는 보통 위젯의 값을 설정하거나 위젯의 값을 가져오거나 위젯의 속성을 변경할 때 사용
PyQt에서 대부분의 위젯들이 공통적으로 사용하는 함수들이 몇 가지 있음.
- “Qt Designer를 이용한 UI 제작” 부분에서 어떻게 Qt Designer를 이용하여 UI 파일과 Python 코드를 연결하는지에 대해서 살펴 봤음(그때는 화면에 보인 위젯들은 아무런 기능을 하지 않았음).
- 위젯이 변화했을 때 어떤 동작을 하게 하기 위해서는 무엇을 해야 하는가?
위젯에서 발생한 시그널을 처리하는 슬롯이 있어야 함
시그널과 슬롯을 연결해야 함
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uicform_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
# 이 부분에 시그널과 슬롯을 연결하는 코드
# 여기에 슬롯(함수) 정의
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
# filename – PushButtonSignal.py
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/PushButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
# QPushButton 위젯(btnA)에서 클릭 시그널이 발생하면
# btnA_function() 슬롯에 연결
self.btnA.clicked.connect(self.btnA_function)
# btnA_function() 슬롯 정의
def btnA_function(self):
print('Button A Clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
클릭하면 클릭했다는 신호가 발생한다.
#원래 선생의 말은 30% 정도만 들리더라.
강사는 노가다 = 움직이는 만큼 돈을 번다.
→ 회사는 아니다.
- 사업과 장사의 차이는 무엇인가?
백종원: 사업
사업: 시스템이 하는 것
장사: 자신이 직접 하는 것
알아서 하라고 하면 싫어한다.
(일을 맡긴다는 것은, 책임과 권한을 주는 것이다.)
같이 고민해서 ‘중학교 2학년’ 대상으로 어떤 것을 먹을지 생각한다.
자신이 없어도 돌아가는 시스템을 구축해야 한다.
→ 다시 끌어올리기 위해 고민하는 중이다.
내가 연봉을 그만큼 받기 위해선, 그런 능력이 있어야하고, 증명해서 동의해야 한다.
문제가 있으면, 스스로 얘기를 해서 해결해야 한다.
요점: 나의 연봉을 증가시키려면 어떻게 해야 하는가?
→ 방법을 찾고 있다.
- 구체적으로 행동하면서 실패해봐야 안다.
QRadioButton vs QCheckButton
n개 중에 1개를 선택할 때, Radio버튼으로 구현한다.
위젯 상자의 Containers 안에 있는 GroupBox
위젯 상자의 Button 안에 있는 Radio Button
물어볼 때는 라디오 버튼 중 1개만 잡는다.
→ n개 중에서 하나를 선택하라는 질문을 할 때 일반적으로 많이 사용하는 방법이다.
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/RadioButtonTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.rBtn1.clicked.connect(self.groupBox_rbtn_function)
self.rBtn2.clicked.connect(self.groupBox_rbtn_function)
self.rBtn3.clicked.connect(self.groupBox_rbtn_function)
def groupBox_rbtn_function(self):
if self.rBtn1.isChecked():
print('RadioButtin1 Checked')
elif self.rBtn2.isChecked():
print('RadioButten2 Checked')
elif self.rBtn3.isChecked():
print("RadioButton3 Checked")
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
실행결과
PPT를 한번 만들었다가, 다시 만들었다.
기본구조 잡아보기 → 라벨 붙여보기 → 버튼 넣어보기 → 디자인을 써서 버튼을 하나 달고, 반응을 하기 위해 signal과 slot이 연결된다.
위젯, Buttons / Push Button
- UI 파일 생성 - QPushButton 위젯 두 개를 Dialog 창에 올려 놓기
텍스트 속성, 위치는 바꿔도 영향 X
**import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType("PushButtons.ui")[0]
class WindowClass(QMainWindow, form_class) :
def __init__(self) :
super().__init__()
self.setupUi(self)
self.btnA.clicked.connect(self.btnAFunction)
self.btnB.clicked.connect(self.btnBFunction)
def btnAFunction(self) :
print(self.btnA.text() + " Clicked")
QMessageBox.information(self, "Info", "Button A Clicked")
def btnBFunction(self) :
print(self.btnB.text() + " Clicked")
QMessageBox.information(self, "Info", "Button B Clicked")
if __name__ == "__main__" :
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()**
- QCheckBox
계층 구조
: Dialog > Button
: Dialog > Containers > Button
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType('./ui/CheckBoxTest.ui')[0]
class WindowClass(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.groupChkBox1.stateChanged.connect(self.group_chk_function)
self.groupChkBox2.stateChanged.connect(self.group_chk_function)
self.ChkBox1.stateChanged.connect(self.chk_function)
self.ChkBox2.stateChanged.connect(self.chk_function)
def group_chk_function(self):
if self.groupChkBox1.isChecked() : print('CheckBox1 in group is Checked')
if self.groupChkBox2.isChecked() : print('CheckBox2 in group is Checked')
def chk_function(self):
if self.ChkBox1.isChecked() : print('CheckBox1 is Checked')
if self.ChkBox2.isChecked() : print('CheckBox2 is Checked')
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
⇒ 출력결과
- 체크박스 안에 1번만 클릭하면, 1번에 대한 출력결과가 나오고
- 체크박스 안에 1번 클릭 후 2번을 클릭하면, 둘 다에 대한 출력결과가 나오고
- 체크박스 밖에 1번만 클릭하면, 밖에 1번에 대한 출력결과가 나오고
- 체크박스 밖에 1번 클릭 후 2번을 클릭하면, 밖에 있는 둘 다에 대한 출력결과가 나온다.
체크박스 안과 밖을 클릭하면, 나중에 클릭한 것에 대한 출력결과가 나온다.
(안을 먼저 클릭하면 밖에 대한 결과가 나오고, 밖을 먼저 클릭하면 밖에 대한 결과가 나온다.)
주문 시스템 만들기
- Window 디자인
GroupBox, CheckBox (GroupBox와 CheckBox의 텍스트(test) 속성 설정)
예전에 주문시스템을 만들면 어떨까?
→ 이용객들이 키오스크 문화에 익숙하지 않았다.
객체 이름
- 자장면 → chkBox_A0
- 짬뽕 → chkBox_A1
- 탕수육 → chkBox_B0
- 양장피 → chkBox_B1
- 팔보채 → chkBox_B2
동작
- 주문 내역을 주방에 출력
→ Terminal 창에 주문 내역을 print 하시오.
클릭 후, 주문버튼을 누르면 주문이 되는 방식으로 구상해야 한다.
- 가위바위보 게임 샘플
import sys
from random import randint
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
# from PyQt5.QtWid
class MainWindow(QDialog):
def __init__(self):
super().__init__()
self.setup_ui()
def setup_ui(self):
main_layout = QVBoxLayout() #메인 레이아웃
user_choose_layout = QHBoxLayout() #버튼 담길 레이아웃
#타이틀 지정
title = QLabel("허접한 가위바위보")
title_font = title.font()
# title_font.setPointSize(25)
title_font = QFont("나눔고딕코딩", 25, QFont.Bold)
title.setFont(title_font)
title.setAlignment(Qt.AlignCenter)
# 이미지 불러오기 및 이미지 사이즈 강제조정
rock_image = QPixmap('주먹.png')
rock_image = rock_image.scaled(50,50,Qt.IgnoreAspectRatio)
scissor_image = QPixmap('가위.png')
scissor_image = scissor_image.scaled(50, 50, Qt.IgnoreAspectRatio)
paper_image = QPixmap('보.png')
paper_image = paper_image.scaled(50, 50, Qt.IgnoreAspectRatio)
# 가위바위보 버튼 , 종료 버튼
self.scissor_btn = QPushButton('가위')
self.rock_btn = QPushButton('바위')
self.paper_btn = QPushButton('보')
quit_btn = QPushButton("종료하기", self)
#버튼 이름 숨기기
# self.scissor_btn.setProperty("orgtext", scissor_btn)
# self.scissor_btn.setText("가위")
#종료버튼 눌렀을 때 종료하기
quit_btn.clicked.connect(self.close)
#버튼에 이미지 넣기 및 버튼 사이즈 조정
self.scissor_btn.setIcon(QIcon(scissor_image))
self.scissor_btn.setIconSize(QSize(70, 70))
self.rock_btn.setIcon(QIcon(rock_image))
self.rock_btn.setIconSize(QSize(70, 70))
self.paper_btn.setIcon(QIcon(paper_image))
self.paper_btn.setIconSize(QSize(70, 70))
#버튼 누르면 이벤트
self.scissor_btn.clicked.connect(self.game_play)
self.rock_btn.clicked.connect(self.game_play)
self.paper_btn.clicked.connect(self.game_play)
#화면 나올 창
# self.image = QLabel()
#레이아웃 담아주기
user_choose_layout.addWidget(self.rock_btn)
user_choose_layout.addWidget(self.paper_btn)
user_choose_layout.addWidget(self.scissor_btn)
main_layout.addWidget(title)
# main_layout.addWidget(image)
main_layout.addLayout(user_choose_layout)
main_layout.addWidget(quit_btn)
self.setWindowTitle("가위바위보게임")
self.setLayout(main_layout)
self.show()
def game_play(self):
# global com_guess
random_num = randint(1, 3)
print(random_num)
if random_num == 1:
com_guess = '가위'
elif random_num == 2:
com_guess = '바위'
if random_num == 3:
com_guess = '보'
reply = QMessageBox() #응답이 받아질 메세지박스
reply.setWindowTitle('결과는!') #메세지박스 상단 텍스트
sender = self.sender() #눌린 버튼을 가져옴
btn_name = sender.text() #눌린 버튼의 이름을 가져옴
if (random_num == 1 and btn_name == '가위') or \\
(random_num == 2 and btn_name == '바위') or \\
(random_num == 3 and btn_name == '보'):
# draw_img = QPixmap('yelled_pingu.jpg')
# draw_img.
reply.setIconPixmap(QPixmap('yelled_pingu.jpg'))
reply.setText(f"비겼습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
elif (random_num == 1 and btn_name == '바위') or \\
(random_num == 2 and btn_name == '보') or \\
(random_num == 3 and btn_name == '가위'):
reply.setIconPixmap(QPixmap('smile_pingu.jpg'))
reply.setText(f"이겼습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
else:
reply.setIconPixmap(QPixmap('angry_pingu2.png'))
reply.setText(f"졌습니다! 컴퓨터는 {com_guess}를 냈습니다.")
reply.exec_()
def closeEvent(self, event):
# 종료 대화상자 표시
reply = QMessageBox.question(self, '종료확인', '종료하시겠습니까?',
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
# '예' 버튼을 클릭하면 종료
event.accept()
else:
# '아니오' 버튼을 클릭하면 이벤트 무시
event.ignore()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainWindow()
# MainWindow.show()
sys.exit(app.exec_())
이번주 월, 화는 PyQt수업
수, 목, 금은 데이터 분석 기초
다음주 월, 화, 수는 박태우 강사님 수업
다음 주 목, 금은 데이터 분석 기초
다다음주는 MySQL
이후, 웹 서버로 넘어간다.
- 자바 스크립트 → Node.js(자바 스크립트 업그레아드 버전)
이후 데이터분석으로 본격적으로 들어간다.
(원래 날짜가 정해져있지만, 상황에 따라 탄력적으로 운영한다.)
3월 초에도 데이터분석을 이어간다.
웹 크롤링도 하기 나름이다.
(일단, 파이썬에 적응해야 한다.)
보통 웹 크롤링으로 데이터를 모으려고 하진 않는다.
웹 크롤링은 시간이 많이 걸린다.
(여력 있으면 하고, 없으면 넘어가도 된다.)
데이터베이스 수업이 일주일 정도 잡혀있지만, Node.js에서 사용하는 데이터베이스와 MySQL 데이터베이스가 조금 다르다.
작년에는 여름에 시작해서 가을이었다.
추석끼고 나서 조금 분위기가 해이해졌다.
우리는 설날을 잘 보내야 탄력이 유지되지 않을까싶다.
터미널 창에 주문내역을 프린트하는데,
클릭할 때마다 프린트하는 건 아니다.
→ 이번에는 주문 눌렀을 때 프린트하면 된다.
(체크상태를 보고 주문을 해야한다.)
주문한 리스트가 있어야 하는데, 언제 주문리스트를 만들 것인가?
(프린트한 내용은 언제 만들면 좋을까?)
- 주문리스트를 만들고 프린트 할 것인가?
(주문 버튼을 눌렀을 때, 주문리스트를 만들면 된다.)
→ 리스트를 어떻게 뽑을 것인가?
버튼 클릭하면, 주문내역을 프린트한다.
프로그램에 익숙하다면, 반복문으로 바꿔보자.
위젯과 레이아웃
- 위젯, Display / Qlabel
PyQt 책은 서점에 없다.
(교보문고에 전자책으로 있다.)
→ PyQt를 인터넷에 검색하면 잘 나온다.