如何重新实现 QDialog 的接受和拒绝槽?
How to reimplement a QDialog's accept and reject slots?
我正在开发一个 GUI 项目,其中用户面临以下 QDialog:
class StockSelectorDialog(QDialog, stockselector_ui):
def __init__(self, parent_, *args, **kwargs):
super(StockSelectorDialog, self).__init__(*args, **kwargs)
self.setAttribute(Qt.WA_DeleteOnClose, on=True)
self.setupUi(self)
self.dialogButtonBox.accepted.connect(self.accept)
self.dialogButtonBox.rejected.connect(self.reject)
self.parent_ = parent_
self.symbolsbuffer = parent_.symbols.copy()
self.symbolmodel = SymbolListModel(self)
self.listView.setModel(self.symbolmodel)
self.symbolAddButton.clicked.connect(self.onAddButtonClicked)
self.symbolDeleteButton.clicked.connect(self.onDeleteButtonClicked)
def onAddButtonClicked(self, s):
symbol = self.symbolEdit.text()
if symbol:
self.symbolsbuffer.append(symbol)
self.symbolmodel.layoutChanged.emit()
self.symbolEdit.setText("")
def onDeleteButtonClicked(self, s):
indexes = self.listView.selectedIndexes()
if indexes:
for i in indexes:
del self.symbolsbuffer[i.row()]
self.symbolmodel.layoutChanged.emit()
self.listView.clearSelection()
def accept(self):
self.parent_.symbols = self.symbolsbuffer
self.parent_.onSymbolsChanged()
self.close()
def reject(self):
self.close()
UI 文件在这里:https://github.com/danib-prog/stockmarket-helper/blob/master/stockselector.ui
一切正常,直到我添加了缓冲区系统,为此我不得不重新实现对话框的 accept
和 reject
插槽(尽管我对后者不太确定) .现在,对话框会在必要时打开,ListView
可以正常使用所有按钮和 LineEdit
,但我的 dialogButtonBox
没有响应。
为什么会这样?问题的解决方案是什么?
您不应该为此在对话框中调用 close()
,主要是因为它会导致调用 reject()
;幸运的是 Qt 足够聪明,可以防止递归,但重点仍然存在:这两种方法都应该设置对话框的 result 并使用 done()
,of close()
,所以他们的事件循环正确地退出了 exec_()
.
如果您需要重写 class 函数来执行默认行为 以外的操作 ,您应该始终记住也要调用基础实现以便正确达到预期效果。
def accept(self):
self.parent_.symbols = self.symbolsbuffer
self.parent_.onSymbolsChanged()
super(StockSelectorDialog, self).accept()
def reject(self):
super(StockSelectorDialog, self).reject()
此外,请注意 Qt Designer 在使用带按钮的默认对话框模板创建时已经连接了 QDialogButtonBox 的按钮,因此您不应该再次连接它们,否则 accept
和 reject
会被调用两次。
我正在开发一个 GUI 项目,其中用户面临以下 QDialog:
class StockSelectorDialog(QDialog, stockselector_ui):
def __init__(self, parent_, *args, **kwargs):
super(StockSelectorDialog, self).__init__(*args, **kwargs)
self.setAttribute(Qt.WA_DeleteOnClose, on=True)
self.setupUi(self)
self.dialogButtonBox.accepted.connect(self.accept)
self.dialogButtonBox.rejected.connect(self.reject)
self.parent_ = parent_
self.symbolsbuffer = parent_.symbols.copy()
self.symbolmodel = SymbolListModel(self)
self.listView.setModel(self.symbolmodel)
self.symbolAddButton.clicked.connect(self.onAddButtonClicked)
self.symbolDeleteButton.clicked.connect(self.onDeleteButtonClicked)
def onAddButtonClicked(self, s):
symbol = self.symbolEdit.text()
if symbol:
self.symbolsbuffer.append(symbol)
self.symbolmodel.layoutChanged.emit()
self.symbolEdit.setText("")
def onDeleteButtonClicked(self, s):
indexes = self.listView.selectedIndexes()
if indexes:
for i in indexes:
del self.symbolsbuffer[i.row()]
self.symbolmodel.layoutChanged.emit()
self.listView.clearSelection()
def accept(self):
self.parent_.symbols = self.symbolsbuffer
self.parent_.onSymbolsChanged()
self.close()
def reject(self):
self.close()
UI 文件在这里:https://github.com/danib-prog/stockmarket-helper/blob/master/stockselector.ui
一切正常,直到我添加了缓冲区系统,为此我不得不重新实现对话框的 accept
和 reject
插槽(尽管我对后者不太确定) .现在,对话框会在必要时打开,ListView
可以正常使用所有按钮和 LineEdit
,但我的 dialogButtonBox
没有响应。
为什么会这样?问题的解决方案是什么?
您不应该为此在对话框中调用 close()
,主要是因为它会导致调用 reject()
;幸运的是 Qt 足够聪明,可以防止递归,但重点仍然存在:这两种方法都应该设置对话框的 result 并使用 done()
,of close()
,所以他们的事件循环正确地退出了 exec_()
.
如果您需要重写 class 函数来执行默认行为 以外的操作 ,您应该始终记住也要调用基础实现以便正确达到预期效果。
def accept(self):
self.parent_.symbols = self.symbolsbuffer
self.parent_.onSymbolsChanged()
super(StockSelectorDialog, self).accept()
def reject(self):
super(StockSelectorDialog, self).reject()
此外,请注意 Qt Designer 在使用带按钮的默认对话框模板创建时已经连接了 QDialogButtonBox 的按钮,因此您不应该再次连接它们,否则 accept
和 reject
会被调用两次。