Qt – модель takeRow повреждает связанный виджет в поле зренияPython

Программы на Python
Ответить
Anonymous
 Qt – модель takeRow повреждает связанный виджет в поле зрения

Сообщение Anonymous »

В настоящее время я решаю проблему в своем приложении PySide6. У меня есть древовидное представление, которое должно поддерживать перемещение элементов с помощью перетаскивания, но я также использую собственные виджеты для некоторых элементов. Теперь ни одну из этих вещей не сложно реализовать, я упростил элемент древовидного представления, перейдя к следующему коду:

Код: Выделить всё

class MoveItemTreeView(QTreeView):
def moveItem(self, source_row: int, destination_row: int) -> None:
"""Move an item in the tree widget from source to destination."""
model = typing.cast(QStandardItemModel, self.model())
columns = model.takeRow(source_row)
model.insertRow(destination_row, columns)
При этом элемент просто извлекается и помещается после целевой строки.

Это работает правильно и обеспечивает желаемое поведение. Моя проблема в том, что эта операция кажется чтобы удалить любые виджеты, связанные с этим индексом, с помощью setIndexWidget, виджеты просто исчезнут.
Я предоставлю изображение, демонстрирующее поведение:
Изображение

Это минимальный воспроизводимый пример, сгенерировавший это изображение:
< pre class="lang-py Prettyprint-override">

Код: Выделить всё

import sys
import typing
from PySide6.QtGui import QStandardItem, QStandardItemModel
from PySide6.QtWidgets import (
QApplication,
QLabel,
QMainWindow,
QTreeView,
QVBoxLayout,
QWidget,
)

class MoveItemTreeView(QTreeView):
def moveItem(self, source_row: int, destination_row: int) -> None:
"""Move an item in the tree widget from source to destination."""
model = typing.cast(QStandardItemModel, self.model())

columns = model.takeRow(source_row)
model.insertRow(destination_row, columns)

class MainWindow(QMainWindow):
def __init__(self) -> None:
super().__init__()

central_widget = QWidget(self)
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)

tree_view = MoveItemTreeView()
layout.addWidget(tree_view)

model = QStandardItemModel()
tree_view.setModel(model)

# Add some items
for i in range(5):
item = QStandardItem(f"Item {i}")
model.appendRow(item)

for j in range(3):
child = QStandardItem()
item.appendRow(child)
tree_view.setIndexWidget(child.index(), QLabel(f"Child {j}"))

tree_view.moveItem(2, 3)
tree_view.expandAll()
self.setGeometry(100, 100, 600, 600)

class App(QApplication):
def __init__(self) -> None:
super().__init__()

self.window = MainWindow()
self.window.show()

if __name__ == "__main__":
app = App()
sys.exit(app.exec())
Я подумал, что это может быть проблема в том, что виджет связан с определенной строкой, и, поскольку элемент больше не находится в этой строке, связь будет нарушена. Но операция перемещается вокруг других элементов, и у них все еще есть действительные виджеты.
Я попробовал вручную повторно связать виджеты в moveItem, собрать их перед перемещением и использовать setIndexWidget после него, но это приводило только к зависаниям и сбоям.
Поэтому мой вопрос таков: Я делаю что-то неправильно, это неопределенное или недокументированное поведение, или я столкнуться с ошибка?
Я знаю, что могу просто перегенерировать виджеты, мне просто интересно, что именно происходит не так, потому что я ничего не нашел об этом поведении в документации.
Изменить:
Я знаю, что использование setIndexWidget обычно не подходит, и специальный QStyledItemDelegate предпочтительнее, в моем случае я использовать пользовательские виджеты, которые действуют как редакторы - задача, для которой делегат был бы идеален, проблема заключалась в том, что делегат на самом деле не предлагал хороший способ «всегда показывать» редактор, а вместо этого зависел от триггеров редактора представления. Я пытался заставить это работать, но простое использование виджета оказалось гораздо более простым (и, на мой взгляд, более аккуратным) решением, тем более что оно просто работает.

Подробнее здесь: https://stackoverflow.com/questions/793 ... et-in-view
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»