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'로 바꿔준다.

 

+ Recent posts