如何在 PyQt5 中的文件对话框之后启动表格的交互式视图? [英] How to launch an interactive view of a table after file dialog in PyQt5?

查看:133
本文介绍了如何在 PyQt5 中的文件对话框之后启动表格的交互式视图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 PyQt5,我制作了两个小部件.第一个小部件是一个用户提示,用于选择一个带有确认所选文件路径的警报的文件.BackEnd 读取选中的数据文件并处理数据;为了MWE,dataBackEnd中被定义为一个二维数组,被选中的文件仅用于获取文件路径.第二个小部件加载表格的视图供用户查看.(它还与此问题无关,但我的用例是我希望用户通过单击特定单元格来选择行/列.)我可以让第二个小部件自行工作,但是如果我第一次加载第一个小部件,则该表不会加载. 我认为我没有遗漏任何 .close().exec_() 方法,所以我不确定为什么第二个小部件不会加载.这个错误的原因是什么,我该如何规避它?我在之前的尝试中尝试使用 on_clicked() 方法,但我不确定如何将其应用于不同类型的不相同的小部件/表格/等.

Using PyQt5, I made two widgets. The first widget is a user-prompt to select a file with an alert that confirms the selected filepath. The BackEnd reads the selected data file and processes the data; for the sake of MWE, data is defined in BackEnd as a 2-d array and the selected file is only used to get a filepath. The second widget loads a view of the table for the user to look at. (It is not yet relevant to this question, but my use case is that I would like to have a user to select rows/columns by clicking on particular cells.) I can get the second widget to work by itself, but the table does not load if I first load the first widget. I don't think I am missing any .close() or .exec_() methods, so I'm not sure why the second widget will not load. What is the cause of this error and how do I circumvent it? I tried using on_clicked() methods in previous attempts, but I'm not sure how to apply that to different types of widgets/tables/etc that are not identical.

下面的代码是二维数组的表格视图.

The code below is for the table-view of the 2-d array.

import sys
from PyQt5 import QtWidgets, QtGui, QtCore
import numpy as np

class BackEnd():

    def __init__(self):
        super().__init__()
        # ...
        nrows, ncols = 50, 10
        self.data = np.arange(nrows * ncols).reshape((nrows, ncols)).astype(str)

class TableModel(QtCore.QAbstractTableModel):

    """
    An instance of this class is created inside the constructor
    of the class 'TableWindow'.
    """

    def __init__(self, data):
        super(TableModel, self).__init__()
        self._data = data

    def data(self, index, role):
        if role == QtCore.Qt.DisplayRole:
            # See below for the nested-list data structure.
            # .row() indexes into the outer list,
            # .column() indexes into the sub-list
            return self._data[index.row()][index.column()]

    def rowCount(self, index):
        # The length of the outer list.
        return len(self._data)

    def columnCount(self, index):
        # The following takes the first sub-list, and returns
        # the length (only works if all rows are an equal length)
        return len(self._data[0])

class TableWindow(QtWidgets.QMainWindow):

    """
    This class is used to view the raw data file via gui.
    """

    def __init__(self, data):
        super().__init__()
        self.table = QtWidgets.QTableView()
        self.model = TableModel(data)
        self.table.setModel(self.model)
        self.setCentralWidget(self.table)
        self.setWindowTitle("Select 'row' if each student corresponds to a row; otherwise, select 'column'")

通过运行下面的代码片段,您应该能够看到一个显示表格视图的弹出窗口(第二个小部件).

By running the code snippet below, one should be able to see a pop-up showing a view of the table (second widget).

back_end = BackEnd()

## initialize application
app = QtWidgets.QApplication(sys.argv)

## view data file
window = TableWindow(back_end.data.tolist())
window.show()

## exit application
sys.exit(app.exec_())

当尝试组合两个小部件时,上面的代码片段应该被注释掉.下面的代码用于文件选择小部件(第一个小部件).

When trying to combine the two widgets, the code snippet above should be commented out. The code below is for the file selection widget (first widget).

class MainWindow(QtWidgets.QMainWindow):


    """
    This class contains all GUI methods.
    """

    def __init__(self):
        self._backend = BackEnd()
        self._fpath = None
        super().__init__()
        self.initialize_ui()

    @property
    def backend(self):
        return self._backend

    @property
    def fpath(self):
        return self._fpath

    def initialize_ui(self):
        self.select_input_data_file()
        self.verify_input_data_file()
        # self.close()
        self.interact_with_table()

    def select_input_data_file(self):
        dialog = QtWidgets.QFileDialog(
            self,
            "Select input file",
            "path",
            "",
            supportedSchemes=["file"],
            options=QtWidgets.QFileDialog.DontUseNativeDialog)
        fpath = dialog.getOpenFileName(None, 'Open file', '/home')[0]
        self._fpath = fpath
        # dialog.close()
        # dialog = None

    def verify_input_data_file(self):
        alert = QtWidgets.QMessageBox()
        alert.setText('The input filepath you selected is: \n{}'.format(self.fpath))
        alert.exec_()
        # alert.close()
        # alert = None

    def interact_with_table(self):
        window = TableWindow(self.backend.data.tolist())
        window.show()

下面的代码是我尝试让用户使用第一个小部件选择文件(成功)然后显示数据表(不成功).

The code below is my attempt at having the user use the first widget to select a file (successful) and then show the data table (unsuccessful).

## initialize application
app = QtWidgets.QApplication(sys.argv)

## view data file
window = MainWindow()
window.show()

## exit application
sys.exit(app.exec_())

推荐答案

MainWindow.interact_with_table 中,TableWindow 小部件被分配给一个局部变量.当 interact_with_table 返回时,此变量超出范围并且 TableWindow 的引用计数为零.这将导致在下一个垃圾回收周期中删除 TableWindow 对象.一种解决方案是对表格窗口进行持久引用,例如通过将其分配给 MainWindow 的实例变量,即

In MainWindow.interact_with_table, the TableWindow widget is assigned to a local variable. When interact_with_table returns, this variable goes out of scope and the reference count of TableWindow goes to zero. This will cause the TableWindow object to be deleted during the next garbage collection cycle. One solution is to make a persistant reference to the table window for example by assigning it to an instance variable of MainWindow, i.e.

def interact_with_table(self):
    self.table_window = TableWindow(self.backend.data.tolist())
    self.table_window.show()

这篇关于如何在 PyQt5 中的文件对话框之后启动表格的交互式视图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