[비트코인자동매매]1. PyQt

UkiUkhui·2022년 4월 9일
0

1. PyQt

import sys
from PyQt5.QtWidgets import *

class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setGeometry(100,200,300,400)
        self.setWindowTitle("PyQt")

app = QApplication(sys.argv)
win = MyWindow()
win.show()
app.exec_()

2. QtDesigner 이용하기

1) UI 파일 사용

anaconda navigater > show original > bin 파일 > Designer

  • 윈도우 생성하고 다른 이름으로 저장
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic

form_class = uic.loadUiType("/Users/jangsujeong/Desktop/mywindow.ui")[0]
class MyWindow(QMainWindow, form_class):#다중상속
    def __init__(self):
        super().__init__()
        self.setupUi(self)

app = QApplication(sys.argv)
win = MyWindow()
win.show()
app.exec_()
  • loadUiType(): QT Designer의 결과물인 mywindow.ui 파일을 읽어 파이썬 클래스 코드를 만듦
    • XML 파일을 읽어서 파이썬 클래스로 만들어줌.
  • setupUi() : form_class에 정의된 메서드. Qt Designer에서 만든 클래스 초기화.
  • 생성한 mywindow.ui를 코드로 열어보기
  • *.ui = XML이라는 언어로 되어 있음.

2) 이벤트 추가하기

  • Qt Designer 통해 위젯 생성하면 XML로 작성되는 위젯을 파이썬 변수에 바인딩 불가능.
btn = QPushButton('클릭', self)
btn.clicked.connect(self.method)

  • Qt Designer는 위젯을 바인딩할 변수를 지정하는 기능 제공
  • Object : 'pushButton'
    • 파이썬에서 버튼 이벤트를 정의할 때 사용할 변수의 이름
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic

form_class = uic.loadUiType("/Users/jangsujeong/Desktop/mywindow.ui")[0]
class MyWindow(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.pushButton.clicked.connect(self.btn_clicked)
    def btn_clicked(self):
        print('button click')

app = QApplication(sys.argv)
win = MyWindow()
win.show()
app.exec_()

3) 코빗 시세 조회기 만들기

import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
import pykorbit

form_class = uic.loadUiType("/Users/jangsujeong/Desktop/mywindow.ui")[0]
class MyWindow(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.pushButton.clicked.connect(self.inquery)

    def inquery(self):
        price = pykorbit.get_current_price("BTC")
        self.lineEdit.setText(str(price))

app = QApplication(sys.argv)
win = MyWindow()
win.show()
app.exec_()

  • pykorbit 모듈을 통해 얻어온 현재가를 QLineEdit 위젯에 출력함
  • self.lineEdit.setText(str(price)) : price변수가 바인딩하는 값을 lineEdit의 setText()로 넘겨줌
    • setText() : 문자열만 입력받음

4) QTimer

  • 일정 시간마다 자동으로 현재가를 조회하고 위젯에 출력하기
  • PyQt : QTimer사용
self.timer = QTimer(self) #윈도우가 생성될 때 QTimer 객체 생성해야함
self.timer.start(1000) #생성한 객체에 interval(1초) 추가 설정
self.timer.timeout.connect(self.timeout) #
  • QTimer.timeout() : interval마다 발생하는 이벤트
    • 1초에 한번씩 timeout 이벤트 발생
    • 이벤트 루프 : 1초에 한 번 self.timeout()이라는 메서드 호출
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
import pykorbit
from PyQt5.QtCore import *

