Reputation: 380
I have a QComboBox
filled with some data. I wish to edit the lineEdit
of the comboBox
and when I do that to make the comboBox
display his pop up while I am editing. The problem is I lost the focus of the lineEdit
and I can write only one letter at a time.
This is what I am doing at a trivial level:
ui->comboBox->addItem("This");
ui->comboBox->addItem("is");
ui->comboBox->addItem("a");
ui->comboBox->addItem("comboBox");
ui->comboBox->setEditable(true);
connect(ui->comboBox, SIGNAL(currentTextChanged(QString)), this, SLOT(PrintTextLineEdit(QString)));
void MainWindow::PrintTextLineEdit(QString str)
{
ui->comboBox->showPopup();
ui->comboBox->lineEdit()->setFocus();
}
Also if I use the blockSignal
on the lineEdit
while I show the pop up is useless. Any suggestions?
EDIT
It seems I need to provide some extra detail. I need to be able to write an entire word at a time without to lose focus when I use ui->comboBox->showPopUp()
in the currentTextChanged
signal.
Or to put it simple: the cursor do not need to disappear from the QLineEdit
after the signal is emitted and the popUp is shown.
Upvotes: 3
Views: 4867
Reputation: 11064
Using the QCompleter
feature of QLineEdit
may be a better / less hacky solution:
QStringListModel *model; // or another QAbstractItemModel
model->setStringList({"This", "is", "a", "combobox"});
QLineEdit *lineEdit;
lineEdit->setCompleter(new QCompleter(model, lineEdit));
lineEdit->completer()->setFilterMode(Qt::MatchContains); // set filter mode as desired
A popup will be shown once the user starts editing the line edit. The only disadvantage of this approach is the absence of the drop down icon to show all possible (unfiltered) items.
Upvotes: 1
Reputation: 11
Your problem is caused by grabKeyboard
. The keyboard is grabbed by the popups, so the solution is easy, just set the edit to regrab the keyboard, using grabKeyBoard()
Upvotes: 1
Reputation: 2210
You need to derive your own combo box class from QComboBox
and override the showPopup()
virtual method to return the focus back to the line edit.
void CMyComboBox::showPopup()
{
QComboBox::showPopup();
// Put the focus back later, after all pending events are processed.
QTimer::singleShot(0, [this](){ lineEdit()->setFocus(); });
}
As a special case, a QTimer with a timeout of 0 will time out as soon as all the events in the window system's event queue have been processed.
EDIT:
This works (although one could consider that as a hack):
class CMyComboBox : public QComboBox
{
public:
CMyComboBox(QWidget* parent)
: QComboBox(parent)
{
view()->installEventFilter(this);
}
// Event filter forwards view key events to the line edit.
bool eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
QKeyEvent* newEvent = new QKeyEvent(keyEvent->type(), keyEvent->key(), keyEvent->modifiers(),
keyEvent->text(), keyEvent->isAutoRepeat(), keyEvent->count());
QFocusEvent* focusEvent = new QFocusEvent(QEvent::FocusIn, Qt::OtherFocusReason);
QCoreApplication::postEvent(lineEdit(), focusEvent);
QCoreApplication::postEvent(lineEdit(), newEvent);
}
return false;
}
};
But personally, I would probably use a separated QMenu
for displaying word list, not the popup menu of combo box.
Upvotes: 2
Reputation: 26468
When I look in the code of QCombobox i see the following inside the showPopup code:
container->show();
container->updateScrollers();
view()->setFocus(); // <<-- focus command here
view()->scrollTo(view()->currentIndex(),
style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)
? QAbstractItemView::PositionAtCenter
: QAbstractItemView::EnsureVisible);
So perhaps if you do the following (not tested here) you might get the result you want:
ui->comboBox->addItem("This");
ui->comboBox->addItem("is");
ui->comboBox->addItem("a");
ui->comboBox->addItem("comboBox");
ui->comboBox->setEditable(true);
ui->comboBox->view()->setFocusPolicy(Qt::FocusPolicy::NoFocus); // don't allow focusing of the view of the popup
connect(ui->comboBox, SIGNAL(currentTextChanged(QString)), this, SLOT(PrintTextLineEdit(QString)));
void MainWindow::PrintTextLineEdit(QString str)
{
ui->comboBox->showPopup();
ui->comboBox->lineEdit()->setFocus();
}
Worth a try.
Upvotes: 0
Reputation: 2073
Each combobox has a default QCompleter
that can show completion options in the popup. I think you can achieve what you want by setting this completers mode to PopupCompletion
.
ui->comboBox->completer()->setCompletionMode(QCompleter::PopupCompletion);
In this case, combobox will show matching selections while typing. If you want it to list all items of combobox, I think you should implement a custom QCompleter that matches all items regardless of what user types.
Upvotes: 6