Так что, по сути, я хочу использовать treeView для выбора верхнего уровня в качестве триггера для изменения страницы QStackWidget 1 и дочернего выбора в качестве триггера для изменения страницы QStackWidget 2, как показано на рисунке. Ранее я использовал функцию selectedindexes, чтобы получить выделение, и это работало, но оно перераспределяло данные каждый раз, когда я нажимал на другой файл, и изменения, сделанные на вкладке «Просмотр данных», терялись. Тогда я прочитал о StackedWidgets.
Для каждого нового добавленного файла или фильтра я использовал счетчик (self.counter + = 1) в функции загрузки для добавления новых уровней / потомков и отслеживания количества выполнений определенной функции.
У меня есть 3 вопроса:
- Является ли использование QStackWidget лучшим способом сделать это?
- Как обработать событие удаления, чтобы при удалении третьего файла он правильно отображал данные в других представлениях файлов? Расширение: Является ли использование self.counter лучшим способом для отслеживания загрузки функций?
- Как получить каждую новую страницу с теми же виджетами, что и исходные, но с пустыми данными?
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import ntpath
import matplotlib
import matplotlib.pylab as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import pandas as pd
from scipy.signal import savgol_filter
class Ui_MainWindow(object):
fileCounter = -1
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout_2.setObjectName("gridLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
self.groupBox.setObjectName("groupBox")
self.gridLayout = QtWidgets.QGridLayout(self.groupBox)
self.gridLayout.setObjectName("gridLayout")
self.treeWidget = QtWidgets.QTreeWidget(self.groupBox)
self.treeWidget.setObjectName("treeWidget")
self.gridLayout.addWidget(self.treeWidget, 0, 0, 1, 1)
self.horizontalLayout.addWidget(self.groupBox)
self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget)
self.stackedWidget.setObjectName("stackedWidget")
self.page = QtWidgets.QWidget()
self.page.setObjectName("page")
self.gridLayout_3 = QtWidgets.QGridLayout(self.page)
self.gridLayout_3.setObjectName("gridLayout_3")
self.tabWidget = QtWidgets.QTabWidget(self.page)
self.tabWidget.setObjectName("tabWidget")
self.tab = QtWidgets.QWidget()
self.tab.setObjectName("tab")
self.gridLayout_4 = QtWidgets.QGridLayout(self.tab)
self.gridLayout_4.setObjectName("gridLayout_4")
self.stackedWidget_2 = QtWidgets.QStackedWidget(self.tab)
self.stackedWidget_2.setObjectName("stackedWidget_2")
self.page_3 = QtWidgets.QWidget()
self.page_3.setObjectName("page_3")
self.gridLayout_5 = QtWidgets.QGridLayout(self.page_3)
self.gridLayout_5.setObjectName("gridLayout_5")
# Added Matplotlib
self.plotter = plt.figure()
self.showPlot = FigureCanvas(self.plotter)
self.gridLayout_5.addWidget(self.showPlot, 0, 0, 1, 1)
self.stackedWidget_2.addWidget(self.page_3)
self.page_4 = QtWidgets.QWidget()
self.page_4.setObjectName("page_4")
self.stackedWidget_2.addWidget(self.page_4)
self.gridLayout_4.addWidget(self.stackedWidget_2, 0, 0, 1, 1)
self.tabWidget.addTab(self.tab, "")
self.tab_2 = QtWidgets.QWidget()
self.tab_2.setObjectName("tab_2")
self.gridLayout_6 = QtWidgets.QGridLayout(self.tab_2)
self.gridLayout_6.setObjectName("gridLayout_6")
self.checkBox_2 = QtWidgets.QCheckBox(self.tab_2)
self.checkBox_2.setObjectName("checkBox_2")
self.gridLayout_6.addWidget(self.checkBox_2, 0, 0, 1, 1)
self.tabWidget.addTab(self.tab_2, "")
self.gridLayout_3.addWidget(self.tabWidget, 0, 0, 1, 1)
self.stackedWidget.addWidget(self.page)
self.page_2 = QtWidgets.QWidget()
self.page_2.setObjectName("page_2")
self.stackedWidget.addWidget(self.page_2)
self.horizontalLayout.addWidget(self.stackedWidget)
self.gridLayout_2.addLayout(self.horizontalLayout, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.actionOpen_File = QtWidgets.QAction(MainWindow)
self.actionOpen_File.setObjectName("actionOpen_File")
self.menuFile.addAction(self.actionOpen_File)
self.menubar.addAction(self.menuFile.menuAction())
self.retranslateUi(MainWindow)
self.tabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.groupBox.setTitle(_translate("MainWindow", "Files"))
self.treeWidget.headerItem().setText(0, _translate("MainWindow", "File Name"))
self.treeWidget.headerItem().setText(1, _translate("MainWindow", "Last Updated"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Plot"))
self.checkBox_2.setText(_translate("MainWindow", "Derivative"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Data"))
self.menuFile.setTitle(_translate("MainWindow", "File"))
self.actionOpen_File.setText(_translate("MainWindow", "Open File"))
self.actionOpen_File.triggered.connect(self.addnewFile)
self.checkBox_2.stateChanged.connect(self.state_changed)
# TreeWidget Specifications
self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu)
self.treeWidget.customContextMenuRequested.connect(self.openMenu)
self.treeWidget.setColumnCount(2)
self.treedata = QTreeWidgetItem(self.treeWidget)
self.fileseqList = []
self.taskseqList = []
def addfileName(self, fileName):
self.treedata.setText(self.fileCounter,fileName)
self.fileseqList.append(fileName) # This is for creating a list which stores sequence of fileName
def addtaskName(self, taskName):
self.childItem = QTreeWidgetItem(self.treedata)
self.childItem.setText(self.fileCounter,taskName)
def delete(self):
print(self.treeWidget.currentIndex())
selectrows = []
selectcols = []
# if child, if parent delete that and change the initial list, update the model rendering
for i in self.treeWidget.selectionModel().selectedIndexes():
selectrows.append(i.row())
selectcols.append(i.column())
# Implement function for deleting selected parent,child
def addnewFile(self):
self.fileName, _ = QFileDialog.getOpenFileName(None, 'Open File', ".", "Files (*.*)", options=QFileDialog.DontUseNativeDialog)
self.FILENAMETREE = ntpath.basename(self.fileName)
self.fileCounter += 1
self.df = pd.read_csv(self.fileName)
self.addfileName(self.FILENAMETREE)
self.plotFunction(self.df.transpose())
def openMenu(self, position):
indexes = self.treeWidget.selectedIndexes()
if len(indexes) > 0:
level = 0
index = indexes[0]
while index.parent().isValid():
index = index.parent()
level += 1
menu = QMenu()
if level == 0:
menu.addAction("Delete File")
elif level == 1:
menu.addAction("Delete Task")
menu.exec_(self.treeWidget.viewport().mapToGlobal(position))
def plotFunction(self,df):
self.plotter.clear()
ax = self.plotter.add_subplot(111)
df.T.plot(ax=ax)
ax.get_legend().remove()
self.showPlot.draw()
def state_changed(self, int): # List of tasks
if self.checkBox_2.isChecked():
X = savgol_filter(self.df, 11, polyorder = 2, deriv=2)
self.plotFunction(pd.DataFrame(X))
self.addtaskName("Derivative")
else:
pass
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
ОБНОВЛЕНИЕ: загружен код и создан новый (тестовый) способ заполнения treeWidget. До сих пор не знаю, следует ли продолжать с treeWidget или treeView для этого приложения. Вы можете открыть любой CSV-файл с первой строкой в виде заголовков (Xaxis), а остальные строки - с осью Y. Создал contextMenu для удаления, но не знаю, как получить выбранные индексы, чтобы получить потомок, также родительский, в настоящее время они просто показывают родителя. Для этой цели нужна некоторая структура данных, чтобы последовательность файлов / задач возвращалась и оставалась неизменной при удалении или добавлении.
Ссылка для загрузки файла, который может быть нанесен на график
Вот структура, о которой я думаю. Пожалуйста, укажите ваши входные данные:
Structure for populating StackWidget and QTreeWidget
class NewFileStructure():
def __init__(self,parent=None):
initialize function
open qfiledialog and import file
check extension and read the file
def loadFileinTreeWidget(self):
load the file in treewidget
increment file counter
add treeroot as fileName
return fileName, treeroot index and filecounter
def loadnewStackWidget1Page(self):
every new file is loaded in a new instance(page) of QStackWidget
all pages in this stackwidget contain same widget and layouts
def plot(self):
plot the file in stackwidget2Page1
class NewTaskStructure():
def __init__(self):
initialize function
user selects some filter/task
def addtasktoTreeWidget(self):
the user has selected the treeroot
we get the treeroot index
the task is added as a child to the treeroot by referencing index
increment taskcounter
return taskname, index, taskcounter and treeroot to which it is added
def loadNewStackWidget2Page(self):
the UI for the new stackwidget is loaded
shown in stackwidget 2
def
def openMenu(self):
This contains options for deleting the selected index (fileName or task)
Updates the filecounter and taskcounter by removing the values
or subtracts 1 from the point where the file/task was deleted
updates treeWidget data accordingly
def selectionchangedTreeWidget(self):
This method determines what index to put the task in
it returns selected filename,index
it returns selected taskname,index
it changes the page of stackwidget 1 (new file) when treeroot filename selected
it changes the page of stackwidget 2 (new task) when treeroot child task selected
whenever a new task is added, this function gets called