123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622 |
- # Licensed under GPLv3
- # Written by Sebastian Lohff (seba@someserver.de)
- # http://seba-geek.de/projects/seopardy/
-
- from PySide import QtGui, QtCore
-
- import copy
-
- from gamestate import QuestionAnswers
- from music import MusicBox
- from video import VideoPlayer
- from player import Player, ButtonEvent, nobodyColor
-
- class QuestionWindow(QtGui.QDialog):
- buzzersOpen = QtCore.Signal(bool)
- playerGotQuestion = QtCore.Signal(int)
-
- def __init__(self, players, section, qnumber, question, answers=None, dj=None, parent=None):
- super(QuestionWindow, self).__init__(parent)
-
- self.players = players
- self.section = section
- self.qnumber = qnumber
- self.question = question
- self.dj = dj
-
- self._windowSetup = False
- self._videoPlayer = None
-
- if answers is not None:
- self.answers = answers
- else:
- self.answers = QuestionAnswers(self.section, self.qnumber)
-
- if not self.answers.is_answered():
- if not self._question_has_audio():
- MusicBox.play_music("questionSong")
-
- if self.dj:
- self.answers.set_dj_points(self.dj[1])
- playerNo = self.players.index(self.dj[0])+1
- QtCore.QCoreApplication.postEvent(self, ButtonEvent(playerNo))
-
- self._setupGui()
- self.setWindowTitle("Seopardy - %s - %d" % (section, qnumber*100))
- self._inWindow = False
-
- if self.question["Type"] == "Music":
- tag = "%s-%s" % (self.section, self.qnumber)
- MusicBox.add_music(tag, self.question["Question"])
- MusicBox.play_music(tag)
- elif self.question["Type"] == "Video":
- self._videoPlayer.play()
-
- def get_answers(self):
- return self.answers
-
- def closeEvent(self, event):
- if not self._inWindow:
- self.buzzersOpen.emit(False)
- MusicBox.stop_music()
- if self._videoPlayer:
- self._videoPlayer.stop()
- event.accept()
- else:
- event.ignore()
-
- def _mkQuestionLabel(self, text, monospaced=False):
- question = QtGui.QLabel(text, alignment=QtCore.Qt.AlignCenter)
- question.setWordWrap(True)
- extra = ""
- if monospaced:
- extra += "font-family: monospace;"
- question.setStyleSheet("QLabel { font-size: 40px; %s }" % (extra,))
-
- return question
-
- def _setupGui(self):
- self.layout = QtGui.QVBoxLayout()
-
- seclabel = QtGui.QLabel(self.section)
- seclabel.setStyleSheet("QLabel { font-size: 30px; }")
- self.layout.addWidget(seclabel, alignment=QtCore.Qt.AlignCenter)
- self.layout.addStretch()
-
- qlabel = None
- stretch = 0
- if self.question["Type"] == "Text":
- qlabel = self._mkQuestionLabel(self.question["Question"])
- elif self.question["Type"] == "Music":
- qlabel = self._mkQuestionLabel("Listen...")
- elif self.question["Type"] == "Image":
- qlabel = QtGui.QLabel()
- pixmap = QtGui.QPixmap()
- pixmap.loadFromData(open(self.question["Question"]).read())
- qlabel.setPixmap(pixmap)
- qlabel.setAlignment(QtCore.Qt.AlignCenter)
- elif self.question["Type"] == "Code":
- # to have this a) aligned but b) centered we "cheat" a bit with the spaces...
- code = self.question["Question"].split("\n")
- code = map(lambda x: x.replace("\t", " "), code)
- maxLineLen = max(map(len, code))
- code = map(lambda x: x + ((maxLineLen-len(x))*" "), code)
-
- qlabel = self._mkQuestionLabel("<pre>"+"\n".join(code)+"</pre>", monospaced=True)
- elif self.question["Type"] == "Video":
- self._videoPlayer = VideoPlayer(self.question["Question"], self.question["Audio"])
- qlabel = self._videoPlayer.get_widget()
- stretch = 1
- else:
- raise ValueError("%s is an unknown type for section %s question name %s" % (self.question["Type"], self.section, self.question["Name"]))
-
- self.layout.addWidget(qlabel, stretch=stretch)
-
- self.layout.addStretch()
-
- self.setLayout(self.layout)
-
- def event(self, e):
- if e.type() == ButtonEvent.eventType:
- if e.get_playerno() <= len(self.players) and not self._inWindow:
- done = False
- if self.question["Type"] == "Music":
- MusicBox.stop_music()
- elif self.question["Type"] == "Video":
- self._videoPlayer.pause()
-
- self._inWindow = True
- player = self.players[e.get_playerno()-1]
- qawin = QuestionAnswerWindow(player, self)
- self.playerGotQuestion.emit(e.get_playerno())
- res = qawin.exec_()
- if res == QuestionAnswerWindow.CORRECT:
- self.answers.add_try(player, correct=True)
- self._inWindow = False
- done = True
- self.close()
- elif res == QuestionAnswerWindow.WRONG:
- self.answers.add_try(player, correct=False)
- self._inWindow = False
-
- if not done:
- self.buzzersOpen.emit(True)
- if self.question["Type"] == "Music":
- # resume music if question was not answered
- MusicBox.play_music("%s-%s" % (self.section, self.qnumber))
- elif self.question["Type"] == "Video":
- # resume video if question was not answered
- self._videoPlayer.play()
-
- elif e.get_playerno() > len(self.players) and not self._inWindow:
- # unknown player! to not confuse certain devices we send a buttons open event
- self.buzzersOpen.emit(True)
- print("unknown player", e.get_playerno())
-
-
- return True
- else:
- ret = super(QuestionWindow, self).event(e)
-
- # we want to do this after the window has focus for the first time
- if not self._windowSetup and e.type() == QtCore.QEvent.FocusIn:
- if not self.answers.is_answered():
- self.buzzersOpen.emit(True)
- self._windowSetup = True
-
- return ret
-
-
- def keyPressEvent(self, e):
- if e.key() == QtCore.Qt.Key_Escape:
- if not self.answers.is_answered():
- self.answers.nobody_knew()
- self.close()
- elif not self.answers.is_answered() and e.key() >= ord('1') and e.key() <= ord(str(len(self.players))):
- QtCore.QCoreApplication.postEvent(self, ButtonEvent(int(chr(e.key()))))
-
- @QtCore.Slot(int)
- def playerButtonPress(self, no):
- QtCore.QCoreApplication.postEvent(self, ButtonEvent(int(no)))
-
- def _question_has_audio(self):
- return self.question["Type"] == "Music" or (self.question["Type"] == "Video" and self.question["Audio"])
-
- class QuestionAnswerWindow(QtGui.QDialog):
- CORRECT = 1
- WRONG = 2
- OOPS = 3
-
- def __init__(self, player, parent=None):
- super(QuestionAnswerWindow, self).__init__(parent)
- self.player = player
-
- self._setupGui()
- self.setWindowTitle("Seopardy - Answer by Player %s" % (self.player.name,))
-
-
- # move window to bottom right of screen
- g = QtGui.QApplication.desktop().screenGeometry()
- self.show()
- cPos = self.rect()
- self.move(g.width() - cPos.width(), g.height() - cPos.height())
-
- def _setupGui(self):
- self.layout = QtGui.QVBoxLayout()
-
- self.plabel = QtGui.QLabel(self.player.name)
- self.plabel.setStyleSheet("QLabel { font-size: 60px; }")
- self.layout.addWidget(self.plabel, alignment=QtCore.Qt.AlignCenter)
-
- btnbox = QtGui.QHBoxLayout()
- right = QtGui.QPushButton("Correct")
- right.clicked.connect(lambda: self.done(self.CORRECT))
- btnbox.addWidget(right)
- wrong = QtGui.QPushButton("Wrong")
- wrong.clicked.connect(lambda: self.done(self.WRONG))
- btnbox.addWidget(wrong)
- btnbox.addStretch()
- oops = QtGui.QPushButton("Oops")
- oops.clicked.connect(lambda: self.done(self.OOPS))
- btnbox.addWidget(oops)
- self.layout.addLayout(btnbox)
-
- self.setLayout(self.layout)
-
-
- class EditAnswersWindow(QtGui.QDialog):
- def __init__(self, players, answers, parent=None):
- super(EditAnswersWindow, self).__init__(parent)
- self._players = players
- self._answers = answers
- self._nobody = not answers.got_answered()
- self._dj_points = answers.get_dj_points()
- self._in_window = False
- if self._answers:
- self._tries = copy.copy(self._answers.get_tries())
- else:
- self._tries = []
-
- self._setupGui()
- self.setWindowTitle("Seopardy - Edit Answers")
-
- self.installEventFilter(KeyGrabber((QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right), self))
-
- def get_new_answers(self):
- qa = QuestionAnswers(self._answers.section, self._answers.qnumber, dj_points=self._dj_points)
-
- rightPlayer = None
- for player, correct in self._tries:
- if correct:
- rightPlayer = player
- else:
- qa.add_try(player, correct)
-
- if rightPlayer:
- qa.add_try(rightPlayer, True)
- elif self._nobody:
- qa.nobody_knew()
-
- return qa
-
- def closeEvent(self, event):
- if not self._in_window:
- event.accept()
- else:
- event.ignore()
-
- def _setupGui(self):
- self.layout = QtGui.QVBoxLayout()
-
- self.qlabel = QtGui.QLabel("Questions")
- self.qlabel.setStyleSheet("QLabel { font-size: 30px; }")
- self.layout.addWidget(self.qlabel, alignment=QtCore.Qt.AlignCenter)
-
- self.answerlayout = QtGui.QVBoxLayout()
- self._resetAllButtons()
- self.layout.addLayout(self.answerlayout)
-
- self.xlabel = QtGui.QLabel("+/- right/wrong, d delete, a add, arrows change player\ne edit double jeopardy")
- self.xlabel.setStyleSheet("QLabel { font-size: 15px; }")
- self.layout.addWidget(self.xlabel)
-
- self.setLayout(self.layout)
-
- def keyPressEvent(self, e):
- if e.key() == QtCore.Qt.Key_Escape:
- self.close()
- elif e.key() == QtCore.Qt.Key_E:
- # edit double jeopardy
- if self._dj_points is not None and len(self._tries) > 0 and not self._in_window:
- self._in_window = True
- dwin = DoubleJeopardyWindow(self._players, self._answers.qnumber*100, self._tries[0][0], current_points=self._dj_points, parent=self)
- dwin.exec_()
- self._dj_points = dwin.get_chosen_points()
- self._tries[0] = (dwin.get_player(), self._tries[0][1])
- self._in_window = False
- else:
- currFocus = self._getCurrFocus()
- if currFocus is None and e.key() != QtCore.Qt.Key_A:
- return
-
- nothingDone = False
- if e.key() == QtCore.Qt.Key_Plus:
- self._nobody = False
- for i, (player, correct) in enumerate(self._tries):
- self._tries[i] = (player, i==currFocus)
- if currFocus == len(self._tries):
- self._nobody = True
- elif e.key() == QtCore.Qt.Key_Minus:
- if currFocus == len(self._tries):
- if len(self._tries) == 0:
- self._nobody = False
- else:
- if self._tries[currFocus][1]:
- # give nobody the score for this one
- self._nobody = True
- self._tries[currFocus] = (self._tries[currFocus][0], False)
- elif e.key() == QtCore.Qt.Key_A:
- self._tries.append((self._players[0], False))
- self._makeNobodyConsistent()
- currFocus = len(self._tries) - 1
- elif e.key() == QtCore.Qt.Key_D and currFocus < len(self._tries):
- del self._tries[currFocus]
- elif e.key() == QtCore.Qt.Key_Left and currFocus < len(self._players):
- playlen = len(self._players)
- prevPlayer = self._players[(self._players.index(self._tries[currFocus][0])-1+playlen)%playlen]
- self._tries[currFocus] = (prevPlayer, self._tries[currFocus][1])
- elif e.key() == QtCore.Qt.Key_Right and currFocus < len(self._tries):
- playlen = len(self._players)
- nextPlayer = self._players[(self._players.index(self._tries[currFocus][0])+1+playlen)%playlen]
- self._tries[currFocus] = (nextPlayer, self._tries[currFocus][1])
- else:
- super(EditAnswersWindow, self).keyPressEvent(e)
- nothingDone = True
-
- if not nothingDone:
- self._resetAllButtons()
- self.updateGeometry()
-
- # reset focus
- #print("setting focus to", min(currFocus, self.answerlayout.count()), self.answerlayout.itemAt(min(currFocus, self.answerlayout.count())).widget().text(), self.answerlayout.itemAt(min(currFocus, self.answerlayout.count())).widget().hasFocus())
- self.answerlayout.itemAt(min(currFocus, self.answerlayout.count())).widget().setFocus(QtCore.Qt.FocusReason.NoFocusReason)
- #print("setting focus to", min(currFocus, self.answerlayout.count()), self.answerlayout.itemAt(min(currFocus, self.answerlayout.count())).widget().text(), self.answerlayout.itemAt(min(currFocus, self.answerlayout.count())).widget().hasFocus())
- #print(self.focusWidget())
- #if self.focusWidget():
- # print("widget", self.focusWidget().text())
-
- def _makeNobodyConsistent(self):
- if len(self._tries) > 0:
- someoneKnew = any([c for p, c in self._tries])
- self._nobody = not someoneKnew
-
- def _getCurrFocus(self):
- if self.focusWidget() is not None:
- for i in range(self.answerlayout.count()):
- if self.answerlayout.itemAt(i).widget() == self.focusWidget():
- return i
- return None
-
- def _resetAllButtons(self):
- f = self.answerlayout.takeAt(0)
- while f is not None:
- f.widget().deleteLater()
- f = self.answerlayout.takeAt(0)
-
- # add buttons
- first = True
- for player, correct in self._tries:
- self._addAnswerButton(player, correct, first)
- first = False
-
- # add the nobody button
- self._addAnswerButton(Player("nobody", nobodyColor), self._nobody)
-
- def _addAnswerButton(self, player, correct=False, first=False):
- prefix = "+" if correct else "-"
- dj = " (D)" if first and self._dj_points is not None else ""
- btn = QtGui.QPushButton("\n%s%s%s\n" % (prefix, player.name, dj), self)
- btn.setStyleSheet("QPushButton { background-color: %s; color: white; font-size: 20px; border: none; }" % (player.color.name(),))
- btn.installEventFilter(KeyGrabber((QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right), self))
- self.answerlayout.addWidget(btn)
-
- class KeyGrabber(QtCore.QObject):
- def __init__(self, keys, parent, *args, **kwargs):
- super(KeyGrabber, self).__init__(parent, *args, **kwargs)
- self._keys = keys
- self._parent = parent
-
- def eventFilter(self, obj, e):
- if e.type() == QtCore.QEvent.KeyPress:
- if e.key() in self._keys:
- self._parent.keyPressEvent(e)
- return True
- return QtCore.QObject.eventFilter(self, obj, e)
-
- class PlayerStartWindow(QtGui.QDialog):
- buzzersOpen = QtCore.Signal(bool)
- playerGotQuestion = QtCore.Signal(int)
-
- def __init__(self, players, parent):
- super(PlayerStartWindow, self).__init__(parent)
- self._players = players
- self._parent = parent
-
- self._playerLineEdits = []
- self._windowSetup = False
-
- self._setupGui()
- self.setWindowTitle("Seopardy - Start")
- self.show()
- MusicBox.play_music("startSong")
-
- # center window
- g = QtGui.QApplication.desktop().screenGeometry()
- cPos = self.rect()
- self.move(g.width()/2 - cPos.width()/2, g.height()/2 - cPos.height()/2)
-
- def event(self, e):
- if e.type() == ButtonEvent.eventType:
- if e.get_playerno() <= len(self._players)+1:
- if e.get_playerno() == len(self._players)+1:
- # add a new player
- self._parent.add_player(addToGui=True)
- self._guiAddPlayer(self._players[-1])
-
- layoutItem = self.playerGrid.itemAtPosition(e.get_playerno(), 1)
- if layoutItem:
- widget = layoutItem.widget()
- widget.selectAll()
- widget.setFocus()
-
- self.playerGotQuestion.emit(e.get_playerno())
- return True
- else:
- ret = super(PlayerStartWindow, self).event(e)
-
- if not self._windowSetup and e.type() == QtCore.QEvent.WindowActivate:
- self.buzzersOpen.emit(True)
- self._windowSetup = True
-
- return ret
-
- def closeEvent(self, event):
- MusicBox.stop_music()
- self.buzzersOpen.emit(False)
- event.accept()
-
- def keyPressEvent(self, e):
- # needed to circumvent dialogclosing when enter is pressed
- if e.key() == QtCore.Qt.Key_Escape:
- self.close()
- elif e.key() == QtCore.Qt.Key_K:
- # FIXME: Remove this
- QtCore.QCoreApplication.postEvent(self, ButtonEvent(1))
-
- def _setupGui(self):
- self.layout = QtGui.QVBoxLayout()
- self.playerGrid = QtGui.QGridLayout()
-
- for player in self._players:
- self._guiAddPlayer(player)
-
- self.layout.addLayout(self.playerGrid)
-
- startbtn = QtGui.QPushButton("\nStart\n", self)
- startbtn.setStyleSheet("QPushButton { font-size: 40px; }")
- startbtn.clicked.connect(self.close)
- self.layout.addWidget(startbtn)
-
- self.setLayout(self.layout)
-
- def _guiAddPlayer(self, player):
- row = self.playerGrid.rowCount()
-
- label = QtGui.QLabel("Player %d" % (row,), self)
- label.setStyleSheet("QLabel { font-size: 40px; background-color: %s; color: white; }" % (player.color.name(),))
- self.playerGrid.addWidget(label, row, 0)
-
- edit = QtGui.QLineEdit(player.name, self)
- edit.setStyleSheet("QLineEdit { font-size: 40px; }")
- edit.editingFinished.connect(lambda widget=edit, player=player: self._playerDoneEditing(widget, player))
- self.playerGrid.addWidget(edit, row, 1)
-
- def _playerDoneEditing(self, widget, player):
- player.change_name(widget.text())
- self.buzzersOpen.emit(True)
-
- @QtCore.Slot(int)
- def playerButtonPress(self, no):
- QtCore.QCoreApplication.postEvent(self, ButtonEvent(int(no)))
-
-
- class VictoryWindow(QtGui.QDialog):
- def __init__(self, players, parent):
- super(VictoryWindow, self).__init__(parent)
- self._players = players
- self._parent = parent
-
- self._setupGui()
- self.setWindowTitle("Seopardy - Victory")
- MusicBox.play_music("closingSong")
-
- def _setupGui(self):
- self.layout = QtGui.QVBoxLayout()
- self.playerGrid = QtGui.QGridLayout()
-
- winPlayers = sorted(self._players, key=lambda p: p.points, reverse=True)
- for i, player in enumerate(winPlayers):
- label = QtGui.QLabel(player.name, self)
- fsize = 60 if i == 0 else 25
- label.setStyleSheet("QLabel { font-size: %dpx; background-color: %s; color: white; }" % (fsize, player.color.name(),))
- self.playerGrid.addWidget(label, i, 0)
-
- points = QtGui.QLabel(str(player.points), self)
- points.setStyleSheet("QLabel { font-size: %dpx; }" % (fsize,))
- self.playerGrid.addWidget(points, i, 1, alignment=QtCore.Qt.AlignRight)
-
- self.layout.addLayout(self.playerGrid)
-
- self.setLayout(self.layout)
-
- def keyPressEvent(self, e):
- if e.key() == QtCore.Qt.Key_Escape:
- self.close()
-
- def closeEvent(self, event):
- MusicBox.stop_music()
- event.accept()
-
- class DoubleJeopardyWindow(QtGui.QDialog):
- def __init__(self, player, points, current_player=None, current_points=None, parent=None):
- super(DoubleJeopardyWindow, self).__init__(parent)
- self._player = player
- self._currentPlayer = current_player
- self._points = points
- if current_points:
- self._currentPoints = current_points
- else:
- self._currentPoints = points
-
- self._setupGui()
- self.setWindowTitle("Seopardy - Double Jeopardy")
-
- # move window to bottom right of screen
- g = QtGui.QApplication.desktop().screenGeometry()
- self.show()
- cPos = self.rect()
- self.move(g.width() - cPos.width(), g.height() - cPos.height())
-
- def get_chosen_points(self):
- return self._currentPoints
-
- def get_player(self):
- return self._currentPlayer
-
- def _setupGui(self):
- self.layout = QtGui.QVBoxLayout()
-
- header = QtGui.QLabel("Double Jeopardy", self)
- header.setStyleSheet("QLabel { font-size: 50px; }")
- self.layout.addWidget(header, alignment=QtCore.Qt.AlignCenter)
-
- self.pbtn = QtGui.QPushButton("", self)
- self._stylePlayerButton()
- self.pbtn.installEventFilter(KeyGrabber((QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right), self))
- self.layout.addWidget(self.pbtn)
-
- self.pointsbtn = QtGui.QPushButton("% 5s" % self._currentPoints)
- self.pointsbtn.setStyleSheet("QPushButton { font-size: 50px; border: none; }")
- self.pointsbtn.installEventFilter(KeyGrabber((QtCore.Qt.Key.Key_Left, QtCore.Qt.Key.Key_Right), self))
- self.layout.addWidget(self.pointsbtn, alignment=QtCore.Qt.AlignCenter)
- self.pointsbtn.setFocus()
-
- start = QtGui.QPushButton("Done", self)
- start.clicked.connect(self.closeIfNotNobody)
- self.layout.addWidget(start)
-
- self.setLayout(self.layout)
-
- def closeIfNotNobody(self):
- if self.get_player() is not None:
- self.close()
-
- def keyPressEvent(self, e):
- if e.key() == QtCore.Qt.Key_Escape or e.key() == QtCore.Qt.Key_Enter:
- self.closeIfNotNobody()
- elif e.key() == QtCore.Qt.Key_Left or e.key() == QtCore.Qt.Key_Right:
- if self.focusWidget() == self.pbtn:
- if e.key() == QtCore.Qt.Key_Right:
- if self._currentPlayer == None:
- self._currentPlayer = self._player[0]
- elif self._currentPlayer == self._player[-1]:
- self._currentPlayer = None
- else:
- self._currentPlayer = self._player[self._player.index(self._currentPlayer)+1]
- elif e.key() == QtCore.Qt.Key_Left:
- if self._currentPlayer == None:
- self._currentPlayer = self._player[-1]
- elif self._currentPlayer == self._player[0]:
- self._currentPlayer = None
- else:
- self._currentPlayer = self._player[self._player.index(self._currentPlayer)-1]
- self._stylePlayerButton()
- elif self.focusWidget() == self.pointsbtn:
- if e.key() == QtCore.Qt.Key_Right and self._currentPoints < self._points*2:
- self._currentPoints += 50
- elif e.key() == QtCore.Qt.Key_Left and self._currentPoints > self._points/2:
- self._currentPoints += -50
- self.pointsbtn.setText("% 4s" % self._currentPoints)
-
- def _stylePlayerButton(self):
- player = None
- color = None
- if self._currentPlayer == None:
- player = "nobody"
- color = nobodyColor
- else:
- player = self._currentPlayer.name
- color = self._currentPlayer.color
-
- self.pbtn.setText(player)
- self.pbtn.setStyleSheet("QPushButton { background-color: %s; color: white; font-size: 50px; border: none; }" % (color.name(),))
|