오늘은 GUI 관련 재미난 지식을 알게 되었습니다. (감사합니다. 선생님)
*주의사항 본 블러그가 코드에 띄어 쓰기를 지원하지 않아서 큭히 함수 def 문 다음줄부터는 Indent TAB 이 필요하다는 점
꼭 명심하시기 바랍니다. 초보자는 직접 입력 하세요~ ㅋ
01 TKinter
T.K.인터 라고 읽는다고 하네요.
파이썬 설치하거나 아나콘다 설치하면 기본적으로 포함된 GUI라이브러리라 모양이나 호환성은 그다지 좋지 않지만 공짜~라는 점에서 그리고 갑자기 창을 띄어야 한다거나 할 때 별도 라이브러리 설치 없이 사용 가능하니 기본은 알고 가는 것이 좋다고 해서 몇 가지 코드를 실험해봤습니다.
1. 레이블
OS 상관없이 다 실행됩니다. 근데 좀 모양이 이쁘지는 않네요 ㅎ
2023 09 01
#오전 세션
from tkinter import * #기본으로 설치되어있음.
root = Tk()
#레이블(메시지표시)
label = Label(root, text = "Hello, World")
label.pack()
root.mainloop() ## 메시지를 처리해 준다.
2. 리스트박스
#리스트박스
rom tkinter import *
root = Tk()
listbox = Listbox(root)
listbox.pack()
for item in ["item one", "item two", "item three", "item four"]:
listbox.insert(END, item)
root.mainloop() ## 메시지를 처리해 준다.
#리스트 클릭 이벤트 반응 실험
2-1. 리스트박스 이벤트 반응 구현
from tkinter import *
def event_for_listbox(event):
print("리스트박스가 클릭되었습니다."
#리스트박스 이벤트
#03. 이벤트 선택 반응 구현 추가
from tkinter import *
import tkinter.messagebox
def event_for_listbox(event): # 들여 쓰기 주의
w = event.widget
index = int(w.curselection()[0])
value = w.get(index)
msg = f"selected item index({index}) , value ({value})!!"
tkinter.messagebox.showinfo("리스트 선택 : ", msg)
print("리스트 박스가 클릭되었습니다.", msg)
root = Tk()
listbox = Listbox(root)
listbox.pack()
for item in ["item one", "item two", "item three", "item four"]:
listbox.insert(END, item)
#이벤트 헨들러 - <<이벤트호출문장형식>>
listbox.bind("<<ListboxSelect>>", event_for_listbox)
root.mainloop() ## 메시지를 처리해 준다.
근데 이건 맥에서는 잘 작동을 못하는 듯해요 참고하세요
3. 캔버스 만들기
import tkinter
window=tkinter.Tk()
window.title("YUN DAE HEE")
window.geometry("640x400+100+100")
window.resizable(False, False)
canvas=tkinter.Canvas(window, relief="solid", bd=2)
line=canvas.create_line(10, 10, 50, 10, 50, 150, 300, 150, fill="red")
canvas.pack()
window.mainloop()

4. 버튼 /이벤트 대응 실험
#오전 세션 - button 구현
#버튼 클릭 이벤트
# 버튼 클릭 이벤트 선택 반응 구현 추가
from tkinter import *
import tkinter.messagebox
def onevent(event):
w = event.widget
msg = f"button click ({w}) : 버튼이 클릭되었습니다."
tkinter.messagebox.showinfo("버튼 선택 : ", msg)
root = Tk()
btn = Button(root, text ="여기를 클릭해 주세요.")
btn.pack()
btn.bind("<Button-1>", onevent)
root.mainloop() ## 메세지를 처리해준다.
선생님이 그 유명한 QT라는 GUI라이브러리에 대해 소개해주셨어요
알고 보니, 대단한 녀석 같아요.. 이거만 깊이 파는 것도 좋을 것 같습니다.
코드는 좀 긴데 한 번만 카피하고 중복되는 부분은 계속 사용하면 돼요~
02.QT
1. QT라이브러리 설치 하기
저는 아나콘다 이용 중이라 쉽게 했고요.
그냥 일반 파이썬을 사용한다면 꼭 가상환경을 만들고 , 거기에
pip install 라이브러리명
명령을 이용해서 라이브러리를 설치해야 합니다.

1. 기본 Hello world 윈도 만들기
import sys
from PyQt5.QtWidgets import QApplication, QWidget
class MyApp(QWidget): #QWiget을 넣어서 MyApp 콜
def __init__(self):
super().__init__() #Constructor
self.initUI() #자신의 initUI 함수 호출
def initUI(self):
self.setWindowTitle('Hello World Window')
self.move(300, 300)
self.resize(400, 200)
self.show()
if __name__ == '__main__': # 시작점
app = QApplication(sys.argv) # QT Main Application Call app로 저장
ex = MyApp() ## 메인 호출
sys.exit(app.exec_()) #시스템 종료
2.Push Button 실험하기
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
class MyApp(QWidget): #QWiget을 넣어서 MyApp 콜
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
btn1 = QPushButton('&Button1', self)
btn1.setCheckable(True)
btn1.toggle()
btn2 = QPushButton(self)
btn2.setText('Button&2') #Alt+ 2: 클릭
btn3 = QPushButton('Button3', self)
btn3.setText('Button&3')
#Layout : 배치
vbox = QVBoxLayout() # 박스타입레이아웃, 여러 가지 레이아웃 방식 지원, CSSㄴ레이아웃처럼 자신만의 방식이 있다.
vbox.addWidget(btn1) #버튼의 속성을 가진 위젯을
vbox.addWidget(btn2)
vbox.addWidget(btn3)
self.setLayout(vbox) ㅣ#레이아웃 구성 (레이아웃은 컨테이너 역할을 함. 박스형태의 틀)
self.setWindowTitle('QPushButton')
self.setGeometry(300, 300, 300, 200)
self.show()
if __name__ == '__main__': # 시작점
app = QApplication(sys.argv) # QT Main Application Call app로 저장
ex = MyApp() ## 메인 호출
sys.exit(app.exec_()) #시스템 종료
3. 조그셔틀 같은 다이얼 구현
# https://wikidocs.net/35494 참조
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
form_class = uic.loadUiType("spinboxTest.ui")[0]
class WindowClass(QMainWindow, form_class) :
def __init__(self) :
super().__init__()
self.setupUi(self)
self.spinbox_Test.valueChanged.connect(self.printValue)
self.btn_showInfo.clicked.connect(self.printInfo)
self.btn_changeRangeStep.clicked.connect(self.changeRangeStep)
self.doublespinbox_Test.valueChanged.connect(self.printDoubleValue)
self.btn_doubleShowInfo.clicked.connect(self.printDoubleInfo)
self.btn_doubleChangeRangeStep.clicked.connect(self.doubleChangeRangeStep)
def printValue(self) :
print(self.spinbox_Test.value())
def printInfo(self) :
print("Maximum value is", self.spinbox_Test.maximum())
print("Minimum value is", self.spinbox_Test.minimum())
print("Step Size is", self.spinbox_Test.singleStep())
def changeRangeStep(self) :
self.spinbox_Test.setRange(0,1000)
self.spinbox_Test.setStep(10)
def printDoubleValue(self) :
print(self.doublespinbox_Test.value())
def printDoubleInfo(self) :
print("Maximum value is",self.doublespinbox_Test.maximum())
print("Minimum value is",self.doublespinbox_Test.minimum())
print("Step Size is",self.doublespinbox_Test.singleStep())
def doubleChangeRangeStep(self) :
self.doublespinbox_Test.setRange(0,1000)
self.doublespinbox_Test.setStep(1.5)
if __name__ == "__main__" :
app = QApplication(sys.argv)
myWindow = WindowClass()
myWindow.show()
app.exec_()
4.싱글슬럿 연결 하는 윈도우 실험
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLCDNumber, QDial, QVBoxLayout
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
lcd = QLCDNumber(self) # LCD 창
dial = QDial(self) # 다이얼
dial.setValue(10)
dial.setMinimum(10)
dial.setMaximum(200)
vbox = QVBoxLayout() #Layout Vertical Box
vbox.addWidget(lcd)
vbox.addWidget(dial)
self.setLayout(vbox)
dial.valueChanged.connect(lcd.display) # 다이얼에 값이 바뀌면 LCD 에 연결해라
self.setWindowTitle('Signal and Slot') #
self.setGeometry(600, 600, 200, 200
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MyApp()
sys.exit(app.exec_())
5. 엑셀 같은 테이블 구조 만들기 1
버튼을 누르면 내용이 다 지워집니다. 주석 참고 하세요~
import sys
import numpy as np
from PyQt5.QtWidgets import *
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.tableWidget = QTableWidget()
self.tableWidget.setRowCount(20)
self.tableWidget.setColumnCount(4)
self.clearBtn = QPushButton('Clear')
self.clearBtn.clicked.connect(self.tableWidget.clear) # 버튼이 눌리면 내용을 다 지워라
#20*4 행렬의 난수 1~100까지 생성
rand_items = np.random.randint(1, 100, size=(20, 4))
for i in range(20):
for j in range(4):
self.tableWidget.setItem(i, j, QTableWidgetItem(str(rand_items[i, j])))
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
layout = QVBoxLayout()
layout.addWidget(self.tableWidget)
layout.addWidget(self.clearBtn)
self.setLayout(layout)
self.setWindowTitle('PyQt5 - QTableWidget')
self.setGeometry(300, 100, 600, 400)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MyApp()
sys.exit(app.exec_())
5-1. 변형 1
테이블에서 내용을 넣고 스크롤도 되는 것으로 변형했어요
mport sys
import numpy as np
from PyQt5.QtWidgets import *
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.tableWidget = QTableWidget()
self.tableWidget.setRowCount(20)
self.tableWidget.setColumnCount(4)
self.clearBtn = QPushButton('Clear')
self.clearBtn.clicked.connect(self.tableWidget.clear)
self.scrollToTop = QPushButton('Scroll to Top')
self.scrollToTop.clicked.connect(self.tableWidget.scrollToTop)
self.scrollToBottom = QPushButton('Scroll to Bottom')
self.scrollToBottom.clicked.connect(self.tableWidget.scrollToBottom)
rand_items = np.random.randint(1, 100, size=(20, 4))
for i in range(20):
for j in range(4):
self.tableWidget.setItem(i, j, QTableWidgetItem(str(rand_items[i, j])))
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
layout = QVBoxLayout()
layout.addWidget(self.tableWidget)
layout.addWidget(self.clearBtn)
layout.addWidget(self.scrollToTop)
layout.addWidget(self.scrollToBottom)
self.setLayout(layout)
self.setWindowTitle('PyQt5 - QTableWidget')
self.setGeometry(300, 100, 600, 400)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MyApp()
sys.exit(app.exec_())
5-2 변형 2
자세한 해석 은 주석을 참고하세요
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.tableWidget = QTableWidget() # 데이터 값을 보관하고 수정하는 기능이 들어있음.
self.tableWidget.setRowCount(20)
self.tableWidget.setColumnCount(4)
self.label = QLabel('')
self.scrollToTop = QPushButton('Scroll to Top')
self.scrollToTop.clicked.connect(self.tableWidget.scrollToTop)
self.scrollToBottom = QPushButton('Scroll to Bottom')
self.scrollToBottom.clicked.connect(self.tableWidget.scrollToBottom)
self.tableWidget.cellClicked.connect(self.set_label) #이벤트 등록 : siginal, slot event func: cellClicked -> set_label Calling
rand_items = np.random.randint(1, 100, size=(20, 4)) # 난수 발생 숫자 , 행령(20*4)
for i in range(20):
for j in range(4):
self.tableWidget.setItem(i, j, QTableWidgetItem(str(rand_items[i, j]))) # tableWidget.setItem () 셀에 값을 지정함 )
# 난수 를 스트링으로 변환 i,j(x,y) 로 넣어 값을 가져다 QTableWidgetItem()에 넣어서 setItem으로 넣어서 테이블위젯에 으로 넘겨줌
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
layout = QVBoxLayout()
layout.addWidget(self.tableWidget)
layout.addWidget(self.label)
layout.addWidget(self.scrollToTop)
layout.addWidget(self.scrollToBottom)
self.setLayout(layout)
self.setWindowTitle('PyQt5 - QTableWidget')
self.setGeometry(300, 100, 600, 400)
self.show()
def set_label(self, row, column):
item = self.tableWidget.item(row, column)
value = item.text()
label_string = 'Row: ' + str(row+1) + ', Column: ' + str(column+1) + ', Value: ' + str(value)
self.label.setText(label_string)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MyApp()
sys.exit(app.exec_())
6. 오늘의 하일라이트 주식 차트 만들기 (비트코인 실시간 차트 보여주기

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtChart import *
from PyQt5.QtGui import *
from PyQt5.QtCore import Qt
from PyQt5.QtCore import *
import pyupbit
import time
from pandas import Series
SITE_NAME = ["KRW-ETH", "KRW-BTC"]
#Thread
class Worker(QThread):#사이트에서 실시간으로 데이터를 수신하고 있음 (쓰레드/Background)
price = pyqtSignal(float)
def __init__(self):
super().__init__()
#Background 에서 계속 돌고 있음
def run(self):
while True:
cur_price = pyupbit.get_current_price(SITE_NAME[0]) #pyupbit 회사에서 Received Data
self.price.emit(cur_price)
time.sleep(1)
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
# thread
self.worker = Worker()
#Call back 등록 함수 호출 (이름만사용 () 없음), 데이터를 수신하면 호출될 함수 : Self.get_price()
self.worker.price.connect(self.get_price)
self.worker.start()
self.minute_cur = QDateTime.currentDateTime() # current
self.minute_pre = self.minute_cur.addSecs(-60) # 1 minute ago
self.ticks = Series(dtype='float64') # Pandas시리즈 객체 생성 : 수신된 데이터를 판다스 객체로 보관
# window size
self.setMinimumSize(800, 400)
#분당 80회 수신 (?) 인터벌:1분
df = pyupbit.get_ohlcv(SITE_NAME[0], interval='minute1', count=80)
#판다스 데이터 프레임
# data : Candle chart
self.series = QCandlestickSeries() #
self.series.setIncreasingColor(Qt.red) #양봉 컬러
self.series.setDecreasingColor(Qt.blue) # 음봉 컬러
# initial OHLC feeding
# df.index 는 판다스의 데이터 프레임
for index in df.index:
open = df.loc[index, 'open'] #시가
high = df.loc[index, 'high'] #최고가
low = df.loc[index, 'low'] #최저가
close = df.loc[index, 'close'] # 종가
# time conversion 시간 관련
format = "%Y-%m-%d %H:%M:%S"
str_time = index.strftime(format)
dt = QDateTime.fromString(str_time, "yyyy-MM-dd hh:mm:ss")
ts = dt.toMSecsSinceEpoch()
#ts = index.timestamp() * 1000
#print(ts)
elem = QCandlestickSet(open, high, low, close, ts)
self.series.append(elem) #시리즈 값 증가
# chart object
chart = QChart()
chart.legend().hide()
chart.addSeries(self.series) # data feeding
# X axis (X 축)
axis_x = QDateTimeAxis()
axis_x.setFormat("hh:mm:ss")
chart.addAxis(axis_x, Qt.AlignBottom)
self.series.attachAxis(axis_x)
# Y Axis (Y 축)
axis_y = QValueAxis()
axis_y.setLabelFormat("%i")
chart.addAxis(axis_y, Qt.AlignLeft)
self.series.attachAxis(axis_y)
# margin
chart.layout().setContentsMargins(0, 0, 0, 0)
# displaying chart
chart_view = QChartView(chart)
chart_view.setRenderHint(QPainter.Antialiasing)
self.setCentralWidget(chart_view)
#준비작업
@pyqtSlot(float)
def get_price(self, cur_price): #현제 수신된 가격
# append current price
dt = QDateTime.currentDateTime()
self.statusBar().showMessage(dt.toString())
self.ticks[dt] = cur_price #판다스의 시리즈에 시간대별 저장
# check whether minute changed
#if dt.time().minute() != self.minute_cur.time().minute():
ts = dt.toMSecsSinceEpoch()
print(ts, cur_price) #현재 가격
sets = self.series.sets()
last_set = sets[-1]
open = last_set.open()
high = last_set.high()
low = last_set.low()
close = last_set.close()
ts1 = last_set.timestamp()
self.series.remove(last_set) # remove last set
#하나의 봉 (싯가 , 최고 최저 , 이전시간 )
new_set = QCandlestickSet(open, high, low, cur_price, ts1)
self.series.append(new_set)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MyWindow()
win.show()
app.exec_()
정말 정신없이 하루 강의가 끝났네요 역시 눈에 보여야 프로그레밍 맞도 나는 거 같아요
다른 세계를 열게 해주셔서 감사드립니다. 선생님 ^^
마지막으로 선생님께서 알려주신 유용한 링크 입니다. 일단 상식 !!ㅋㅋ
1https://wikidocs.net/book/2165
PyQt5 Tutorial - 파이썬으로 만드는 나만의 GUI 프로그램
## 소개 - 한국어로 되어있는 PyQt5 자료가 많지 않아서 아래의 여러 튜토리얼과 강의의 예제를 정리하며 시작했습니다. - **PyQt5의 설치**부터 시작해서, **…
wikidocs.net
https://webassembly.org/getting-started/developers-guide/
https://namu.wiki/w/WebAssembly
WebAssembly - 나무위키
이 저작물은 CC BY-NC-SA 2.0 KR에 따라 이용할 수 있습니다. (단, 라이선스가 명시된 일부 문서 및 삽화 제외) 기여하신 문서의 저작권은 각 기여자에게 있으며, 각 기여자는 기여하신 부분의 저작권
namu.wiki
https://codetorial.net/pyqt5/basics/opening.html
창 띄우기 - Codetorial
예제 ## Ex 3-1. 창 띄우기. import sys from PyQt5.QtWidgets import QApplication, QWidget class MyApp(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle('My First Application') self.move(300, 300) self.
codetorial.net
https://076923.github.io/posts/Python-tkinter-1/
Python tkinter 강좌 : 제 1강 - GUI 생성
tkinter
076923.github.io
- 저자
- 김대진
- 출판
- 성안당
- 출판일
- 2010.04.19
- 저자
- 김석훈
- 출판
- 한빛미디어
- 출판일
- 2018.08.17
- 저자
- 박준성
- 출판
- 길벗
- 출판일
- 2021.10.14
- 저자
- 김황후
- 출판
- 한빛미디어
- 출판일
- 2020.07.01
- 저자
- 김완섭
- 출판
- 인피니티북스
- 출판일
- 2020.02.12