- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当模型以任何方式修改时,我试图施展一些魔法。对添加或删除的项目使用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/
我需要在 PyQt 中将 QAbstractItemModel 与 QTreeView 一起使用。 在 dropMimeData 方法中,我想删除源行(如果它是某个 MIME_TYPE。)如何获取源的
我有一个 map = std::map ,其中 myItemModel继承QAbstractItemModel . 我现在要合并所有 myItemModel合一myItemModel (其他所有元素模
我的 QAbstractItemModel 的实现正在监听一些事件,并在单独的线程中处理更新。 处理更新可能会导致模型中的布局和/或数据更改。 数据本身的存储是boost::mutex - prote
你好来自 SO 的好人! 今天我一直在问自己很多关于我试图实现的事情。 说到这里,我正在尝试使用 Qt 编写某种终端代码,它将用于显示来 self 的应用程序不同部分的消息。 现在我实现了一个模型类(
我为我的模型继承了 QAbstractItemModel 类。为了轻松地将新项目插入模型,我编写了下一个方法: void addItem(MyData *parent, MyData *childre
在创建项目模型时,例如通过子类化 QAbstractItemModel,是否要嵌套行插入和删除等基本操作? 例如,在实践中,必须在调用 ::beginInsertRows() 之后立即调用 ::end
我仍然很难理解 QAbstractItemModel 的项目表示。有两种方法可以返回 QModelIndex 项目,这对我来说没有任何意义。 QModelIndex QAbstractItemMode
我正在研究 QAbstractItemModel 的子类插入 QTreeView .它有一个递归Name = Value类型结构 - 任何索引都可以有自己的子树。这在左侧很好,因为几乎所有的 Tree
一起使用 Qt 的图形 View 和模型 View 框架的最佳方法/模式是什么? 似乎 Qt 应该以某种方式将这两件事联系在一起,但没有。 QGraphicsItem 可以只保留一个 QModelIn
我正在尝试为 TreeView 实现一个简单的模型,但我不知道为什么它不起作用。似乎我所有的节点都是我的 的子节点。根节点,尽管其中三个应该是它的子节点 第一 child 。我也可以看到我的 hasC
QAbstractItemModel 有一个 setHeaderData( int section, ..... ) 方法,该方法根据标题方向采用行或列的部分。我有一个模型,其中包含几个表,这些表都是
我正在实现一个基于 Qt 的树 View ,其中 View 是基于 QTreeView 的类,模型是基于 QAbstractItemModel 的类。这棵树应该有数百万个节点。我正在实现一种过滤机制,
我是 (Py)Qt 新手,现在将 C# GUI 代码移植到 Qt 几天了。我一直问自己的一个问题是为什么 QAbstractItemModel提供 parent() 所需的子类方法,以及为什么他们需要
我有一个关于通知模型对其存储引用的其他对象所做的更改的问题。 我知道信号 dataChanged(),但我不确定如何使用它。例如,我的模型存储了对其他对象的引用(我们称之为 myObjPtr)。只有在
我第一次尝试使用 QTreeView 与 QAbstractItemModel 并立即遇到问题。 QAbstractItemModel 接口(interface)将方法声明为 const ,假设他们不
我使用继承 (QSqlQueryModel) 制作了myModel,并且我 将列插入其中。我想插入 QString 类型的数据,但我不知道该怎么做。 QSQlQueryModel 是只读模型。要使其可
我使用 Qt example for QAbstractItemModel我尝试更新 Item到给定的 index . 我尝试使用 emit DataChanged但它不起作用, View 未更新 .
我一直在努力思考如何为 QAbstractItemModel 开发标准样式的迭代器,但我陷入了困境。我可以使用深度优先或广度优先算法搜索模型,但在将这些模式应用于迭代器时,我不确定如何进行。有人可以直
我正在基于 QAbstractItemModel 实现我的模型,并将其与 QTreeView 一起使用来显示分层数据。数据存储在sqlite表中。 我的问题是添加子节点时应该如何调用beginInse
我正在尝试基于 QAbstractItemModel 创建自己的模型。看起来效果很好。它通过了模型测试断言。 当我删除一行时,我遇到了这个奇怪的问题。删除操作正常。但随后其他行变得不可选择(并非全部)
我是一名优秀的程序员,十分优秀!