1 回答

TA貢獻(xiàn)1801條經(jīng)驗(yàn) 獲得超16個(gè)贊
每個(gè)代表不能只有一個(gè)唯一的編輯器,原因有兩個(gè):
可能有更多的編輯器的活動(dòng)實(shí)例(使用 打開
openPersistentEditor
),例如一個(gè)表,其中一列的每一行都有一個(gè)組合框。每次編輯器將其數(shù)據(jù)提交給模型時(shí),如果它不是持久編輯器,它就會(huì)被銷毀??紤]當(dāng)一個(gè) Qt 對(duì)象被分配給一個(gè) Python 變量/屬性時(shí),它實(shí)際上是一個(gè)指向由 Qt 創(chuàng)建的底層 C++ 對(duì)象的指針。這意味著雖然
self.editor
仍然作為 python 對(duì)象存在,但它指向一個(gè)在編輯器被委托關(guān)閉時(shí)實(shí)際刪除的對(duì)象。
正如函數(shù)名所說,createEditor()
創(chuàng)建一個(gè)編輯器,所以解決方法是每次createEditor()
調(diào)用都創(chuàng)建一個(gè)新實(shí)例。
更新
但是,這里有一個(gè)重要問題:一旦您打開對(duì)話框,委托編輯器就會(huì)失去焦點(diǎn)。對(duì)于一個(gè)項(xiàng)目視圖,這與單擊另一個(gè)項(xiàng)目(更改焦點(diǎn))相同,這將導(dǎo)致數(shù)據(jù)提交和編輯器破壞。
“簡(jiǎn)單”的解決方案是在要打開對(duì)話框時(shí)阻止委托信號(hào)(最重要的closeEditor()
是會(huì)調(diào)用),然后再解除阻止。destroyEditor()
class BrowseEdit(QtWidgets.QLineEdit):
@QtCore.pyqtSlot()
def on_btnaction(self):
self.delegate.blockSignals(True)
selected_path = QtWidgets.QFileDialog.getOpenFileName(self.window(), self.opendialogtitle, self.opendialogdir, self.filefilters)
self.delegate.blockSignals(False)
if not selected_path[0]: return
selected_path = selected_path[0].replace('/', os.sep)
# THIS CAUSES ERROR ('self' GETS DELETED BEFORE THIS LINE!)
self.setText(selected_path)
class BrowseEditDelegate(QtWidgets.QStyledItemDelegate):
# ...
def createEditor(self, parent: QtWidgets.QWidget, option: QtWidgets.QStyleOptionViewItem,
index: QtCore.QModelIndex) -> QtWidgets.QWidget:
try:
if self.model_indices and index in self.model_indices:
editor = BrowseEdit(parent=parent)
editor.delegate = self
return editor
else:
return super().createEditor(parent, option, index)
except Exception as err:
print(err)
return None
也就是說,這是一個(gè)hack。雖然它有效,但不能保證它會(huì)在未來版本的 Qt 中,當(dāng)可能引入其他信號(hào)或它們的行為發(fā)生變化時(shí)。
更好更優(yōu)雅的解決方案是創(chuàng)建一個(gè)在單擊瀏覽按鈕時(shí)調(diào)用的信號(hào),然后項(xiàng)目視圖(或其任何父項(xiàng))將負(fù)責(zé)瀏覽,如果文件對(duì)話框結(jié)果有效則設(shè)置數(shù)據(jù)并再次開始編輯該字段:
class BrowseEditDelegate(QtWidgets.QStyledItemDelegate):
browseRequested = QtCore.pyqtSignal(QtCore.QModelIndex)
# ...
def createEditor(self, parent: QtWidgets.QWidget, option: QtWidgets.QStyleOptionViewItem,
index: QtCore.QModelIndex) -> QtWidgets.QWidget:
try:
if self.model_indices and index in self.model_indices:
editor = BrowseEdit(parent=parent)
editor.btnaction.triggered.connect(
lambda: self.browseRequested.emit(index))
return editor
else:
return super().createEditor(parent, option, index)
except Exception as err:
print(err)
return None
class Window(QtWidgets.QWidget):
def __init__(self):
# ...
delegate = BrowseEditDelegate(indices)
self.tv_plugins_3party.setItemDelegate(delegate)
delegate.browseRequested.connect(self.browseRequested)
def browseRequested(self, index):
selected_path = QtWidgets.QFileDialog.getOpenFileName(self.window(), 'Select file', index.data())
if selected_path[0]:
self.model_plugins_3party.setData(index, selected_path[0])
self.tv_plugins_3party.edit(index)
添加回答
舉報(bào)