Qdialog 打开时无法继续在 QplainTextEdit 上搜索

问题描述 投票:0回答:1

我正在尝试复制默认记事本查找操作。Notepad Find Functionality

但就我而言,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()
python pyside pyside6 qmainwindow qdialog
1个回答
0
投票

QDialog

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())

© www.soinside.com 2019 - 2024. All rights reserved.