如何在 PyQt5 中的文件对话框后启动 table 的交互式视图?
How to launch an interactive view of a table after file dialog in PyQt5?
使用 PyQt5,我制作了两个小部件。第一个小部件是 select 文件的用户提示,带有确认 selected 文件路径的警报。 BackEnd
读取selected数据文件并处理数据;为了 MWE,data
在 BackEnd
中定义为二维数组,selected 文件仅用于获取文件路径。第二个小部件加载 table 的视图供用户查看。 (它还与这个问题无关,但我的用例是我想让用户通过单击特定单元格来 select rows/columns。)我可以得到第二个小部件可以自己工作,但是如果我首先加载第一个小部件,table 不会加载。 我认为我没有遗漏任何 .close()
或 .exec_()
方法,所以我不确定为什么第二个小部件不会加载。这个错误的原因是什么,我该如何避免它?我在之前的尝试中尝试过使用 on_clicked()
方法,但我不确定如何将其应用于不同类型的 widgets/tables/etc 不相同。
下面的代码用于二维数组的 table 视图。
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'")
通过下面的 运行 代码片段,应该能够看到一个显示 table(第二个小部件)视图的弹出窗口。
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_())
当尝试组合这两个小部件时,上面的代码片段应该被注释掉。下面的代码用于文件 selection 小部件(第一个小部件)。
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()
下面的代码是我尝试让用户使用第一个小部件 select 一个文件(成功)然后显示数据 table(不成功)。
## 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
returns 时,此变量超出范围并且 TableWindow
的引用计数变为零。这将导致 TableWindow
对象在下一个垃圾回收周期中被删除。一种解决方案是对 table window 进行持久引用,例如将其分配给 MainWindow
的实例变量,即
def interact_with_table(self):
self.table_window = TableWindow(self.backend.data.tolist())
self.table_window.show()
使用 PyQt5,我制作了两个小部件。第一个小部件是 select 文件的用户提示,带有确认 selected 文件路径的警报。 BackEnd
读取selected数据文件并处理数据;为了 MWE,data
在 BackEnd
中定义为二维数组,selected 文件仅用于获取文件路径。第二个小部件加载 table 的视图供用户查看。 (它还与这个问题无关,但我的用例是我想让用户通过单击特定单元格来 select rows/columns。)我可以得到第二个小部件可以自己工作,但是如果我首先加载第一个小部件,table 不会加载。 我认为我没有遗漏任何 .close()
或 .exec_()
方法,所以我不确定为什么第二个小部件不会加载。这个错误的原因是什么,我该如何避免它?我在之前的尝试中尝试过使用 on_clicked()
方法,但我不确定如何将其应用于不同类型的 widgets/tables/etc 不相同。
下面的代码用于二维数组的 table 视图。
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'")
通过下面的 运行 代码片段,应该能够看到一个显示 table(第二个小部件)视图的弹出窗口。
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_())
当尝试组合这两个小部件时,上面的代码片段应该被注释掉。下面的代码用于文件 selection 小部件(第一个小部件)。
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()
下面的代码是我尝试让用户使用第一个小部件 select 一个文件(成功)然后显示数据 table(不成功)。
## 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
returns 时,此变量超出范围并且 TableWindow
的引用计数变为零。这将导致 TableWindow
对象在下一个垃圾回收周期中被删除。一种解决方案是对 table window 进行持久引用,例如将其分配给 MainWindow
的实例变量,即
def interact_with_table(self):
self.table_window = TableWindow(self.backend.data.tolist())
self.table_window.show()