简体   繁体   中英

QInputDialog with Multiline text

I need to create a text input dialog with multiple lines. Is there any way to do this using QInputDialog?

If not, is the simplest recommendation to subclass QPlainTextEdit?

QInputDialog and more precisely getText work only with a QLineEdit.

Just implement a small dialog sublass which contains a QPlainTextEdit. Shouldn't be too much work. Not as fast as QInputDialog, but not too much effort either.

Update : since version Qt 5.2, QInputDialog has getMultiLineText .

I needed this to work in Qt4 and this was one of the very few questions I found asking about it, none had any implementations as answers. I've just managed to replicate the functionality and look of Qt5 however, so even though it's in Python, I may as well post here as it could come in useful to others.

To get it working, it needed its own layout, and since QInputDialog builds the layout, QDialog had to be subclassed. I then added getMultiLineText to QInputDialog , which returns a reading from the QPlainTextEdit and the result of the new dialog.

class _QInputDialogMultiline(QDialog):
    """Build a replica interface of QInputDialog.getMultilineText."""
    def __init__(self, parent, title, label, text='', **kwargs):
        super(_QInputDialogMultiline, self).__init__(parent, **kwargs)
        if title is not None:
            self.setWindowTitle(title)

        self.setLayout(QVBoxLayout())
        self.layout().addWidget(QLabel(label))
        self.textEdit = QPlainTextEdit()
        self.layout().addWidget(self.textEdit)

        buttonLayout = QHBoxLayout()
        buttonLayout.addStretch()
        okButton = QPushButton('OK')
        buttonLayout.addWidget(okButton)
        cancelButton = QPushButton('Cancel')
        buttonLayout.addWidget(cancelButton)
        self.layout().addLayout(buttonLayout)

        self.textEdit.setPlainText(text)
        self.textEdit.selectAll()
        okButton.clicked.connect(self.accept)
        cancelButton.clicked.connect(self.reject)

class QInputDialog(QInputDialog):
    @classmethod
    def getMultiLineText(cls, parent, title, label, text='', **kwargs):
        dialog = _QInputDialogMultiline(parent, title, label, text, **kwargs)
        result = dialog.exec_()
        return (str(dialog.textEdit.toPlainText()), bool(result))

Example to show they look the same:

QInputDialog.getMultiLineText(None, 'Window Title', 'This is a label.', 'Initial text')

Qt4 (my code):

在此处输入图片说明

Qt5 (standard code):

在此处输入图片说明

I was able to do that using QInputDialog and setting QInputDialog::UsePlainTextEditForTextInput.

However, one issue that I found was that QInputDialog was always selecting the text in the dialog (in exec()) and there is no flag to prevent that. The workaround was to connect the change in the selection to a lambda that deselects everything:

        auto noteDialog = new QInputDialog(this);
        noteDialog->setOptions(QInputDialog::UsePlainTextEditForTextInput);
        noteDialog->setWindowTitle("Title");
        noteDialog->setLabelText("Notes:");
        noteDialog->setTextValue("text");
        auto lineEdit = noteDialog->findChild<QPlainTextEdit*>();
        connect(lineEdit, &QPlainTextEdit::selectionChanged, [lineEdit](){
            if(lineEdit->textCursor().hasSelection())
            {
                QTextCursor cursor = lineEdit->textCursor();
                cursor.clearSelection();
                cursor.movePosition(QTextCursor::End);
                lineEdit->setTextCursor(cursor);
            }
        });
        bool ok = noteDialog->exec();
        if (ok)
            doSomething(noteDialog->textValue());

If you are fine with the selected text, QInputDialog::getMultiLineText alone should do the trick.

To retrieve the user's input from QInputDialog::getText() into an expandable string:

 bool ok;
 std::string* comment = new std::string;
 QString qComment = QInputDialog::getText(0,
         "<title_of_input_dialog_displayed_at_top>",
         "<label_of_input_field_displayed_at_left>",
         QLineEdit::Normal, "<enter_this_or_that_here>", &ok);
 if (ok && !qComment.isEmpty()) {
    QByteArray qba = qComment.toLocal8Bit();
    comment->assign(qba.data(), qba.size());
 } else if (ok) { // user clicked Ok but did not enter text
    comment->assign("<default_user_input>");
 } else { // user clicked Cancel
   ...
 }
 delete comment;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM