但就我而言,QDialog 在第一次操作后关闭。有人可以帮助我在主窗口执行搜索操作或任何替代操作时保持 QDialog 打开吗?
这是我的代码:
class MainWindow(QMainWindow, Ui_Widget):
def init(self, app):
super().init()
self.app = app
self.setupUi(self)
self.setWindowTitle( "Untitled - Notepad")
self.actionFind.triggered.connect(self.find)
def find(self):
cursor = self.plainTextEdit.textCursor()
selected_text = cursor.selectedText()
if (selected_text != ""):
self.text = selected_text
else:
clipboard = QClipboard()
self.text = clipboard.text(QClipboard.Mode.Clipboard)
self.find_dialog = FindDialog(self.text)
ret = self.find_dialog.exec()
if(ret==QDialog.Accepted):
self.text = self.find_dialog.f_search_lineEdit.text()
self.plainTextEdit.find(self.text)
class FindDialog(QDialog, Ui_FindDialog):
def init(self, text):
super().init()
self.setupUi(self)
self.setWindowTitle("Find")
self.search_text = text
#Connections
self.f_find_next_pushButton.clicked.connect(self.ok)
self.f_cancel_find_pushButton.clicked.connect(self.cancel)
self.f_search_lineEdit.setText(self.search_text)
def cancel(self):
self.reject()
def ok(self):
self.search_text = self.f_search_lineEdit.text()
self.accept()
exec()
函数会阻止代码执行,直到它返回,并且只有在对话框关闭时才会发生。
您需要保持对话框可见才能执行多个搜索,因此您显然不能使用
accept()
函数,因为顾名思义,该调用将通过关闭对话框并将其结果返回到调用者:exec()
返回,调用它的函数中的代码执行将继续。对于这种情况,解决方案是使用信号:您为对话框创建一个自定义信号,该信号将随搜索查询一起发出,并将该信号连接到最终执行文本搜索的函数。
请注意,对于这种情况,每次连续创建一个新对话框没有多大意义,最好只创建一次,并最终在需要时再次显示它。另请记住,为了使对话框始终显示在其父窗口之上,
parent
参数是必需的,否则如果用户单击主窗口,它们可能会被隐藏。
虽然我们可以使用 open()
通过执行上述操作,当触发查找操作时,我们只需要调用 show()
然后调用
activateWindow()
:如果不可见,则需要第一个,而第二个确保对话框将获得输入焦点万一它已经是了。
最后,class TextEditor(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Untitled[*] - Notepad')
editMenu = self.menuBar().addMenu('Edit')
self.findAction = editMenu.addAction('Find')
self.findAction.setShortcut(
QKeySequence(QKeySequence.StandardKey.Find))
self.editor = QPlainTextEdit()
self.setCentralWidget(self.editor)
self.findDialog = FindDialog(self)
self.findAction.triggered.connect(self.showFindDialog)
self.editor.document().modificationChanged.connect(
self.setWindowModified)
self.findDialog.findRequested.connect(self.findText)
def findText(self, text, back=False):
findFlag = QTextDocument.FindFlag.FindBackward if back else 0
self.editor.find(text, QTextDocument.FindFlag(findFlag))
def showFindDialog(self):
selection = self.editor.textCursor().selectedText()
if selection:
self.findDialog.setText(selection)
elif not self.findDialog.isVisible():
clipboard = QApplication.clipboard().text()
if clipboard:
self.findDialog.setText(clipboard)
self.findDialog.show()
self.findDialog.activateWindow()
def sizeHint(self):
return QApplication.primaryScreen().size() / 2
class FindDialog(QDialog):
findRequested = pyqtSignal(str, bool)
def __init__(self, parent):
super().__init__(parent)
self.setWindowTitle('Find text')
self.lineEdit = QLineEdit()
self.nextRadio = QRadioButton('&Forward', checked=True)
self.prevRadio = QRadioButton('&Backward')
buttonBox = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
buttonBox.addButton('&Search', QDialogButtonBox.ButtonRole.AcceptRole)
layout = QVBoxLayout(self)
layout.addWidget(self.lineEdit)
optLayout = QHBoxLayout()
layout.addLayout(optLayout)
optLayout.addWidget(self.nextRadio)
optLayout.addWidget(self.prevRadio)
optLayout.addStretch()
layout.addWidget(buttonBox)
# disable focus for all buttons
for btn in self.findChildren(QAbstractButton):
btn.setFocusPolicy(Qt.FocusPolicy(0))
hint = self.sizeHint()
hint.setWidth(hint.width() * 2)
self.setFixedSize(hint)
buttonBox.rejected.connect(self.reject)
buttonBox.accepted.connect(self.emitFind)
def setText(self, text):
self.lineEdit.setText(text)
def emitFind(self):
self.findRequested.emit(
self.lineEdit.text(), self.prevRadio.isChecked())
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
editor = TextEditor()
editor.show()
sys.exit(app.exec())