美文网首页PyQtPythoner集中营
告别会议无趣,也许就差这么一个工具(二)

告别会议无趣,也许就差这么一个工具(二)

作者: 酉月十一 | 来源:发表于2019-01-30 13:37 被阅读4次

    上篇文章我们讲述了系统的布局,这次就来看看功能是怎么实现的。

    3.3 功能函数实现

    在随机点名文件夹下面新建一个python module 名字称:RandomCall.py,用来实现随机点名系统的具体功能。

    3.3.1 核心技术介绍

    随机功能的核心是:利用时间产生随机数,作为下标更新名字。

    涉及到的python模块为time,PyQt的模块为QTimer

    • time

      本篇文章只用到一个函数time.time()来返回当前时间的时间戳;

    • QTimer

      QTimer是PyQt的QtCore的一个模块,QTimer类提供重复性和单次定时器。QTimer类为定时器提供高级编程接口。要使用它,请创建一个QTimer,将其timeout()信号连接到相应的插槽,然后调用start()。从此以后,它将以固定的时间间隔发出timeout()信号。示例代码如下:

    # 实例化QTimer定时器类
    
     time = QTimer(self)
    
    # 设置计时间隔并启动(1000ms == 1s)
    
    time.start(1000)
    
    # 1S 计时结束,触发槽函数
    
    ime.timeout.connect(self.showTime)
    

    首先引入所需要的模块,实现界面展示

    import sys,time
    
    from PyQt5.QtCore import Qt, QFile, QIODevice, QTextStream, QTextCodec
    
    from PyQt5.QtCore import pyqtSlot, QTimer
    
    from PyQt5.QtWidgets import QMainWindow, QApplication
    
    #主窗体设计界面
    
    from Ui_Main import Ui_MainWindow
    

    创建实现功能类,且定义构造函数,

    class RandomCallMain(QMainWindow, Ui_MainWindow):
    
        """
        构造函数
        """
        def __init__(self, parent=None):
        super(RandomCallMain, self).__init__(parent)
    

    添加python主函数,调用实现功能类,显示主界面

    if __name__ == '__main__':
        app = QApplication(sys.argv)
        w = RandomCallMain()
        w.show()
        sys.exit(app.exec_())
    

    运行RandomCall.py文件,主界面显示和运行Ui_Main.py一致,证明程序无问题。

    3.3.2 python读取文件

    随机点名系统产生的名字和福利是通过分别读取【name.txt】和【reward.txt】两个文件存储到列表实现的,代码如下:

    • 读取名字文件
        def getNameFile(self):
    
            """
            读取名字文件
            """
            with open('name.txt', 'r', encoding='UTF-8') as f:
                    self.name_list = f.readlines()
            f.close()
            return self.name_list
    

    通过 with open()读取名字文件,然后将结果保存在self.name_list列表,最后返回列表,供其他函数调用。

    • 读取奖励文件
        def getRewardFile(self):
    
            """
            读取奖励文件
            """
            with open('reward.txt', 'r', encoding='UTF-8') as f:
                    self.reward_list = f.readlines()
            f.close()
            return self.reward_list
    

    通过 with open()读取奖励文件,然后将结果保存在self.reward_list列表,最后返回列表,供其他函数调用。

    TIPS:关于python读取文件网上有很多实例,这里不再重复造轮子。

    3.3.3 开始点名实现
    1. 将开始按钮和槽函数在初始化函数init()进行绑定,代码如下
    #开始按钮绑定槽函数
    
    self.start_button.clicked.connect(self.on_start_button_clicked)
    
    1. 开始槽函数的实现,代码如下:
    def on_start_button_clicked(self):
    
            """
            开始点名
            """
    
            #按开始钮置为不可用
    
            self.start_button.setEnabled(False)
    
            #设置停止按钮为可用
    
            self.pause_button.setEnabled(True)
    
            #记录开始时间
    
            self.start_time = time.time() - self.end_time
    
            #调用界面刷新函数
    
            self.update()
    
    1. 在构造函数init()初始化计数器,代码如下:
    #初始化定时器
    
    self.p_timer = QTimer(self)
    
    #计数结束,触发函数
    
    self.p_timer.timeout.connect(self.update)
    
    1. 界面刷新函数实现,代码如下:
        def update(self):
    
            """
            更新显示内容
            """
            #计算结束时间
            self.end_time = time.time() - self.start_time
    
            #传参调用显示姓名和奖励函数
    
            self.set_name(self.end_time)
    
            #每隔50ms调用一次函数,更新界面显示
    
            self.p_timer.start(50)
    
    1. 选中名字和奖励实现,代码如下:
        def set_name(self, end_time):
            """
            取选中的名字
            """
            #计算数组下标
    
            cur = int(end_time * 100 % 30)
    
            #调用读取名字文件函数
    
            self.getNameFile()
    
            #调用读取奖励文件函数
    
            self.getRewardFile()
    
            #名字和奖励字符串拼接
    
            _str = self.name_list[cur].strip('\n') + ':' + self.reward_list[cur]
    
            #控件QLabel显示名字+奖励
    
            self.select_label.setText(_str)
    
    3.3.4 停止点名实现

    停止点名,主要是停止计数,将开始按钮置为启用,停止按钮置为不启用,代码如下:

    1. 将停止按钮和槽函数在初始化函数init()进行绑定,代码如下
    #开始按钮绑定槽函数
    
    self.pause_button.clicked.connect(self.on_pause_button_clicked)
    

    2.停止槽函数的实现,代码如下:

    def on_pause_button_clicked(self):
    
            """
            停止点名
            """
            #开始按钮置为启用
    
            self.start_button.setEnabled(True)
    
            #停止按钮置为不启用
    
            self.pause_button.setEnabled(False)
    
            #停止计数
    
            self.p_timer.stop()
    

    8.运行RandomCall.py,可以看到本篇文章开始的系统演示,


    随机点名系统.gif

    好了,本次文章就讲到这,接下来一篇文章会介绍随机点名系统美化的方式

    3.3 QSS样式讲解
    3.3.1 QSS的概念

    QSS全称Qt Style Sheets,即Qt样式表。它是Qt提供的一种用来自定义控件外观的机制。QSS大量参考了CSS的内容,只不过QSS的功能比CSS要弱很多,体现在选择器要少,可以使用的QSS属性也要少很多,并且并不是所有的属性都可以用在Qt的所有控件上。

    3.3.1 QSS语法讲解

    QSS的语法规则几乎与CSS相同。一条QSS的样式是由两部分组成的,一部分是选择器指定了哪些控件会受到影响,另一部分是指定了属性的值,表示这些控件的哪些属性会受到影响。例如:

    QPushButton { color: red }
    
    • QPushButton

      表示选择器,指定了所有的QPushButton或者是QPushButton的子类会受到影响,注意凡是继承自QPushButton的子类也会受到影响,这是与CSS中不同的地方,因为CSS应用的都是一些标签,没有类的层次结构,更加没有子类的概念。

    • {color:red}

      规则的定义,表明指定前景颜色是红色。
      整个语法意思就是设置QPushButton类以及其子类的所有控件的前景色是红色。

    1. 选择器

    选择特定的类,如示例中的QPushButton,选择器的选择方式有七种,如下表:

    选中对象 示例 描述
    所有控件 * 选择所有当前控件和其下的所有窗口部件
    所有某类的控件对象,被其子控件对象继承 QPushButton 选择该类的所有实例,以及该类的子控件实例(允许该类型)
    所有某类的控件对象,不被其子控件对象继承 .QPushButton 选择该类的所有实例,不包括子控件实例
    ID选择器 QPushButton #objectname 选择该类实例中对象名为objectName的实例
    选择匹配某属性的控件对象 QPushButton[y=”0”] 选择该类满足该属性条件的所有实例
    某类控件的子控件对象 QWidget > QPushButton 选择指定该类下的直接子控件实例
    某类控件的子孙控件对象 QWidget QPushButton 选择指定该类下的所有子孙控件实例

    QSS样式示例

    • QPushButton背景色置为红色,代码如下:
    QPushButton{background-color:red;}
    
    sparklessparkles
    • 对象名为start_button和pause_button的QPushButton背景色置为绿色,代码如下:
    #start_button,#pause_button{background-color:rrgb(0,255,0)}
    
    sparklessparkles
    1. 子控件(sub-control)

    子控件(同辅助选择器),对于复杂的控件有必要对其子控件窗口进行控制,不同的控件类包含不同的子控件,如QCheckBox中包含indicator子控件。

    QSS示例

    QCheckBox的前面的选择框背景色设置为红色,代码如下:

    QCheckBox#checkBox::indicator{
        width:10px;
        height:10px;
        background-color: red; 
    }
    
    sparklessparkles

    3.状态选择器(pseudo-states)

    状态选择器,可根据不同控件的不同状态对窗口进行控制,如”hover”表示鼠标放上时的状态,”pressed”表示鼠标保持按下时的状态,可根据状态设置不同的外观.

    QSS示例

    鼠标放在QPushButton上面时背景色设置为红色,代码如下:

    QPushButton:hover{background-color:red;}
    
    sparklessparkles

    4.QSS样式其他方式

    • 属性(property)

    属性,是一个窗口部件所固有的特征,每一个类型的窗口控件都会有属于他们自己的属性,如width,height(辅助选择器才有),color等等,定制控件的不同外观。注意:属性是使用逻辑否(!)操作符,如!hover,是鼠标未放在上面的其他状态。

    • 属性值(value)

    属性值,跟在每一个属性后面有一个值,可以是bool,int,10px,red,rgb(0,0,0)等等,根据属性的不同,属性值的类型不同,通过修改指定控件的指定属性的属性值来实现不同的效果,如示例:background-color、width、height等。

    • 盒模型(box model)
      包含了4个影响布局的矩形


      sparklessparkles
      • content rectangle:绘制窗口部件的内容的区域,如文字,图片。
      • padding rectangle:包围content rectangle,由padding属性指定填充操作,主要是窗口部件内容与边缘线(border)之间的空隙,由top,right,bottom和left设置他的大小,缺省为0。
      • border rectangle:包围padding rectangle,为边界预留空间,可认为是窗口的外框线。
      • margin rectangle:最外面的矩形,主要是负责与其他窗口部件间的距离。

    QSS样式还有很多设置方式,如圆角弧度,背景色,九宫格等,本篇文章不再做详细解释,这里给个官方网站,有兴趣的小伙伴可以去看:
    http://doc.qt.io/qt-5/qtwidgets-module.html

    3.3.1 QSS样式使用方式
    • 方法一,直接在代码使用,如下
    #设置开始按钮的背景色为红色
    self.start_button.setStyleSheet(“background-color:red;”)
    
    • 方案二,将样式设置写在一个后缀名为.qss的文件里面,然后在代码界面加载该文件,实现逻辑功能和样式美化的分离,本文使用的就是这个方式
    1. 在随机点名文件夹下面新建一个文件,命名为【style.qss】,代码如下:
    /*设置主窗口背景*/
    #centralwidget{
        background-color:rgb(157, 11, 12);
        border-radius:4px;
        }
    
    /*设置中间窗体显示背景*/
    #mid_widget{
        background-color: rgb(244, 216, 215);
        }
    
    /*中间窗体按钮样式*/
    #start_button,#pause_button{
        /*定义最小最大宽高*/
        min-width: 36px;
        min-height: 36px;
        color: balck;   /*文字颜色*/
        font-size:18px;
        }
    
    /*中间窗体按钮鼠标浮在上面的样式*/
    #start_button:hover,#pause_button:hover{
        background-color: red; /*带透明度白色背景*/
    }
    
    /*名字显示样式设置*/
    #select_label{
        font-size: 18px "黑体";
    
    1. 在RandomCall.py新建一个函数readQss用来读取qss文件,代码如下:
    def readQss():
    """读取qss文件"""
    
        with open('style.qss',encoding='UTF-8') as f :
    
            data = f.read()
    
            f.close()
    
        return data
    
    1. 在主函数调用readQsss函数实现样式,代码如下:
    #读取QSS样式
    
    app.setStyleSheet(readQss())
    

    截至到此,本篇文章已经到了尾声,简单总结下,本篇文章介绍了PyQt的布局、控件的使用、QTimer计数器的使用、QSS样式的简单学习,但是对上面的知识点并没有做过深的讲解,本篇只是想为利用python写GUI的小伙伴起到抛砖引玉的作用,如果想深入研究的可以继续学习。

    附录:

    • Ui_Main.py完整代码如下:
    #!/user/bin/env python
    
    # -*- coding: utf-8 -*-
    
    """
    
    Created on 2019年1月17日pa
    
    @author: <u>yiluo</u>
    
    @site: https://github.com/bingshilei
    
    @email: 786129166<u>@qq.com</u>
    
    @file: Ui_Main.py
    
    @description: 随机点名程序,主窗体
    
    """
    import sys
    from PyQt5 import QtCore, QtGui, QtWidgets
    class Ui_MainWindow(QtWidgets.QMainWindow):
    
        def __init__(self, parent=None):
    
            """
         构造函数初始化界面
            """
            super(Ui_MainWindow, self).__init__(parent)
    
            #设置主窗口名字
    
            self.setObjectName("MainWindow")
    
            #设置系统名字
    
            self.setWindowTitle("随机点名系统")
    
            #设置主窗口大小
    
            self.resize(673, 381)
    
            #设置主窗口最小值
    
            self.setMinimumSize(673, 381)
    
            #设置主窗口最大值
    
            self.setMaximumSize(674, 441)
    
            #创建核心窗口
    
            self.centralwidget = QtWidgets.QWidget(self)
    
            #设置核心窗口名字
    
            self.centralwidget.setObjectName("<u>centralwidget</u>")
    
            #创建QLabel显示上层图片
    
            self.top_label = QtWidgets.QLabel(self.centralwidget)
    
            #设置上层QLabel的大小和位置
    
            self.top_label.setGeometry(0, 0, 673, 85)
    
            #为上层QLabel显示图片
    
            self.top_label.setPixmap(QtGui.QPixmap("top.png"))
    
            #设置上层QLabel的名字
    
            self.top_label.setObjectName("top_label")
    
            #创建QLabel显示下层图片
    
            self.bottom_label = QtWidgets.QLabel(self.centralwidget)
    
            #设置下层QLabel的大小和位置
    
            self.bottom_label.setGeometry(0, 300, 673, 85)
    
            #设置下层QLabel的最小值
    
            self.bottom_label.setMinimumSize(673, 85)
    
            #设置下层QLabel的最大值
    
            self.bottom_label.setMaximumSize(673, 85)
    
            ##为下层QLabel显示图片
    
            self.bottom_label.setPixmap(QtGui.QPixmap("bottom.png"))
    
            #设置下层QLabel的名字
    
            self.bottom_label.setObjectName("bottom_label")
    
            #为中间创建一个窗体
    
            self.mid_widget = QtWidgets.QWidget(self.centralwidget)
    
            #设置中间窗体的位置和大小
    
            self.mid_widget.setGeometry(6, 91, 660, 206)
    
            #设置中间窗体的名字
    
            self.mid_widget.setObjectName("mid_widget")
    
            #为中间窗体设置一个水平布局
    
            self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.mid_widget)
    
            #调整中间窗体的位置(将左、上、右、下的外边距设置为不同的值)
    
            self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
    
            #设置中间窗体布局的名字
    self.horizontalLayout_2.setObjectName("horizontalLayout_2")
    
            #为水平布局设置水平、垂直方向的大小调整策略
    
            spacerItem = QtWidgets.QSpacerItem(209, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
    
            self.horizontalLayout_2.addItem(spacerItem)
    
            #创建一个垂直布局
    
            self.verticalLayout = QtWidgets.QVBoxLayout()
    
            #设置垂直布局名字
    
            self.verticalLayout.setObjectName("verticalLayout")
    
            #创建一个QLable显示被抽中的人和福利
    
            self.select_label = QtWidgets.QLabel("王天安-组长发10元红包", self.mid_widget)
    
            #设置最小值
    
            self.select_label.setMinimumSize(204, 63)
    
            #设置最大值
    
            self.select_label.setMaximumSize(209, 63)
    
            #设置QLabel显示格式
    
            self.select_label.setFrameShape(QtWidgets.QFrame.Panel)
    
            self.select_label.setFrameShadow(QtWidgets.QFrame.Plain)
    
            #设置文字位置居中
    
            self.select_label.setAlignment(QtCore.Qt.AlignCenter)
    
            #设置可以自动换行
    
            self.select_label.setWordWrap(True)
    
            #设置QLabel显示名字
    
            self.select_label.setObjectName("select_label")
    
            #为垂直布局选中人的QLabel控件
    
            self.verticalLayout.addWidget(self.select_label)
    
            #创建水平布局
    
            self.horizontalLayout = QtWidgets.QHBoxLayout()
    
            #设置水平布局名字
    
            self.horizontalLayout.setObjectName("horizontalLayout")
    
            #创建开始按钮
    
            self.start_button = QtWidgets.QPushButton("开始", 
    self.mid_widget)
    
            #设置开始按钮名字
    
            self.start_button.setObjectName("start_button")
    
            #为垂直布局增加开始按钮
    
            self.horizontalLayout.addWidget(self.start_button)
    
            #为水平布局设置水平、垂直方向的大小调整策略
    
            spacerItem1 = QtWidgets.QSpacerItem(
    
                24, 20, QtWidgets.QSizePolicy.Fixed, 
    QtWidgets.QSizePolicy.Minimum)
    
            self.horizontalLayout.addItem(spacerItem1)
    
            #创建停止按钮
    
            self.pause_button = QtWidgets.QPushButton("停止", 
    self.mid_widget)
    
            #设置停止按钮名字
    
            self.pause_button.setObjectName("pause_button")
    
            #为水平布局怎加停止按钮控件
    
            self.horizontalLayout.addWidget(self.pause_button)
    
            #布局嵌套
    
            self.verticalLayout.addLayout(self.horizontalLayout)
    
            self.horizontalLayout_2.addLayout(self.verticalLayout)
    
            #为水平布局设置水平、垂直方向的大小调整策略
    
            spacerItem2 = QtWidgets.QSpacerItem(
    
                209, 20, QtWidgets.QSizePolicy.Expanding, 
    QtWidgets.QSizePolicy.Minimum)
    
            self.horizontalLayout_2.addItem(spacerItem2)
    
            #核心窗体初始化
    
            self.setCentralWidget(self.centralwidget)
    
            #创建菜单栏
    
            self.menubar = QtWidgets.QMenuBar(self)
    
            #设置菜单栏的大小和位置
    
            self.menubar.setGeometry(0, 0, 673, 23)
    
            #设置菜单栏的名字
    
            self.menubar.setObjectName("<u>menubar</u>")
    
            #添加菜单栏
    
            self.setMenuBar(self.menubar)
            
    if __name__ == "__main__":
    
        """
         主函数,实例化界面类并显示
        """
        app = QtWidgets.QApplication(sys.argv)
        ui = Ui_MainWindow()
        ui.show()
        sys.exit(app.exec_())
    
    • RandomCall.py完整代码如下:
    #!/user/bin/env python
    
    # -*- coding: <u>utf</u>-8 -*-
    
    """
    
    Created on 2019年1月17日
    
    @author: <u>yiluo</u>
    
    @site: https://github.com/bingshilei
    
    @email: 786129166<u>@qq.com</u>
    
    @file: RandomCallMain.py
    
    @description: 随机点名程序,功能函数实现
    
    """
    
    
    
    import sys, time
    
    from PyQt5.QtCore import Qt
    
    from PyQt5.QtCore import  QTimer
    
    from PyQt5.QtWidgets import QMainWindow, QApplicatio
    
    #导入主界面函数
    from Ui_main import Ui_MainWindow
    
    class RandomCallMain(QMainWindow, Ui_MainWindow):
    
        """
       随机点名系统功能类.
        """
    
        def __init__(self, parent=None):
    
            """
           构造函数
            """
    
            super(RandomCallMain, self).__init__(parent)
    
            #窗体透明
    
            self.setAttribute(Qt.WA_TranslucentBackground, True)
    
            self.setupUi(self)
    
            #初始化显示信息
    
            self.select_label.setText('开始点名')
    
            #初始化开始时间
    
            self.start_time = 0.0
    
            #初始化结束时间
    
            self.end_time = 0.0
    
            #初始化定时器
    
            self.p_timer = QTimer(self)
    
            #计数结束,触发函数
    
            self.p_timer.timeout.connect(self.update)
    
            #开始按钮绑定槽函数
            self.start_button.clicked.connect(self.on_start_button_clicked)
            
            #停止按钮绑定槽函数
            self.pause_button.clicked.connect(self.on_pause_button_clicked)
    
    
    
        
    
        def keyPressEvent(self, e):
        """
        重写鼠标退出事件,ESC键退
        """
    
            if e.key() == Qt.Key_Escape:
    
                self.close()
    
    
        def on_start_button_clicked(self):
    
            """
            开始点名
    
            """
            #按钮置为不可用
    
            self.start_button.setEnabled(False)
    
            self.pause_button.setEnabled(True)
    
            self.start_time = time.time() - self.end_time
    
            self.update()
    
    
    
        def update(self):
    
            """
            更新显示内容
    
            """
            try:
    
                self.end_time = time.time() - self.start_time
    
                self.set_name(self.end_time)
    
                #每隔50ms调用一次函数,更新界面显示
    
                self.p_timer.start(50)
    
            except Exception as e:
    
                print(e)
    
    
    
        def getNameFile(self):
    
            """
            读取名字文件
            """
    
            with open('name.txt', 'r', encoding='UTF-8') as f:
    
                    self.name_list = f.readlines()
    
            f.close()
    
            return self.name_list
    
    
    
        def getRewardFile(self):
    
            """
            读取奖励文件
    
            """
    
            with open('reward.txt', 'r', encoding='UTF-8') as f:
    
                    self.reward_list = f.readlines()
    
            f.close()
    
            return self.reward_list
    
    
    
        def set_name(self, end_time):
    
            """
            取选中的名字
            """
    
            #计算数组下标
    
            cur = int(end_time * 100 % 30)
    
            self.getNameFile()
    
            self.getRewardFile()
    
            #字符串拼接
    
            _str = self.name_list[cur].strip('\n') + ':' + self.reward_list[cur]
    
            #显示名字+奖励
    
            self.select_label.setText(_str)
    
    
        def on_pause_button_clicked(self):
    
            """
          停止点名
            """
    
            self.start_button.setEnabled(True)
    
            self.pause_button.setEnabled(False)
    
            self.p_timer.stop()
    
    def readqss():
    
        with open('style.qss',encoding='UTF-8') as f :
    
            data = f.read()
    
            f.close()
    
        return data
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
    
        #加载qss文件
    
        app.setStyleSheet(readQss())
    
        w = RandomCallMain()
    
        w.show()
    
        sys.exit(app.exec_())
    
    

    相关文章

      网友评论

        本文标题:告别会议无趣,也许就差这么一个工具(二)

        本文链接:https://www.haomeiwen.com/subject/mgpijqtx.html