form_class = uic.loadUiType("/Users/jangsujeong/Desktop/mywindow.ui")[0]
class MyWindow(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.timer = QTimer(self)  # 윈도우가 생성될 때 QTimer 객체 생성해야함
        self.timer.start(1000)  # 생성한 객체에 interval(1초) 추가 설정
        self.timer.timeout.connect(self.timeout)
        
    def timeout(self):
        cur_time = QTime.currentTime() #현재 시각을 얻어옴
        str_time = cur_time.toString("hh:mm:ss")
        self.statusBar().showMessage(str_time) #윈도우 상태바에 현재시간 출력


app = QApplication(sys.argv)
win = MyWindow()
win.show()
app.exec_()

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

form_class = uic.loadUiType("/Users/jangsujeong/Desktop/mywindow.ui")[0]
class MyWindow(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.timer = QTimer(self)  # 윈도우가 생성될 때 QTimer 객체 생성해야함
        self.timer.start(1000)  # 생성한 객체에 interval(1초) 추가 설정
        self.timer.timeout.connect(self.inquery)

    def inquery(self):
        cur_time = QTime.currentTime()
        str_time = cur_time.toString("hh:mm:ss")
        self.statusBar().showMessage(str_time)
        price = pykorbit.get_current_price("BTC")
        self.lineEdit.setText(str(price))

app = QApplication(sys.argv)
win = MyWindow()
win.show()
app.exec_()

  • 1초 주기로 inquiry 메서드 호출됨
  • inquiry 메서드 안에서 비트코인 가격을 가져와 lineEdit에 출력함

3. PyQt 시그널 슬롯

1) PyQt 사용자 정의 시그널/슬롯

  • 시그널(signal) : 위젯에 정의된 이벤트
  • 슬롯(slot) : 이벤트가 발생할 때 호출되는 함수나 메서드
btn.clicked.connect(self.btn_clicked)
  • 오른쪽, 왼쪽 버튼 구분없이 어느 마우스 버튼이라도 클릭하면 발생함
  • PyQt:원하는 이벤트(시그널)을 직접 정의할 수 있도록 해줌.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class MySignal(QObject):
    signal1 = pyqtSignal()

    def run(self):
        self.signal1.emit()

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

        mysignal = MySignal()
        mysignal.signal1.connect(self.signal1_emitted)
        mysignal.run()

    def signal1_emitted(self):
        print('signal1_emitted')

app = QApplication(sys.argv)
win = MyWindow()
win.show()
app.exec_()
  • 시그널을 정의하고 해당 시그널을 처리하는 슬롯 연결
    • MySignal 클래스 생성 : 사용자 정의 시그널 생성
      • class에서 pyqtSignal 객체 생성
      • pyqtSignal 객체는 클래스 변수로 만들어야 함.
      • signal1 = 시그널(이벤트) 생성됨
      • QPushButton 내 'clicked'라는 시그널이 있던 것과 같은 맥락
      • run() : signal1에서 emit()호출 = emit()은 pyqtSignal클래스에 정의된 메서드임
    • MyWindow 클래스
      • mysignal.signal1.connect(self.signal1_emitted) : MySignal이라는 객체로부터 'signal1' 이벤트 발생 시 이벤트루프는 signal1_emitted 메서드 호출함
      • signal1 이벤트 발생 시점 : run() 메서드 호출될 때 emit() 호출하는 그 순간에 발생
      • mysignal.run() : MySignal객체가 emit()호출하여 시그널 발생시키면 Mywindow에 정의된 메서드(슬롯) 호출됨
  • PyQt의 시그널/슬롯을 이용하면 특정 시점에서 어떤 클래스에서 다른 클래스로 데이터를 쉽게 보내줄 수 있음
  • 스레드 이용
    • ex) 타이머를 이용해 비트코인의 금액을 얻어올 때 다른 작업을 동시에 수행할 수 없음
    • 비트코인, 리플, 이더리움과 같은 여러 가상화폐 금액 동시 조회해도 다른 이벤트 처리가 가능
      ➡️ 스레드 사용하면 금액을 조회하는 일과 얻어온 값을 출력하는 일이 거의 동시에 진행되므로 조회된 금액을 MyWindow로 보내주는 방법이 필요함 ➡️ 그 역할을 하는 것이 사용자 정의 시그널 /슬롯

2) 시그널로 데이터 보내기

  • 시그널을 통해서 한 객체로 다른 객체로 값 보내기
  • ex) 가상화폐 금액 조회기 프로그램 개발
    • 1) 금액 조회 클래스
    • 2) 조회된 값 출력 클래스
    • 금액 조회 클래스는 금액 조회가 완료되자마자 시그널 발생
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class MySignal(QObject):
    signal1 = pyqtSignal()
    signal2 = pyqtSignal(int, int)

    def run(self):
        self.signal1.emit()
        self.signal2.emit(1, 2)

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

        mysignal = MySignal()
        mysignal.signal1.connect(self.signal1_emitted)
        mysignal.signal2.connect(self.signal2_emitted)
        mysignal.run()

    @pyqtSlot()
    def signal1_emitted(self):
        print('signal1_emitted')

    @pyqtSlot(int, int)
    def signal2_emitted(self, arg1, arg2):
        print('signal2_emitted', arg1, arg2)

app = QApplication(sys.argv)
win = MyWindow()
win.show()
app.exec_()
  • signal2의 경우 : emit() 메서드 호출하여 시그널을 발생시킬 때 슬롯으로 전달하고자 하는 값을 넘겨줌
  • MyWindow 클래스에 정의된 슬롯(메서드)
    • 슬롯 : 시그널이 발생할 때 호출당하는 콜백함수
    • 시그널로부터 데이터가 전송되기 때문에 이를 메서드의 인자를 통해 받아주면 됨
    • 데커레이터를 통해 타입도 적어줌
profile
hello world!

0개의 댓글