更改 QTreeWidgetItem 标志时防止递归
Prevent recursion when changing QTreeWidgetItem flags
我正在尝试制作一个非常基本的密码管理器,但在尝试编辑项目时遇到了问题。当按下“编辑密码”按钮时,它使当前选定的项目可编辑,我希望在用户完成修改后将其删除。尝试删除标志 ItemIsEditable
会导致它在行 item.setFlags(item.flags() & ~Qt.ItemIsEditable)
.
上进入无限递归
# app class -------------------------------------------------------------------------- #
class App(QApplication):
# initialisation ----------------------------------------------------------------- #
def __init__(self, argv):
super().__init__(argv)
self.__ready = False
self.__setup__()
self.__load_data__()
self.__ready = True
# private methods ---------------------------------------------------------------- #
def __load_data__(self):
self.data_tree.headerItem().setText(0, "Client")
self.data_tree.headerItem().setText(1, "Workstation")
self.data_tree.headerItem().setText(2, "Login")
self.data_tree.headerItem().setText(3, "Password")
for level_1, client in enumerate(self.data["clients"]):
row_1 = QTreeWidgetItem(self.data_tree)
self.data_tree.topLevelItem(level_1).setText(0, client["name"])
for level_2, workstation in enumerate(client["workstations"]):
row_2 = QTreeWidgetItem(row_1)
self.data_tree.topLevelItem(level_1).child(level_2).setText(
1, workstation["name"]
)
for level_3, login in enumerate(workstation["logins"]):
row_3 = QTreeWidgetItem(row_2)
row_3.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
self.data_tree.topLevelItem(level_1).child(level_2).child(
level_3
).setText(2, login["username"])
self.data_tree.topLevelItem(level_1).child(level_2).child(
level_3
).setText(3, login["password"])
self.data_tree.setSortingEnabled(True)
def __setup__(self):
self.data = pd.read_json("list.json")
self.main_window = QMainWindow()
self.central_widget = QWidget(self.main_window)
self.data_tree = QTreeWidget(self.central_widget)
self.edit_password_button = QPushButton(self.central_widget)
self.central_widget.setGeometry(QRect(0, 0, 500, 500))
self.central_widget.setObjectName("central_widget")
self.data_tree.itemChanged.connect(self.save_password)
self.data_tree.setGeometry(QRect(0, 0, 500, 450))
self.data_tree.setObjectName("data_tree")
self.data_tree.sortByColumn(0, Qt.SortOrder.AscendingOrder)
self.main_window.setCentralWidget(self.central_widget)
self.main_window.setGeometry(QRect(200, 200, 500, 500))
self.main_window.setWindowTitle("Password Manager")
self.main_window.show()
self.edit_password_button.clicked.connect(self.edit_password)
self.edit_password_button.setGeometry(QRect(345, 455, 150, 40))
self.edit_password_button.setText("Edit Password")
# events ------------------------------------------------------------------------- #
@pyqtSlot()
def edit_password(self):
try:
item = self.data_tree.currentItem()
item.setFlags(item.flags() | Qt.ItemIsEditable)
self.data_tree.scrollToItem(item)
self.data_tree.editItem(item, 3)
except Exception as e:
print(e)
@pyqtSlot(QTreeWidgetItem, int)
def save_password(self, item, column):
if not self.__ready:
return
for client in self.data["clients"]:
if client["name"] == item.parent().parent().text(0):
for workstation in client["workstations"]:
if workstation["name"] == item.parent().text(1):
for login in workstation["logins"]:
if login["username"] == item.text(2):
login["password"] = item.text(3)
with open("list.json", "w") as file:
json.dump(json.loads(self.data.to_json()), file, indent=4)
item.setFlags(item.flags() & ~Qt.ItemIsEditable)
def simulate_password(self):
keyboard.write(self.data_tree.currentItem().text(3))
def test_func(self):
print("test")
app = App(sys.argv)
keyboard.add_hotkey("ctrl+insert", app.simulate_password)
sys.exit(app.exec())
itemChanged signal 是针对对项目的 所有 更改发出的,而不仅仅是对其文本的更改。为避免递归,您可以在设置标志时暂时阻止信号,这样 save_password
槽就不会再次被触发:
@pyqtSlot()
def edit_password(self):
item = self.data_tree.currentItem()
blocked = item.treeWidget().blockSignals(True)
item.setFlags(item.flags() | Qt.ItemIsEditable)
item.treeWidget().blockSignals(blocked)
self.data_tree.scrollToItem(item)
self.data_tree.editItem(item, 3)
@pyqtSlot(QTreeWidgetItem, int)
def save_password(self, item, column):
...
blocked = item.treeWidget().blockSignals(True)
item.setFlags(item.flags() & ~Qt.ItemIsEditable)
item.treeWidget().blockSignals(blocked)
我正在尝试制作一个非常基本的密码管理器,但在尝试编辑项目时遇到了问题。当按下“编辑密码”按钮时,它使当前选定的项目可编辑,我希望在用户完成修改后将其删除。尝试删除标志 ItemIsEditable
会导致它在行 item.setFlags(item.flags() & ~Qt.ItemIsEditable)
.
# app class -------------------------------------------------------------------------- #
class App(QApplication):
# initialisation ----------------------------------------------------------------- #
def __init__(self, argv):
super().__init__(argv)
self.__ready = False
self.__setup__()
self.__load_data__()
self.__ready = True
# private methods ---------------------------------------------------------------- #
def __load_data__(self):
self.data_tree.headerItem().setText(0, "Client")
self.data_tree.headerItem().setText(1, "Workstation")
self.data_tree.headerItem().setText(2, "Login")
self.data_tree.headerItem().setText(3, "Password")
for level_1, client in enumerate(self.data["clients"]):
row_1 = QTreeWidgetItem(self.data_tree)
self.data_tree.topLevelItem(level_1).setText(0, client["name"])
for level_2, workstation in enumerate(client["workstations"]):
row_2 = QTreeWidgetItem(row_1)
self.data_tree.topLevelItem(level_1).child(level_2).setText(
1, workstation["name"]
)
for level_3, login in enumerate(workstation["logins"]):
row_3 = QTreeWidgetItem(row_2)
row_3.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
self.data_tree.topLevelItem(level_1).child(level_2).child(
level_3
).setText(2, login["username"])
self.data_tree.topLevelItem(level_1).child(level_2).child(
level_3
).setText(3, login["password"])
self.data_tree.setSortingEnabled(True)
def __setup__(self):
self.data = pd.read_json("list.json")
self.main_window = QMainWindow()
self.central_widget = QWidget(self.main_window)
self.data_tree = QTreeWidget(self.central_widget)
self.edit_password_button = QPushButton(self.central_widget)
self.central_widget.setGeometry(QRect(0, 0, 500, 500))
self.central_widget.setObjectName("central_widget")
self.data_tree.itemChanged.connect(self.save_password)
self.data_tree.setGeometry(QRect(0, 0, 500, 450))
self.data_tree.setObjectName("data_tree")
self.data_tree.sortByColumn(0, Qt.SortOrder.AscendingOrder)
self.main_window.setCentralWidget(self.central_widget)
self.main_window.setGeometry(QRect(200, 200, 500, 500))
self.main_window.setWindowTitle("Password Manager")
self.main_window.show()
self.edit_password_button.clicked.connect(self.edit_password)
self.edit_password_button.setGeometry(QRect(345, 455, 150, 40))
self.edit_password_button.setText("Edit Password")
# events ------------------------------------------------------------------------- #
@pyqtSlot()
def edit_password(self):
try:
item = self.data_tree.currentItem()
item.setFlags(item.flags() | Qt.ItemIsEditable)
self.data_tree.scrollToItem(item)
self.data_tree.editItem(item, 3)
except Exception as e:
print(e)
@pyqtSlot(QTreeWidgetItem, int)
def save_password(self, item, column):
if not self.__ready:
return
for client in self.data["clients"]:
if client["name"] == item.parent().parent().text(0):
for workstation in client["workstations"]:
if workstation["name"] == item.parent().text(1):
for login in workstation["logins"]:
if login["username"] == item.text(2):
login["password"] = item.text(3)
with open("list.json", "w") as file:
json.dump(json.loads(self.data.to_json()), file, indent=4)
item.setFlags(item.flags() & ~Qt.ItemIsEditable)
def simulate_password(self):
keyboard.write(self.data_tree.currentItem().text(3))
def test_func(self):
print("test")
app = App(sys.argv)
keyboard.add_hotkey("ctrl+insert", app.simulate_password)
sys.exit(app.exec())
itemChanged signal 是针对对项目的 所有 更改发出的,而不仅仅是对其文本的更改。为避免递归,您可以在设置标志时暂时阻止信号,这样 save_password
槽就不会再次被触发:
@pyqtSlot()
def edit_password(self):
item = self.data_tree.currentItem()
blocked = item.treeWidget().blockSignals(True)
item.setFlags(item.flags() | Qt.ItemIsEditable)
item.treeWidget().blockSignals(blocked)
self.data_tree.scrollToItem(item)
self.data_tree.editItem(item, 3)
@pyqtSlot(QTreeWidgetItem, int)
def save_password(self, item, column):
...
blocked = item.treeWidget().blockSignals(True)
item.setFlags(item.flags() & ~Qt.ItemIsEditable)
item.treeWidget().blockSignals(blocked)