LINUX.ORG.RU

Не работает delegare в QTableView

 , , ,


0

1

Пытаюсь вставлять виджеты в ячейки. По руководству и примерам из интернета. Вот только не работает до конца. Когда я активирую встроенный комбобокс и меняю значение - вызов setData и изменение сохранённых данных происходит, а вот последующего вызова data уже нет. Даже после требуемого документацией явного вызова dataChanged. Соответственно QTableView показывает старое значение.

Привожу сокращённый пример. https://pastebin.com/MNQsFvWd Люди это делают. Этот механизм для этого предназначен. Т.е. как-то можно заставить это работать правильно?

★★★★★

ReadFuckenManual

А если серьёзно, сколько, вам, хомячкам, можно повторять: здесь нет экстрасенсев, телепатов, ведунов и прочих эзотериков, скиньте хотя бы фрагмент кода на простом проекте где вы не понимаете.

nikitalol
()
Последнее исправление: nikitalol (всего исправлений: 1)
Ответ на: комментарий от nikitalol

Потому что lor добавил кавычку к url. Но эта же ссылка без кавычек в посте. Всегда была

https://pastebin.com/MNQsFvWd

Так открывает? Только что проверил в другом браузере. Всё прекрасно видно без логина.

atrus ★★★★★
() автор топика

Вообще я это реализовывал через наследование от комбобокса своего комбобокса и сигналы/слоты ручками.

nikitalol
()
Ответ на: комментарий от nikitalol

Ну, допустим. А грид после редактирования как заставляли обновиться? Я проверял - вызов setData есть и __data меняется.

atrus ★★★★★
() автор топика
Ответ на: комментарий от atrus

Как то много лишних телодвижений как по мне…

Нутк а с чего вы взяли что у вас вообще там должны меняться значения, я нигде не вижу вызова соответствующих функций или цепляния их к сигналам

Рекомендую всё таки наследоваться от объектов которые хотите вставить в дерево или табличку примерно так, тут правда для pyqt но для pyside емнип похоже:

class QTreeComboBox(QtWidgets.QComboBox):
    currentTreeIndexChanged = QtCore.pyqtSignal(int, str)

    def __init__(self, index: int):
        super().__init__()
        self.index = index
        self.unit = self.currentText()
        self.currentIndexChanged.connect(self.emmiter)

    def emmiter(self):
        self.currentTreeIndexChanged.emit(self.index, self.unit)

Тут можно например сразу перекидывать нужную информацию в слот из виджета без секса с сылками на функции, но только если её не очень много, если скорость нужна там другие подходы

nikitalol
()
Последнее исправление: nikitalol (всего исправлений: 1)

Самое первое предположение - dataChanged() вызывается для некорректного диапазона ячеек.

Посмотри к какому слоту dataChanged() приконнекчен и в этом слоте в консоль выводи значения. Так ты поймешь, с какими ячейками ты работаешь.

Xintrea ★★★★★
()
Ответ на: комментарий от Xintrea

Я под отладчиком прошёл. Список __data точно изменяется и корректно. Т.е. при изменении верхней левой ячейки index.row() - 0, index.column() - 0. Но после вызова dataChanged.emit(index, index) ничего не происходит. Нового вызова data с role = Qt.ItemDataRole.DisplayRole просто не происходит...

atrus ★★★★★
() автор топика
Последнее исправление: atrus (всего исправлений: 1)
Ответ на: комментарий от atrus

Но после вызова dataChanged.emit(index, index) ничего не происходит.

Еще раз тебе говорю: проверяй кто этот вызов обрабатывает, и доходит ли этот вызов до нужного кода.

Xintrea ★★★★★
()
Ответ на: комментарий от nikitalol

Нутк а с чего вы взяли что у вас вообще там должны меняться значения

С того, что это происходит. Когда выделение с ячейки снимается qtableview удаляет виджет, вызывая setModelData, в котором текущее значение через model.setData отправляется в модель. И это происходит. Список в модели обновляется, туда записывается новое значение, я это проверил.

