随机抽签工具——PyQt5实现

前言:

闲着无聊写个简单的抽签工具,原意是为了决定某个群的抽签顺序,既然都准备开始做了,那就写个带界面的小程序,正好回顾一下PyQt的用法

界面外观:

随机抽签工具——PyQt5实现

整个界面由两个文本框和两个按键组成,非常的简单。如果有机会受到群友反馈的话,可以稍微做的复杂一点。左边的文本框显示昵称,右边的文本框显示抽取的顺位。

在原本的计划中,只有一个“开始”按钮,点击一次抽取一个结果。不过这样就会显得没有抽签的仪式感,最好在两个框中出现滚动的条目,所以就在“开始”按键边上增加了一个“结束”按键。点击“开始”,则开始滚动名称和顺位,点击“结束”则结束随机,固定显示最后的结果。详细的用法说明会在上传的资源中,以单独的小文件描述。

逻辑设计:

这个工具一共有三个信号。一个与“开始”按键绑定,一个与“结束”按键绑定,另一个与滚动显示绑定。

开始按键信号:

负责发送“开始滚动”信号,以及确认当前剩余未被选中的人数。当现有未被选中的人数仅为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()

大概就这么多吧,工具就上传到这个链接底下了,有需要直接使用工具的,可以自行下载。

 

上一篇:qt 毛玻璃效果


下一篇:PyQt5 提示框