当PopUp处于活动状态时,QComboBox编辑LineEdit

时间:2016-12-20 06:39:53

标签: c++ qt

我有QComboBox填充了一些数据。我希望修改lineEdit的{​​{1}},当我这样做时,我会在编辑时弹出comboBox。问题是我失去了comboBox的焦点,我一次只能写一个字母。

这就是我在一个微不足道的层面所做的事情:

lineEdit

此外,如果我在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(); } 上使用blockSignal,而我显示弹出窗口则无用。有什么建议吗?

修改

我似乎需要提供一些额外的细节。当我在lineEdit信号中使用ui->comboBox->showPopUp()时,我需要能够一次写出整个单词而不会失去焦点。

或者说简单:在发出信号并显示popUp后,光标不需要从currentTextChanged消失。

5 个答案:

答案 0 :(得分:3)

每个组合框都有一个默认的QCompleter,可以在弹出窗口中显示完成选项。我认为通过将此完成模式设置为PopupCompletion可以达到您想要的效果。

ui->comboBox->completer()->setCompletionMode(QCompleter::PopupCompletion);

在这种情况下,组合框将在键入时显示匹配的选择。如果您希望它列出所有组合框,我认为您应该实现一个匹配所有项目的自定义QCompleter,无论用户类型是什么。

答案 1 :(得分:1)

您需要从QComboBox派生自己的组合框类,并覆盖showPopup()虚拟方法,将焦点返回到行编辑。

void CMyComboBox::showPopup()
{
  QComboBox::showPopup();

  // Put the focus back later, after all pending events are processed.
  QTimer::singleShot(0, [this](){ lineEdit()->setFocus(); });
}
  

作为一种特殊情况,超时为0的QTimer将会很快超时   因为窗口系统事件队列中的所有事件都已存在   处理。

修改

这有效(尽管人们可以将其视为黑客):

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;
    }
};

但就个人而言,我可能会使用单独的QMenu来显示单词列表,而不是组合框的弹出菜单。

答案 2 :(得分:1)

您的问题是由 grabKeyboard 引起的。键盘被弹出窗口抓取,所以解决方案很简单,只需将编辑设置为重新抓取键盘,使用 grabKeyBoard()

答案 3 :(得分:0)

当我查看QCombobox的代码时,我在showPopup代码中看到以下内容:

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

所以,如果您执行以下操作(此处未测试),您可能会获得所需的结果:

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

值得一试。

答案 4 :(得分:0)

使用 QCompleterQLineEdit 功能可能是一个更好/更简单的解决方案:

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

一旦用户开始编辑行编辑,就会显示一个弹出窗口。这种方法的唯一缺点是没有下拉图标来显示所有可能的(未过滤的)项目。