LINUX.ORG.RU

QComboBox выпадающий список перехватывает фокус

 ,


0

2

Приветствую. Задача такая: нужно сделать комбобокс с полем ввода, чтобы список обновлялся в зависимости от того, что ввели. Не могу понять, как сделать, чтобы список не перехватывал фокус. На данный момент получается так: изменяем текст, список обновляется, но фокус на списке, и дальше изменять текст не получается, нужно кликнуть мышкой, чтобы список закрылся и стало активным поле ввода. Подскажите как это обойти? Минимальный пример:

#include <QApplication>
#include <QMainWindow>
#include <QComboBox>
#include <QVBoxLayout>
#include <QStringList>
#include <QLineEdit>
 
 
class MainWindow : public QMainWindow
{
    QComboBox* cb;
    QStringList ports = { "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3", "/dev/ttyM1", "/dev/ttyM2" };
public:
    MainWindow(QWidget* parent = nullptr) : QMainWindow(parent)
    {
        QWidget* central = new QWidget(this);
        QVBoxLayout* layout = new QVBoxLayout(central);
        cb = new QComboBox(this);
        cb->addItems(ports);
        cb->setEditable(true);
        connect(cb, &QComboBox::editTextChanged, this, &MainWindow::textEdit);
        layout->addWidget(cb);
        setCentralWidget(central);
    }
public slots:
    void textEdit(const QString& text)
    {
        cb->blockSignals(true);
        cb->clear();
        if (text.isEmpty())
            cb->addItems(ports);
        else
        {
            QStringList filter;
            for (const QString& port : ports)
            {
                if (port.contains(text, Qt::CaseInsensitive))
                    filter.append(port);
            }
            cb->addItems(filter);
        }
        cb->setEditText(text);
        cb->showPopup();
        cb->lineEdit()->setFocus();
        cb->blockSignals(false);
    }
};
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    MainWindow window;
    window.show();
    return app.exec();
}

Мой скромный опыт говорит, что использовать blockSignals без очень веской причины – плохая идея. Но возможно, это не при чём.

anonymous
()
Ответ на: комментарий от anonymous

Без blockSignals будет зацикливание, так как в слоте восстанавливается введенная строка, и тем самым опять вызывается этот же слот. Если вы знаете другой способ, буду рад.

lazgo
() автор топика

На другом форуме подсказали использовать QCompleter:

#include <QApplication>
#include <QMainWindow>
#include <QComboBox>
#include <QVBoxLayout>
#include <QStringList>
#include <QLineEdit>
#include <QCompleter>


class MainWindow : public QMainWindow
{
    QComboBox* cb;
    QStringList ports = { "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3", "/dev/ttyM1", "/dev/ttyM2" };
public:
    MainWindow(QWidget* parent = nullptr) : QMainWindow(parent)
    {
        QWidget* central = new QWidget(this);
        QVBoxLayout* layout = new QVBoxLayout(central);
        cb = new QComboBox(this);
        cb->addItems(ports);
        cb->setEditable(true);
        QCompleter* completer = cb->completer();
        completer->setCaseSensitivity(Qt::CaseInsensitive);
        completer->setCompletionMode(QCompleter::PopupCompletion);
        completer->setFilterMode(Qt::MatchContains);
        //connect(cb, &QComboBox::editTextChanged, this, &MainWindow::textEdit);
        layout->addWidget(cb);
        setCentralWidget(central);
    }
public slots:
    void textEdit(const QString& text)
    {
        cb->blockSignals(true);
        cb->clear();
        if (text.isEmpty())
            cb->addItems(ports);
        else
        {
            QStringList filter;
            for (const QString& port : ports)
            {
                if (port.contains(text, Qt::CaseInsensitive))
                    filter.append(port);
            }
            cb->addItems(filter);
        }
        cb->setEditText(text);
        cb->showPopup();
        cb->lineEdit()->setFocus();
        cb->blockSignals(false);
    }
};

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    MainWindow window;
    window.show();
    return app.exec();
}
lazgo
() автор топика
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария