Pyside2是Qt框架的Python实现,借着Python的大热,对推广Qt框架也是很好的推动,Qt对线程有专门的类QThread,但是在C++下的子线程处理用在Pyside2中虽然能正常退出程序,但是返回的code始终不是0。所以采用信号告知运行结束的方式进行处理。 C++线程处理:Ui_process为用户操作处理类,将用户操作转给不同的类处理。在这里有File_process、Track_process及各自对应的子线程。 - #ifndef UI_PROCESS_H
#define UI_PROCESS_H
#include <QObject> #include <QThread>
class File_process; class Track_process; class Track_data;
class Ui_process : public QObject { Q_OBJECT public: explicit Ui_process(QObject *parent = nullptr); ~Ui_process();
void get_filter_conditions(QMap<QString, QVariant>* filter, QList<Track_data* >* list);
public slots: void sl_open_files(); void sl_split_data_to_files(); void sl_exit_application();
signals: void si_open_files(QStringList files_name);
void si_split_data_to_files(QStringList files_name);
void si_send_track_to_model(Track_data* data);
void si_clear_model_();
void si_send_filter_and_track_to_process(QMap<QString, QVariant>* filter, QList<Track_data* >* list);
void si_updte_model_by_filter(int row, bool flag);
private: void init_connects();
/*************************************************************************** @Date 2021-05-23 @Author qiaowei @Contact weiweiqiao@126.com @Version 1.0 @Brief Create a sub thread @Param thread sub thread @Param process pointer moved into sub thread ***************************************************************************/ void start_sub_thread(QThread& thread, QObject* process);
private: // 文件处理类及对应子线程 File_process* file_process_; QThread file_thread_;
// 航迹处理类及对应子线程 Track_process* track_process_; QThread track_thread_;
};
#endif // UI_PROCESS_H
Ui_process类实现: - #include <QApplication>
#include <QFileDialog> #include <QtDebug> #include <QMetaType> #include "ui_process.h" #include "file_process.h" #include "track_process.h" #include "../data_modules/track_data.h"
Ui_process::Ui_process(QObject *parent) : QObject(parent) , file_process_(new File_process()) , track_process_(new Track_process()) { init_connects(); }
Ui_process::~Ui_process() { if ((nullptr != track_process_) && (thread() == track_process_->thread())) { delete track_process_; track_process_ = nullptr; }
track_thread_.quit(); track_thread_.wait();
if ((nullptr != file_process_) && (thread() == file_process_->thread())) { delete file_process_; file_process_ = nullptr; }
file_thread_.quit(); file_thread_.wait(); }
void Ui_process::get_filter_conditions(QMap<QString, QVariant> *filter, QList<Track_data *> *list) { start_sub_thread(track_thread_, track_process_);
emit si_send_filter_and_track_to_process(filter, list); }
void Ui_process::sl_open_files() { QStringList files_list = QFileDialog::getOpenFileNames();
if ( !files_list.isEmpty()) { emit si_clear_model_();
start_sub_thread(file_thread_, file_process_);
emit si_open_files(files_list); } }
void Ui_process::sl_split_data_to_files() { QStringList files_list = QFileDialog::getOpenFileNames();
if ( !files_list.isEmpty()) { start_sub_thread(file_thread_, file_process_);
emit si_split_data_to_files(files_list); } }
void Ui_process::sl_exit_application() { QApplication::closeAllWindows(); }
void Ui_process::init_connects() { connect(this, &Ui_process::si_split_data_to_files, file_process_, &File_process::sl_split_data_to_files);
connect(this, &Ui_process::si_send_filter_and_track_to_process, track_process_, &Track_process::sl_filter_track_data);
connect(this, &Ui_process::si_open_files, file_process_, &File_process::sl_open_files_to_show);
connect(file_process_, &File_process::si_send_track_to_model, this, &Ui_process::si_send_track_to_model);
connect(track_process_, &Track_process::si_update_track_by_filter, this, &Ui_process::si_updte_model_by_filter); }
void Ui_process::start_sub_thread(QThread &thread, QObject *process) { if ( !thread.isRunning()) { if (nullptr != process) { process->moveToThread(&thread);
connect(&thread, &QThread::finished, process, &QObject::deleteLater);
thread.start(); } } }
在析构函数中对子线程进行的比对,当线程不为空指针且在主线程中,说明子线程未启动,直接delete;反之,子线程已启动,使用quit,wait方法进行关闭处理。 Python处理:在UiProcess类中定义关闭子线程函数sl_stop_sub_thread(self, code: int),当在子线程运行的函数结束时,发射结束信号,调用sl_stop_sub_thread(self, code: int) - # !/usr/bin/env python
# encoding: utf-8 # @File : ui_process_module.py # @Time : 2021/5/17 # @Author : qiaowei # @Version : 1.0 # @Email : weiweiqiao@126.com # @License : (C) Copyright 2013-2021 # @Brief :
import ctypes from PySide2.QtCore import QObject from PySide2.QtCore import QThread from PySide2.QtWidgets import QApplication from PySide2.QtWidgets import QFileDialog from PySide2.QtCore import Slot from PySide2.QtCore import Signal from process_package.data_process_module import DataProcess
class UiProcess(QObject): def __init__(self): super(UiProcess, self).__init__() # 在构造函数中创建变量对象__data_process,__thread,在私有函数__instance中实例化 self.__data_process = None self.__thread = None
self.__instance() self.__connect()
@Slot() def sl_open_track_files(self): files = QFileDialog.getOpenFileNames()[0] if 0 != len(files): pass
@Slot() def sl_split_data_to_files(self): """ 打开文件,将文件内容按条件保存到不同的文件中
:return: None """ files = QFileDialog.getOpenFileNames()[0] # 选取文件数量不为0 if 0 != len(files): if self.__setup_sub_thread(self.__thread, self.__data_process): self.si_split_data_to_files.emit(files)
@Slot() def sl_quit_application(self): """ Slot function, quit application
:return: None """ QApplication.closeAllWindows()
@Slot(int) def sl_stop_sub_thread(self, code: int): """ 根据标志位关闭子线程
:param code: 子线程标志位。0为__thread
:return: None """ if 0 == code: self.__thread.exit()
def __instance(self): self.__data_process = DataProcess() self.__thread = QThread()
def __connect(self): # 打开文件列表,将文件的数据根据条件保存到不同文件中 self.si_split_data_to_files.connect(self.__data_process.sl_split_data_to_files) # 子线程的任务结束后调用线程关闭函数 self.__data_process.si_stop_sub_thread.connect(self.sl_stop_sub_thread)
def __setup_sub_thread(self, thread: QThread, process: QObject): """ 启动子线程
:param thread: 要启动的子线程 :param process: 迁移到子线程中的变量
:return: True 子线程正常启动;False 子线程启动失败 """ if not thread.isRunning(): process.moveToThread(thread) thread.start()
return True
return False
# Signal # 打开文件,读取数据,显示到Model/View si_open_files = Signal(list)
# 打开文件,读取数据,将数据根据条件保存到不同文件中 si_split_data_to_files = Signal(list)
迁入子线程的类,sl_split_data_to_files(self, file_list: list)函数在运行结束前发射结束信号 - # !/usr/bin/env python
# encoding: utf-8 # @File : data_process_module.py # @Time : 2021/5/17 # @Author : qiaowei # @Version : 1.0 # @Email : weiweiqiao@126.com # @License : (C) Copyright 2013-2021 # @Brief : 处理数据类 # @History : 20210521 添加sl_split_data_to_files函数
from PySide2.QtCore import QObject from PySide2.QtCore import QDateTime from PySide2.QtCore import QFile from PySide2.QtCore import QIODevice from PySide2.QtCore import QTextStream from PySide2.QtCore import Slot from PySide2.QtCore import Signal from data_module.constant_module import SYS_RECV_PROCESS
class DataProcess(QObject): def __init__(self): super(DataProcess, self).__init__()
def sl_open_files_to_show_track(self, file_list: list): if 0 == len(file_list): return
@Slot(list) def sl_split_data_to_files(self, file_list: list): """ 根据传入的文件名列表。依次读取每个文件中数据并按设置保存到新建的文件中
:param file_list: 打开的文件名列表
:return: None """ if 0 == len(file_list): return
time = QDateTime().currentDateTime().toString()
# 创建保存process数据的文档 save_process_file = QFile(file_list[0].replace('.log', '_PROCESS_.log')) # save_process_file = QFile('process.log')
try: for name in file_list: file = QFile(name) if not file.exists(): return if not file.open(QIODevice.ReadOnly | QIODevice.Text): return
in_stream = QTextStream(file) # in_stream.setCodec('utf-8') in_stream.setAutoDetectUnicode(True)
# 续写文件模式打开新创建的文件 if save_process_file.open(QFile.WriteOnly | QFile.Truncate | QFile.Append): out_stream_process = QTextStream(save_process_file)
# 按行遍历文件,将符合要求的数据保存到save_process_file文件中 while not in_stream.atEnd(): content = in_stream.readLine() if SYS_RECV_PROCESS in content: out_stream_process << content.replace('sysRecv 1 process', '') << '\n'
file.close() save_process_file.close() except IOError as io_error: print('File error:' + str(io_error)) finally: if file.isOpen(): file.close() if save_process_file.isOpen(): save_process_file.close() # 发射退出子线程的信号 self.si_stop_sub_thread.emit(0)
# 信号,线程完成任务后,向调用线程的对象发射信号 si_stop_sub_thread = Signal(int)
这是目前我能想到的处理方式,如有更好的,希望不吝赐教
|