有人能看到是什么导致ItemChanged信号触发三次而不是一次吗?
目的是:
- 从外部源加载数据
- 创建一个树小部件,其中包含与数据列相对应的顶级项目
- 勾选用户应该在表中看到的列
- 创建一个仅显示选定列的表
我设法修复了代码,使其忽略方形选择(如果只选择了一些子项(,也忽略了对子项的任何更改。但每次选择或取消选择航向时,信号仍会发出3次。
import pandas as pd
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.Qt import Qt
import sys
df = pd.DataFrame()
column_names = ['something1', 'different1', 'nothing1']
df_2 = pd.DataFrame(columns = column_names)
df= df.append (df_2)
df.loc[len(df)] = [2, 4, 5]
df.loc[len(df)] = [6, 7, 8]
df.loc[len(df)] = [9, 10, 11]
df.loc[len(df)] = [12, 13, 14]
class My_test(QtWidgets.QFrame):
def __init__ (self, df,*args, **kw):
super(My_test, self).__init__(*args, **kw)
# Import the datafrarme
self.df = df
self.horizontalLayout_2 = QtWidgets.QVBoxLayout()
#Define the table
self.table = QtWidgets.QTableWidget()
#Define the tree
self.tree = QtWidgets.QTreeWidget(self)
self.tree.setHeaderLabel("Station Data")
#Complete the Gui
self.horizontalLayout_2.addWidget(self.table)
self.horizontalLayout_2.addWidget(self.tree)
self.setLayout(self.horizontalLayout_2)
# Create the top level tree items (the same as the table headers)
for name in df.columns:
top_level_item_KD = QTreeWidgetItem([name])
top_level_item_KD.setFlags(top_level_item_KD.flags() | Qt.ItemIsUserCheckable | Qt.ItemIsTristate )
# self.tree.itemChanged['QTreeWidgetItem*','int'].connect(self.my_func)
#Connect the itemChanged signal to the its slot
self.tree.itemChanged.connect(self.return_checked_headers)
#Populate each header with the appropriate data
for data_point in df[name]:
child_KD = QTreeWidgetItem([str(data_point)])
child_KD.setFlags(child_KD.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
child_KD.setCheckState(0, Qt.Unchecked)
top_level_item_KD.addChild(child_KD)
self.tree.addTopLevelItem(top_level_item_KD)
def return_checked_headers(self,item ,column_index):
#column_index is not used in the function. It is kept in the definition for a reminder of what is the second option of the "itemChanged" signal
my_selected_columns = []
#Identify how many data columns have been generated
top_level_count = self.tree.topLevelItemCount()
#check if change is on a top level item
if item.parent() == None:
#ignore the change if it is a square (value of 1)
if item.checkState(0)!=1:
for index in range(self.tree.topLevelItemCount()):
tree_item = self.tree.topLevelItem(index)
if tree_item.checkState(0) !=0:
my_header = tree_item.text(0)
my_selected_columns.append(my_header)
self.update_table(self.df,my_selected_columns, self.table)
def update_table(self, df, headers, table):
print ('you are in the updating fucntion')
self.df = df
self.headers = headers
self.table = table
viewing_df = []
viewing_df =self.df[self.headers]
column_count = len(self.headers)
row_count = len(viewing_df)
#Update row and column numbers to reflect input data
self.table.setRowCount(len(viewing_df.index))
self.table.setColumnCount(len(self.headers))
#Create the column headings
self.table.setHorizontalHeaderLabels(self.headers)
#Transfer data
for row_number, row_data in enumerate(viewing_df.values):
for column_number, datum in enumerate(row_data):
#Convert numerical data to 1 decimal place and ensure it is converted to a string
if type(datum)==float or int:
datum= str(round(datum,1))
self.table.setItem(row_number, column_number,QTableWidgetItem(datum))
#Run the GUI
app = QtWidgets.QApplication (sys.argv)
my_window = My_test(df)
my_window.show()
app.exec_()
这是因为您为for name in df.columns
的每个周期连接了信号。由于您有三列,因此信号连接三次,这意味着每次数据更改(通过检查项(时,函数都会被调用三次。
只需将连接置于for循环之外,您将只有一个呼叫。
# ...
self.setLayout(self.horizontalLayout_2)
self.tree.itemChanged.connect(self.return_checked_headers)
for name in df.columns:
# ...