gpt4 book ai didi

python - PySide:QAbstractItemModel - 连接 dataChanged()

转载 作者:行者123 更新时间:2023-12-01 08:34:37 25 4
gpt4 key购买 nike

当模型以任何方式修改时,我试图施展一些魔法。对添加或删除的项目使用react非常容易,但我很难找到一种对被修改(重命名)的项目使用react的方法

model.dataChanged.connect(do_some_magic)

遗憾的是,它的效果并不好:

model.layoutChanged.connect(do_some_magic)

编辑:我的代码有一个简化版本,仅关注 QTreeView

main.py:

import sys
from PySide import QtGui
from editable_tree import EditableTreeView


def main():
pm_app = QtGui.QApplication(sys.argv)
pm_app.setStyle('plastique')
pm_form = EditableTreeView()

pm_form.show()
pm_app.exec_()


if __name__ == '__main__':
main()

可编辑树.py:

from PySide import QtGui
from PySide import QtCore
import os
import editable_tree_ui

class TreeItem(object):
def __init__(self, _name, _parent=None):
"""
:param _name: str
:param _parent: TreeItem
"""
self._name = _name
self._children = []
self._parent = _parent

# if _parent is not None:
# _parent.add_child(self)

def name(self):
"""
:return: str
"""
return self._name

def set_name(self, name):
"""
:param name: str
:return: str
"""
self._name = name

def child(self, row):
"""
:param row: int
:return: TreeItem
"""
return self._children[row]

def child_count(self):
"""
:return: list
"""
return len(self._children)

def parent(self):
"""
:return: TreeItem
"""
return self._parent

def row(self):
"""
:return: QModelIndex
"""
if self._parent is not None:
return self._parent._children.index(self)

def add_child(self, child):
"""
:param child: TreeItem
"""
self._children.append(child)

def insert_child(self, position, child):
"""
:param position: int
:param child: TreeItem
:return: bool
"""
if position < 0 or position > len(self._children):
return False

self._children.insert(position, child)
child._parent = self
return True

def remove_child(self, position):
"""
:param position: int
:return: bool
"""
if position < 0 or position > len(self._children):
return False

child = self._children.pop(position)
child._parent = None

return True

def log(self, tab_level=-1):
"""
:param tab_level: int
:return: str
"""
output = ""
tab_level += 1

for i in range(tab_level):
output += "\t"

output += "|------" + self._name + "\n"

for child in self._children:
output += child.log(tab_level)

tab_level -= 1
output += "\n"

return output

def __repr__(self):
return self.log()


class TreeModel(QtCore.QAbstractItemModel):
def __init__(self, _data, _parent=None):
"""
:param _data: dict
:param _parent: TreeItem
"""
super(TreeModel, self).__init__(_parent)

self._data = _data
self.root_item = TreeItem('ROOT')

self.setup_model_data(self._data)

def rowCount(self, parent):
"""
:param parent: QModelIndex
:return: int
"""
if not parent.isValid():
parent_item = self.root_item
else:
parent_item = parent.internalPointer()

return parent_item.child_count()

def columnCount(self, parent):
"""
:param parent: QModelIndex
:return: int
"""
return 1

def data(self, index, role):
"""
:param index: QModelIndex
:param role: int
:return: QString
"""
if not index.isValid():
return None

item = index.internalPointer()

if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
if index.column() == 0:
return item.name()

def setData(self, index, value, role=QtCore.Qt.EditRole):
"""
:param index: QModelIndex
:param value: QVariant
:param role: int (flag)
:return: bool
"""
if index.isValid():
if role == QtCore.Qt.EditRole:
item = index.internalPointer()
item.set_name(value)

return True
return False

def headerData(self, section, orientation, role):
"""
:param section: int
:param orientation: Qt.Orientation
:param role: int
:return: QString
"""
if role == QtCore.Qt.DisplayRole:
if section == 0:
return self.root_item.name()
else:
return "Typeinfo"

def flags(self, index):
"""
:param index: QModelIndex
:return: int (flag)
"""
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable

def parent(self, index):
"""
Should return the parent of the item with the given QModelIndex

:param index: QModelIndex
:return: QModelIndex
"""
item = self.get_item(index)
parent_item = item.parent()

if parent_item == self.root_item:
return QtCore.QModelIndex()

return self.createIndex(parent_item.row(), 0, parent_item)

def index(self, row, column, parent):
"""
Should return a QModelIndex that corresponds to the given row, column and parent item

:param row: int
:param column: int
:param parent: QModelIndex
:return: QModelIndex
"""
parent_item = self.get_item(parent)

