python - qtreewidget itemChanged 被调用两次进行重命名
问题描述
我正在制作 QTreeWidget 的子类。
在尝试捕获涉及其默认信号的重命名时 -itemChanged
和itemDoubleClicked
,这些方法确实有效,但我注意到它们itemChanged
被调用了两次而不是一次。
无法真正弄清楚第二个“额外”信号的触发位置或原因。
欣赏是否有人可以提供一些启示。
IsNewItemRole = QtCore.Qt.UserRole + 1000
class CustomTreeDelegate(QtGui.QStyledItemDelegate):
@property
def text_color(self):
if not hasattr(self, "_text_color"):
self._text_color = QtGui.QColor()
return self._text_color
@text_color.setter
def text_color(self, color):
"""Sets QColor towards object.
Args:
color (QtGui.QColor): RGB color values.
"""
self._text_color = color
def initStyleOption(self, option, index):
"""Change the font color only if item is a new added item.
Args:
option ():
index (QModelIndex?)
"""
super(CustomTreeDelegate, self).initStyleOption(option, index)
if self.text_color.isValid() and index.data(IsNewItemRole):
option.palette.setBrush(QtGui.QPalette.Text, self.text_color)
class CustomTreeWidgetItem(QtGui.QTreeWidgetItem):
"""Initialization class for QTreeWidgetItem creation.
Args:
widget (QtGui.QTreeWidget): To append items into.
text (str): Input name for QTreeWidgetItem.
is_tristate (bool): Should it be a tri-state checkbox. False by default.
"""
def __init__(self, parent=None, text=None, is_tristate=False, is_new_item=False):
super(CustomTreeWidgetItem, self).__init__(parent)
self.setText(0, text)
# flags = QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsUserCheckable
if is_tristate:
# flags |= QtCore.Qt.ItemIsTristate
# Solely for the Parent item
self.setFlags(
self.flags()
| QtCore.Qt.ItemIsTristate
| QtCore.Qt.ItemIsEditable
| QtCore.Qt.ItemIsUserCheckable
)
else:
self.setFlags(
self.flags()
| QtCore.Qt.ItemIsEditable
| QtCore.Qt.ItemIsUserCheckable
)
self.setCheckState(0, QtCore.Qt.Unchecked)
self.setData(0, IsNewItemRole, is_new_item)
def setData(self, column, role, value):
"""Override QTreeWidgetItem setData function.
QTreeWidget does not have a signal that defines when an item has been
checked/ unchecked. And so, this method will emits the signal as a
means to handle this.
Args:
column (int): Column value of item.
role (int): Value of Qt.ItemDataRole. It will be Qt.DisplayRole or
Qt.CheckStateRole
value (int or unicode):
"""
state = self.checkState(column)
QtGui.QTreeWidgetItem.setData(self, column, role, value)
if (role == QtCore.Qt.CheckStateRole and
state != self.checkState(column)):
tree_widget = self.treeWidget()
if isinstance(tree_widget, CustomTreeWidget):
tree_widget.itemToggled.emit(self, column)
class CustomTreeWidget(QtGui.QTreeWidget):
"""Initialization class for QTreeWidget creation.
Args:
widget ():
"""
itemToggled = QtCore.pyqtSignal(QtGui.QTreeWidgetItem, bool)
selectionItemChanged = QtCore.pyqtSignal(bool)
contentUpdates = QtCore.pyqtSignal()
def __init__(self, widget=None):
super(CustomTreeWidget, self).__init__(widget)
self.rename_counter = False
self.currentItemChanged.connect(self.selection_item_changed)
self.itemChanged.connect(self.tree_item_changed)
self.itemDoubleClicked.connect(self.tree_item_double_clicked)
def selection_item_changed(self, current, previous):
"""Overrides widget's default signal.
Emiited when current item selection is changed. This will also toggles
the state of `self.add_child_btn`.
If a child item is selected, the "Add Child" button will be disabled.
Args:
current (CustomTreeWidgetItem): Currently selected item.
previous (CustomTreeWidgetItem or None): Previous selected item.
"""
state = True
if not current:
# print '>>> nothing is selected'
state = False
return
if current.parent():
state = False
self.selectionItemChanged.emit(state)
def tree_item_changed(self, item, column):
"""Overrides widget's default signal.
Emitted when the contents of the selected item in the column changes.
Args:
item (CustomTreeWidgetItem): Selected item.
column (int): Column value of the selected item.
"""
print '>>> selection item is changed!'
if self.rename_counter and self.prev_name != item.text(column):
item.setData(0, IsNewItemRole, True)
self.rename_counter = False
self.contentUpdates.emit()
elif item.data(column, IsNewItemRole):
print 'item is already an newitemrole'
return
def tree_item_double_clicked(self, item, column):
"""Overrides widget's default signal.
Emitted when User performs double clicks inside the widget.
Args:
item (CustomTreeWidgetItem): Selected item.
column (int): Column value of the selected item.
"""
self.prev_name = item.text(column)
self.rename_counter = True
class MainApp(QtGui.QWidget):
def __init__(self, parent=None):
super(MainApp, self).__init__(parent)
test_dict = {
"menuA": ["a101", "a102"],
"menuC": ["c101", "c102", "c103"],
"menuB": ["b101"],
}
self._tree = CustomTreeWidget()
self._tree.header().hide()
self._tree_delegate = CustomTreeDelegate(self._tree)
self._tree.setItemDelegate(self._tree_delegate)
for pk, pv in sorted(test_dict.items()):
parent = CustomTreeWidgetItem(self._tree, pk, is_tristate=True)
for c in pv:
child = CustomTreeWidgetItem(parent, c)
self._tree.expandAll()
main_layout = QtGui.QHBoxLayout()
main_layout.addWidget(self._tree)
self.setLayout(main_layout)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
w = MainApp()
w.show()
sys.exit(app.exec_())
解决方案
推荐阅读
- php - 在主题中加载特定的 WooCommerce 模板
- bash - 将代码拆分为文件
- unity3d - 为什么我的搅拌机 .fbx 文件没有导出到 Unity?
- asp.net-core - 如何在 Asp net core 3.1 中通过身份服务器 4 中的用户 ID 获取 access_token、刷新令牌
- java - 导入比主 gradle 项目文件高一级的额外项目
- c# - 是否可以在 C# 中为 KeyValuePairs 的 LinkedList 创建序列化代理?
- r - R循环使用data.table标准化变量
- postgresql - 如何更改露天开始目录?
- c++ - 我如何在 wxWidgets 中绘图?
- node.js - 在 Nock 中,URL 对我来说似乎没问题,但不匹配