Проблема в этом. https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QAbstractItemView.html#PySi... Написано - надо вызвать. Вызываю. Ничего не происходит.

atrus ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Простите, я вас не понял. Я думал вызов должен обрабатывать QAbstractItemModel внутри себя, чтобы перечитать изменённую модель.

atrus ★★★★★
() автор топика
Ответ на: комментарий от nikitalol

В слоте я ставить ничего не могу, он же в C++ коде. В Python ставил.

self.__data[index.row()][index.column()] = value
корректно меняет __data

self.dataChanged.emit(index, index)
отрабатывает и ни фига не происходит больше.

atrus ★★★★★
() автор топика
Ответ на: комментарий от atrus

У тебя сигнал dataChanged.emit(index, index) должен быть законнекчен к виду, например к QTableView. Вид, получив этот сигнал, по сути обратится к модели через метод data(), получит новые данные и обновит на экране.

Вот и проверяй, происходит ли это у тебя.

Xintrea ★★★★★
()
Ответ на: комментарий от Xintrea

У тебя сигнал dataChanged.emit(index, index) должен быть законнекчен к виду, например к QTableView.

Ага. А как? В доке про это не написано. Т.е.

(где w - QTableView) w.setModel(мой потомок QAbstractTableModel) недостаточно, надо ещё что-то руками коннектить?

atrus ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Лол, ты сам сталкивался с этой же проблемой! (Похоже это самое непонятно-говёное в Qt). Не обновляется вид QTableView при изменении данных модели. Emit dataChanged() присутствует.

Сейчас читаю тот тред. Надеюсь найти там что-то полезное. (Увы, там ни хера не оказалось. Ровно те же «умные» ответы в стиле, «чтобы изменить данные надо изменить данные».)

atrus ★★★★★
() автор топика
Последнее исправление: atrus (всего исправлений: 1)
Ответ на: комментарий от atrus

По идее, setModel() для вида достаточно, в этот момент все само законнектится. Если, несмотря на вызов emit dataChanged(index, index), ячейки не обновляются, то надыть убедиться, что модель корректно реализует методы data()/setData().

У тебя data() точно возвращает новые значения? А setData() точно устанавливает новые значения?

Xintrea ★★★★★
()
Ответ на: комментарий от Xintrea

У тебя data() точно возвращает новые значения? А setData() точно устанавливает новые значения?

Увы, но да. Если бы всё было так просто, то до ЛОР вопрос бы даже не дошёл.

Добавил в setModelData после вызова model.setData - «print(model.data(index, Qt.ItemDataRole.DisplayRole))» и он печатает новое значение...

atrus ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

да вроде да:

    def setData(self, index, value, role = Qt.EditRole) -> bool:
        if index.isValid():
            match role:
                case Qt.ItemDataRole.EditRole:
                    self.__data[index.row()][index.column()] = value
                    self.dataChanged.emit(index, index)
                    return True

        return False

atrus ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Всё, нашёл ответ. Для ячеек с установленным delegate data вообще не вызывается, а отрисовка содержимого полностью полагается на вызов paint делегата.

Да, это логично и очевидно, но если об этом не подумать, то можно не слабо так затупить...

atrus ★★★★★
() автор топика
Ответ на: комментарий от atrus

Через одно место сделали если честно всё, реально порактчнее:

  • Отнаследоваться от нужного вижета добавив отправку сигнала с нужной инфой при изменении
  • Прицепить сигнал к методу, который будет просто в ручную делать действие в соответствии с той инфой которую вы передаёте
nikitalol
()
Ответ на: комментарий от nikitalol

По моему мы о разных вещах говорим. Речь о поведении, которое происходит, когда редактор закрывается и внешний виджет удаляется. Куда там что через сигналы передавалось уже не имеет значения.

atrus ★★★★★
() автор топика
Ответ на: комментарий от atrus

Я ради прикола запустил у себя то что сделал автор и не заметил каких то удалений виджетов Но возможно я чёт не понял

nikitalol
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.