python PyQt5程序运行界面无响应

写在前面

此文档仅记录本人遇到的问题及解决办法,并非涵盖所有

最近写一个股价监控小程序,在改进为界面程序后,每次运行到耗时方法时界面就卡死,无响应,花费了很长事件才把问题解决了,记录一下

原因分析

程序在主线程中执行,当主程序中有一个事件比较耗时时,主程序就会等耗时事件处理完才会进行下一步,此时界面就会卡死出现无响应的状态

代码展示

main.py

import sys
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QApplication

import stock_price_wring

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainW = QMainWindow()
    ui = monitor.Ui_MainWindow()
    ui.setupUi(mainW)
    mainW.show()
    sys.exit(app.exec_())

调用的耗时代码

 def do_monitor(monitor_info, send_mail, authorization, receive_mail):
    """
    预警监控
    :param monitor_info: 监控条件数据
    :param send_mail: 发件邮箱
    :param authorization: 授权码
    :param receive_mail: 收件邮箱
    :return: 回显信息
    """
    now_date = datetime.datetime.now().strftime('%Y-%m-%d')
    for item in monitor_info:
        info = get_stock_info(item[0])
        # 判断监控方式
        if item[2] == 0:
            # 价格下跌至
            if float(info['price'][0]) <= item[1]:
                text = info['time'][0] + '  ' + info['name'][0] + '触发预警条件:股价跌到' + str(item[1]) + '元,提醒您及时关注'
                send_content = info['name'][0] + '触发预警条件:股价跌到' + str(item[1]) + '元,提醒您及时关注' + '\n\n' + '股票代码:' + info['code'][0] + '\n' + '股票名称:' + info['name'][0] + '\n' + '预警周期:当日' + '\n' + '预警指标:股价' + '\n' + '时\t\t间:' + now_date + ' ' + info['time'][0]
                res = do_send_mail(send_mail, authorization, receive_mail, send_content)
                monitor_info.remove(item)
                return text+'\n'+res
        elif item[2] == 1:
            # 价格上涨至
            if float(info['price'][0]) >= item[1]:
                text = info['time'][0] + '  ' + info['name'][0] + '触发预警条件:股价涨到' + str(item[1]) + '元,提醒您及时关注'
                send_content = info['name'][0] + '触发预警条件:股价涨到' + str(item[1]) + '元,提醒您及时关注' + '\n\n' + '股票代码:' + info['code'][0] + '\n' + '股票名称:' + info['name'][0] + '\n' + '预警周期:当日' + '\n' + '预警指标:股价' + '\n' + '时\t\t间:' + now_date + ' ' + info['time'][0]
                res = do_send_mail(send_mail, authorization, receive_mail, send_content)
                monitor_info.remove(item)
                return text+'\n'+res
        else:
            return ''

