该代码实现了一个逻辑回归真假新闻分类的GUI界面,下面对代码进行详细解释说明:

  1. 导入必要的模块和包:
import pathlib  # 路径操作模块
import time  # 时间模块
import traceback  # 异常跟踪模块
from typing import Optional, Callable, Generator, Union  # 类型注解
import pandas as pd  # 数据处理模块
from PySide6.QtCore import QAbstractTableModel, Qt, QRunnable, Signal, QThreadPool, QThread, QTimer  # Qt相关模块
from PySide6.QtGui import QPixmap, QIcon  # Qt相关模块
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel, QFileDialog, QTableView, QStackedWidget, \
    QVBoxLayout, QScrollArea, QWidget, QHeaderView, QMessageBox, QDialog  # Qt相关模块
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas  # matplotlib相关模块
from matplotlib.figure import Figure  # matplotlib相关模块
from ui_windows import Ui_MainWindow  # GUI界面设计模块
import main  # 主要的业务逻辑实现模块
  1. 自定义一个TableModel类,继承自QAbstractTableModel,用于将DataFrame数据展示在GUI界面的TableView中:
class TableModel(QAbstractTableModel):
    def __init__(self, data: pd.DataFrame):
        super().__init__()
        self._data = data

    def rowCount(self, parent=None):
        return self._data.shape[0]

    def columnCount(self, parent=None):
        return self._data.shape[1]

    def data(self, index, role=None):
        if role == Qt.DisplayRole:
            return str(self._data.iloc[index.row(), index.column()])
        return None

    def headerData(self, section, orientation, role=None):
        if role == Qt.DisplayRole:
            if orientation == Qt.Horizontal:
                return str(self._data.columns[section])
            else:
                return str(self._data.index[section])
        return None

    def sort(self, column, order=None):
        self.layoutAboutToBeChanged.emit()
        self._data.sort_values(self._data.columns[column], ascending=order == Qt.AscendingOrder, inplace=True)
        self.layoutChanged.emit()

    @property
    def df(self):
        return self._data
  1. 自定义一个TableWidget类,继承自QTableView,用于展示数据:
class TableWidget(QTableView):
    def __init__(self, data: Optional[pd.DataFrame] = None):
        super().__init__()
        if data is not None:
            self.setModel(TableModel(data))
  1. 自定义一个Task类,用于封装需要执行的任务:
class Task:
    def __init__(
            self,
            func: Callable[..., Generator[Union[str, pd.DataFrame], None, None]],
            *args,
            **kwargs
    ):
        self._func = func
        self._args = args
        self._kwargs = kwargs

    def __call__(self):
        try:
            yield from self._func(*self._args, **self._kwargs)
        except Exception as e:
            traceback.print_exc()
            yield str(e)
  1. 自定义一个Worker类,继承自QThread,用于执行任务:
class Worker(QThread):
    resulted = Signal(pd.DataFrame)
    step = Signal(str)
    image = Signal(pathlib.Path)
    wrapper = Signal(list)
    stop = Signal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self._task = None

    def bind_task(self, func, *args, **kwargs):
        self._task = Task(func, *args, **kwargs)

    def run(self):
        if self._task is None:
            raise ValueError("Task not bind")
        print("开始执行")
        for value in self._task():
            if isinstance(value, pd.DataFrame):
                self.resulted.emit(value)
            elif isinstance(value, str):
                print("收到", value)
                self.step.emit(value)
                time.sleep(0.1)
            elif isinstance(value, pathlib.Path):
                print("图片", value)
                self.image.emit(value)
            elif isinstance(value, list):
                self.wrapper.emit(value)
        self.stop.emit()
  1. 自定义一个MatplotlibWidget类,继承自QWidget,用于展示matplotlib绘制的可视化图:
class MatplotlibWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.figure = Figure()
        self.canvas = FigureCanvas(self.figure)
        layout = QVBoxLayout(self)
        layout.addWidget(self.canvas)
        self.setLayout(layout)

    def draw(self, data: pd.DataFrame):
        pass
  1. 自定义一个DrawWorker类,继承自QRunnable,用于执行matplotlib绘制图形的任务:
class DrawWorker(QRunnable):
    def __init__(self, func, *args, **kwargs):
        super().__init__()
        self._func = func
        self._args = args
        self._kwargs = kwargs

    def run(self):
        self._func(*self._args, **self._kwargs)
  1. 自定义一个ImageWidget类,继承自QWidget,用于展示图片:
class ImageWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.label = QLabel()
        self.label.setAlignment(Qt.AlignCenter)
        layout = QVBoxLayout(self)
        layout.addWidget(self.label)
        self.setLayout(layout)
        self.setObjectName("#image")
        self.setStyleSheet(
            """
            #image {
                background-color: white;
                border: 1px solid black;
                border-radius: 5px;
            }
            """
        )

    def draw(self, path: pathlib.Path):
        max_width = 1200
        pix = QPixmap(str(path))
        if pix.width() > max_width:
            pix = pix.scaledToWidth(max_width, Qt.SmoothTransformation)
        self.label.setPixmap(
            pix
        )
        self.setFixedSize(
            pix.width() + 2, pix.height() + 2
        )
  1. 自定义一个TipsDialog类,继承自QDialog,用于展示提示信息:
class TipsDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Tips")
        self.resize(300, 200)
        self.setLayout(QVBoxLayout())
        self.label = QLabel("正在处理数据,请稍后……")
        self.layout().addWidget(self.label)
  1. 自定义一个MainWindow类,继承自QMainWindow和Ui_MainWindow,用于实现GUI界面:
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle("逻辑回归真假新闻分类")  # 设置窗口标题
        self.setWindowIcon(
            QIcon(str(pathlib.Path(__file__).parents[1] / "ui/icon.png"))
        )

        self.stack = QStackedWidget()
        self.widget.setLayout(QVBoxLayout())
        self.widget.layout().addWidget(self.stack)
        self.thread_pool = QThreadPool(self)

        self.table = TableWidget()
        # 全部字段拉伸
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.stack.addWidget(self.table)

        self.area = QScrollArea()
        self.area.setWidgetResizable(True)
        self.container = QWidget()
        self.area.setWidget(self.container)
        self.container.setLayout(QVBoxLayout())
        self.stack.addWidget(self.area)

        self.checkBox.setChecked(True)
        self.checkBox_2.setChecked(True)
        self.checkBox_3.setChecked(True)
        self.checkBox.setEnabled(False)
        self.checkBox_2.setEnabled(False)
        self.checkBox_3.setEnabled(False)

        self.worker = Worker()
        self.worker.resulted.connect(self.update_table)
        self.worker.step.connect(self.update_step)
        self.worker.stop.connect(self.end)
        self.worker.image.connect(self.update_image)
        self.worker.wrapper.connect(self.update_wrapper)
        self.widget_2.setFixedWidth(300)
        self.btn_load.clicked.connec
import pathlibimport timeimport tracebackfrom typing import Optional Callable Generator Unionimport pandas as pdfrom PySide6QtCore import QAbstractTableModel Qt QRunnable Signal QThreadPool QThread QT

原文地址: http://www.cveoy.top/t/topic/g0ME 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录