child_item = parent_item.child(row)

if child_item:
return self.createIndex(row, column, child_item)
else:
return QtCore.QModelIndex()

def get_item(self, index):
"""
:param index: QModelIndex
:return: TreeItem
"""
if index.isValid():
item = index.internalPointer()
if item:
return item

return self.root_item

def insertRows(self, position, rows, parent=QtCore.QModelIndex()):
"""
:param position: int
:param rows: int
:param parent: QModelIndex
:return: bool
"""
parent_item = self.get_item(parent)
success = False

self.beginInsertRows(parent, position, position + rows - 1)

for row in range(rows):
child_count = parent_item.child_count()
child_item = TreeItem("untitled" + str(child_count))
success = parent_item.insert_child(position, child_item)

self.endInsertRows()

return success

def removeRows(self, position, rows, parent=QtCore.QModelIndex()):
"""
:param position: int
:param rows: int
:param parent: QModelIndex
:return: bool
"""
parent_item = self.get_item(parent)
success = False

self.beginRemoveRows(parent, position, position + rows - 1)

for row in range(rows):
success = parent_item.remove_child(position)

self.endRemoveRows()

return success

def setup_model_data(self, _data, _parent=None):
"""
Setup TreeView structure extracted from _data

:param _data: dict
:param _parent: TreeItem
"""
if _parent is None:
_parent = self.root_item

for key, value in sorted(_data.iteritems()):
if isinstance(value, dict):
_item = TreeItem(key, _parent)
_parent.add_child(_item)
self.setup_model_data(value, _item)


class EditableTreeView(QtGui.QMainWindow, editable_tree_ui.Ui_MainWindow):
def __init__(self, parent=None):
"""
:param parent: TreeItem
"""
super(EditableTreeView, self).__init__(parent)

self.setupUi(self)

self.template_path = r'C:\Users\gwuest\Downloads\PROJECT_TEMPLATE'
self.target_path = ''

self.template = self.get_directory_structure(self.template_path)

model = TreeModel(self.template)

self.treeView.setModel(model)

model.dataChanged.connect(self.test)

def get_directory_structure(self, _path):
"""
Creates a nested dictionary that represents the folder structure of _path

:param _path: str
:return: dict
"""
structure = {}
_path = _path.rstrip(os.sep)
start = _path.rfind(os.sep) + 1

for path, dirs, files in os.walk(_path):
folders = path[start:].split(os.sep)
subdir = dict.fromkeys(files)
parent = reduce(dict.get, folders[:-1], structure)
parent[folders[-1]] = subdir

return structure


def test(self):
print('test')

editabletree_ui.py:

from PySide import QtCore, QtGui

class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setObjectName("horizontalLayout")
self.treeView = QtGui.QTreeView(self.centralwidget)
self.treeView.setObjectName("treeView")
self.horizontalLayout.addWidget(self.treeView)
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.btn_open_template = QtGui.QPushButton(self.centralwidget)
self.btn_open_template.setObjectName("btn_open_template")
self.verticalLayout.addWidget(self.btn_open_template)
self.btn_open_target = QtGui.QPushButton(self.centralwidget)
self.btn_open_target.setObjectName("btn_open_target")
self.verticalLayout.addWidget(self.btn_open_target)
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.horizontalLayout.addLayout(self.verticalLayout)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)

self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)

def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
self.btn_open_template.setText(QtGui.QApplication.translate("MainWindow", "Template", None, QtGui.QApplication.UnicodeUTF8))
self.btn_open_target.setText(QtGui.QApplication.translate("MainWindow", "Server", None, QtGui.QApplication.UnicodeUTF8))

在 EditableTree 类中,我将 model.dataChanged 连接到测试方法...如果我编辑一个项目,则什么也不会发生:(据我了解,我不需要重新实现 dataChanged() 来使其工作

最佳答案

每次修改某些数据时,都必须发出 dataChanged 信号,在您的情况下是在 setData() 方法中:

def setData(self, index, value, role=QtCore.Qt.EditRole):
"""
:param index: QModelIndex
:param value: QVariant
:param role: int (flag)
:return: bool
"""
if index.isValid():
if role == QtCore.Qt.EditRole:
item = index.internalPointer()
item.set_name(value)
self.dataChanged.emit(index, index) # <---
return True
return False

关于python - PySide:QAbstractItemModel - 连接 dataChanged(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53781144/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com