前言:
闲着无聊写个简单的抽签工具,原意是为了决定某个群的抽签顺序,既然都准备开始做了,那就写个带界面的小程序,正好回顾一下PyQt的用法
界面外观:
整个界面由两个文本框和两个按键组成,非常的简单。如果有机会受到群友反馈的话,可以稍微做的复杂一点。左边的文本框显示昵称,右边的文本框显示抽取的顺位。
在原本的计划中,只有一个“开始”按钮,点击一次抽取一个结果。不过这样就会显得没有抽签的仪式感,最好在两个框中出现滚动的条目,所以就在“开始”按键边上增加了一个“结束”按键。点击“开始”,则开始滚动名称和顺位,点击“结束”则结束随机,固定显示最后的结果。详细的用法说明会在上传的资源中,以单独的小文件描述。
逻辑设计:
这个工具一共有三个信号。一个与“开始”按键绑定,一个与“结束”按键绑定,另一个与滚动显示绑定。
开始按键信号:
负责发送“开始滚动”信号,以及确认当前剩余未被选中的人数。当现有未被选中的人数仅为1时,那就不需要随机了,因为剩余顺位为1,剩余人数也为1,只能这样绑定了,那就直接进入结束模式,发送“结束”信号,并且停止滚动,直接返回。
def startRandomDraw(self):
self.start_clicked = True
if (len(self.name_list) == 0):
self.showMessage()
return
elif (len(self.name_list) == 1):
self.pause()
self.stop_button.click()
return
self._time_signal.emit()
self.resume()
结束按键信号:
负责发送“结束滚动”信号。不过当开始按键没有被按下的时候,按“结束”按键应该无效。另外也需要确认当前剩余未被选中的人数,当当前未被选中的人数为0时,直接显示结果。在人数大于等于1时,按下“结束”按键,需要在当前人物列表和顺位列表中仍有的选项中,随机选出一个,并将这个选项从当前的顺位和人物列表中移除,以避免同一个人或同一个顺位再次被选中。
def stopRandomDraw(self):
if (self.start_clicked == False):
# ignore the stop clicked signal
return
if (len(self.name_list) == 0):
self.showMessage()
return
self.pause()
item = self.name_list.pop(0)
order = self.count_list.pop(0)
self.name_edit.setText(item)
self.order_edit.setText(str(order+1))
self.name_result[order] = item
滚动显示信号:
在后台长期滚动,仅当“结束”按键被按下后,到“开始”按键被按下前,屏幕滚动暂停。滚动信号完全由“开始”和“结束”按键控制。从程序第一次被按下“开始”按键后,就在屏幕滚动。由于一直会对屏幕进行操作,所以滚动显示信号需要一个独立的线程,由线程发送信号,去修改主线程的UI。线程具体实现就不是本文谈论的重点,这边只展示控制信号部分代码。
def showNameAndOrder(self):
random.shuffle(self.name_list)
random.shuffle(self.count_list)
self.name_edit.setText(self.name_list[0])
self.order_edit.setText(str(self.count_list[0]+1))
def showNameAndOrderSingal(self):
while self.__running.isSet():
self.__flag.wait()
while (True):
self.__flag.wait()
self._time_signal.emit()
time.sleep(0.1)
在结束所有抽签之后,展示之前的所有结果。因为觉得没必要重新设计一个界面,就直接使用的QtWidgets.QMessageBox.information,通过弹窗信息来展示结果。
def showMessage(self):
res = ""
for i in range(len(self.name_result)):
res += "{}\t{}\n".format((i+1), self.name_result[i])
QtWidgets.QMessageBox.information(QtWidgets.QWidget(), "抽签结果", res,
QtWidgets.QMessageBox.Ok)
app = QtWidgets.QApplication.instance()
app.quit()
这边居然遇到了最大的坑,也怪我太蠢。information的第一个参数一直没有设置对,其实它是想让我提供一个实例,但是我一直提供的是一个类,而不是类的实例,所以一直在报如下的错
builtins.TypeError: information(QWidget, str, str, buttons: Union[QMessageBox.StandardButtons, QMessageBox.StandardButton] = QMessageBox.Ok, defaultButton: QMessageBox.StandardButton = QMessageBox.NoButton): argument 1 has unexpected type 'RandDraw_UI'
查了查人家说的也都不是这个问题,大概这么蠢直接用类,而不是用实例的就我一个吧。。反正重点不能用self,也不能用QtWidgets.QWidget,应该要用QtWidgets.QWidget()
大概就这么多吧,工具就上传到这个链接底下了,有需要直接使用工具的,可以自行下载。