解决办法

  • 使用多线程
    • 主线程只执行界面显示
    • 子线程中执行耗时任务
  • 构建窗口类
    • 编写事件响应代码
    • 开启线程
    • 接收线程发送的数据
    • 数据回显
  • 构建线程类
    • 执行耗时任务
    • 发送数据给主程序(信号

子线程中定义信号和发送信号

# 实例化一个信号
signal = pyqtSignal(str)

# 发送信号
self.signal.emit(text)

主线程中接收信号

# 实例化线程
self.thread = MonitorThread(self)
# 绑定接收线程信号的方法
self.thread.signal.connect(self.receive_signal)

def receive_signal(self, text):
     """
     接收子线程传送的数据 回显至浏览框
     :param text:
     """
     self.textBrowser.append(text)

部分代码展示

代码结构
在这里插入图片描述
程序入口

if __name__ == '__main__':
    log_dir = os.path.join(os.getcwd(), 'log')
    if not os.path.exists(log_dir):
        os.mkdir(log_dir)
    cgitb.enable(format='text', logdir=log_dir)
    app = QApplication(sys.argv)
    myWin = MyMainForm()
    myWin.show()
    sys.exit(app.exec_())

窗口类

class MyMainForm(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MyMainForm, self).__init__(parent)
        self.setupUi(self)
        # 实例化线程
        self.thread = MonitorThread(self)
        # 窗口启动自动执行获取配置数据
        self.read_base_info()
        # 按钮点击事件
        self.chooseBtn.clicked.connect(self.choose_file)
        self.runBtn.clicked.connect(self.start_monitoring)
        # 接收线程信号,进行数据回显
        self.thread.signal.connect(self.receive_signal)

    def read_base_info(self):
        """
        获取基础数据:发件箱,授权码,收件箱
        """
        base_info = pd.read_table('./baseinfo.txt', header=None)
        self.sendMail.setText(base_info[0][0])
        self.authorization.setText(base_info[0][1])
        self.receiveMail.setText(base_info[0][2])

    def choose_file(self):
        """
        选择预警信息的存储文件 -> Excel
        """
        root = tkinter.Tk()
        root.withdraw()
        filepath = filedialog.askopenfilename()
        self.filePath.setText(filepath)

    def start_monitoring(self):
        """
        开始监控 启动子线程 调用子线程接收数据的方法
        """
        # 数据整理
        file_path = self.filePath.text()
        send_mail = self.sendMail.text()
        authorization = self.authorization.text()
        receive_mail = self.receiveMail.text()
        base_info = {'file_path': file_path,
                     'send_mail': send_mail,
                     'authorization': authorization,
                     'receive_mail': receive_mail}
        # 调用线程接收主线程传递数据的方法
        self.thread.accept_info(base_info)
        # 开启子线程
        self.thread.start()

    def receive_signal(self, text):
        """
        接收子线程传送的数据 回显至浏览框
        :param text:
        """
        self.textBrowser.append(text)

子线程类

class MonitorThread(QThread):
    # 实例化一个信号
    signal = pyqtSignal(str)

    def __init__(self, main_form):
        super(MonitorThread, self).__init__()
        self.file_path = ''
        self.send_mail = ''
        self.authorization = ''
        self.receive_mail = ''
        self.main_form = main_form

    def accept_info(self, base_info):
        """
        接收主线程发送的数据
        :param base_info:
        """
        self.file_path = base_info.get('file_path')
        self.send_mail = base_info.get('send_mail')
        self.authorization = base_info.get('authorization')
        self.receive_mail = base_info.get('receive_mail')

    def run(self):
        """
        子线程运行方法,执行耗时任务
        """
        # 获取监控信息
        monitor_info = get_monitor_info(self.file_path)
        # 循环监控
        while True:
            # 调用方法 返回信息
            text = do_monitor(monitor_info, self.send_mail, self.authorization, self.receive_mail)
            # 发送信号
            self.signal.emit(text)
            time.sleep(1)
  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
PythonPyQt5是一种功能强大的GUI框架,可以用于创建具有各种功能的用户界面。离线地图是指不需要网络连接也能进行地图浏览的功能。下面是使用PythonPyQt5设计离线地图界面的一些思路: 1. 导入必要的库:首先,需要导入PyQt5库以及其他可能需要的库,如地图数据处理库。 2. 创建主窗口:使用PyQt5创建一个主窗口,可以设置窗口的标题、大小和位置等属性。 3. 添加地图组件:在主窗口中添加一个用于显示地图的组件,可以是一个图像标签或其他合适的组件。可以通过加载本地地图数据文件,或者使用开源地图数据进行显示。 4. 添加其他界面元素:可以根据需要在主窗口中添加其他界面元素,如按钮、文本框、下拉菜单等,用于地图的操作和控制。 5. 定义地图操作函数:根据具体需求,定义与地图相关的操作函数,如缩放、平移、标记位置等。这些函数可以与界面元素的信号关联起来,以响应用户的操作。 6. 设置界面布局:使用PyQt5的布局管理器,如垂直布局或网格布局,将界面元素放置在合适的位置,并设置合适的大小和间距。 7. 运行应用程序:最后,调用PyQt5的应用程序对象的exec_()方法,运行应用程序并显示主窗口。 总之,使用PythonPyQt5来设计离线地图界面可以有很多灵活的选择。可以根据实际需求来选择合适的地图数据和界面元素,从而设计出符合用户需求的离线地图界面

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值