pyside2의 기능 중 하나인 property값과 css를 이용하여 동적으로 변하는 버튼을 만들 수 있다.
test3.py
import sys
import time
from PySide2.QtCore import * # Signal()
from PySide2.QtGui import *
from PySide2.QtWidgets import * # QMainWindow, QWidget, QGridLayout
#qthread 에러 없이 종료하기
class UserButton(QPushButton):
def __init__(self):
super(UserButton, self).__init__()
self._prop = 'false'
with open('test3.css', encoding='utf-8') as f:
self.setStyleSheet(f.read())
def getter(self):
return self._prop
def setter(self, val):
if self._prop == val:
return
self._prop = val
self.style().polish(self)
prop = Property(str, fget=getter, fset=setter)
class intervalThread(QThread):
def __init__(self, b1:UserButton, b2:UserButton):
super(intervalThread,self).__init__()
self.working = True
self.b1 = b1
self.b2 = b2
def run(self):
while self.working:
if self.b1.prop == 'true':
self.b1.prop = 'false'
else:
self.b1.prop = 'true'
print(self.b1.prop)
time.sleep(1)
def stop(self):
self.working = False
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
# QWidget.__init__(self)
self.layout = QGridLayout()
self.setLayout(self.layout)
self.button1 = UserButton()
self.button2 = UserButton()
self.layout.addWidget(self.button1, 0, 0, 1, 1)
self.layout.addWidget(self.button2, 0, 1, 1, 1)
self.thread = intervalThread(self.button1, self.button2)
self.thread.finished.connect(self.stopSig)
self.thread.start()
def stopSig(self):
self.close()
def keyReleaseEvent(self, e):
if e.key() == Qt.Key_Escape:
self.thread.stop()
if e.key() == Qt.Key_S:
self.thread.working=True
self.thread.start()
print("S")
if e.key() == Qt.Key_P:
self.thread.working=False
print("P")
app = QApplication(sys.argv)
lf = MainWindow()
lf.show()
sys.exit(app.exec_())
test3.css
QPushButton{
width : 50px;
height : 50px;
}
QPushButton[prop='true']{
background-color : rgb(0,255,0);
}
QPushButton[prop='false']{
background-color : rgb(255,0,0);
}
QPushButton:hover[prop='true']{
background-color : rgb(0,120,0);
}
QPushButton:hover[prop='false']{
background-color : rgb(120,0,0);
}
일단 전체 코드 먼저 올려놓고 하나씩 보겠다.
test3.py 내용 분석
class UserButton(QPushButton):
def __init__(self):
super(UserButton, self).__init__()
self._prop = 'false'
with open('test3.css', encoding='utf-8') as f:
self.setStyleSheet(f.read())
def getter(self):
return self._prop
def setter(self, val):
if self._prop == val:
return
self._prop = val
self.style().polish(self)
prop = Property(str, fget=getter, fset=setter)
먼저 사용자 버튼이다. pyside(pyqt도 마찬가지)에는 QPushButton이 있는데 QPushButton의 기본 속성말고 추가적으로 내가 사용하고 싶은 속성 정보를 추가할 것이다.
속성의 이름은 'prop'이다.
먼저 사용자 버튼을 생성하면 내부 변수로 _prop를 생성하고 css파일을 불러와 StyleSheet를 설정한다.
test3.css 내용을 보면 알겠지만, 속성값 정보에 따라서 나타나는 동작을 다르게 해놨다.
그리고 이를 갱신하는 경우는 setter 함수가 호출되었을 때, _prop의 값이 변경되었을 때이다. 이 때 self.style().polish(self)를 해주면 style이 업데이트가 된다.
사실 처음에는 hover처럼 pseudo class를 사용자가 직접 생성해서 사용할 수 있는 방법이 없나 알아봤는데, 만드는 방법을 못찾은건지, 없는건지 모르겠어서(stack overflow에서 못만든다고 적혀있는 댓글을 보긴 했다.) 이렇게 속성값을 값이 변화할 때 갱신해주는 형식으로 변경했다.
class intervalThread(QThread):
def __init__(self, b1:UserButton, b2:UserButton):
super(intervalThread,self).__init__()
self.working = True
self.b1 = b1
self.b2 = b2
def run(self):
while self.working:
if self.b1.prop == 'true':
self.b1.prop = 'false'
else:
self.b1.prop = 'true'
print(self.b1.prop)
time.sleep(1)
def stop(self):
self.working = False
그리고 테스트를 위해 Thread를 하나 생성해줬고 말이다. 이놈은 외부에서 속성값을 1초에 한번씩 'true', 'false'로 바꿔준다.