【问题标题】:QComboBox edit LineEdit while PopUp is activeQComboBox 在 PopUp 处于活动状态时编辑 LineEdit
【发布时间】:2016-12-20 06:39:52
【问题描述】:

我有一个QComboBox 填充了一些数据。我希望编辑comboBoxlineEdit,并且当我这样做时,让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();
}

另外,如果我在lineEdit 上使用blockSignal,而我显示弹出窗口是无用的。有什么建议吗?

编辑

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

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

【问题讨论】:

  • 您实际上试图实现什么样的行为?某种下拉建议列表?
  • 某种过滤器,但没有代理或自定义列表。我的问题是我希望我可以在弹出窗口打开的情况下输入一个单词。

标签: c++ qt


【解决方案1】:

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

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

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

【讨论】:

  • 不幸的是,这不是我想要的。我只需要在弹出窗口打开的情况下输入一个完整的单词。
【解决方案2】:

您需要从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 会尽快超时 因为窗口系统的事件队列中的所有事件都已 已处理。

编辑:

这行得通(尽管有人可以认为这是一种 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;
    }
};

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

【讨论】:

  • 这也没有产生任何可见的效果:(
  • 抱歉回答不正确。我找到了另一个基于事件过滤器的解决方案。
  • 这是完美的。非常感谢。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    当我查看 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();
    }
    

    值得一试。

    【讨论】:

    • 这似乎没有产生任何可见的效果:(
    • 哦,等等,您正试图在组合框本身的 QLineEdit 上执行此操作?这是内置的功能。删除您的currentTextChanged 信号槽并使用@heyYo 他的方法。
    • 没有。我正在尝试在组合框的 QLineEdit 中写一些东西,当我这样做时,我需要显示 popUp。我为此打开了这个问题,仅此而已。在当前情况下,每次我写一封信都会显示弹出窗口,我无法在 QLineEdit 中进一步写入。
    • @student,以下是否对您有所帮助:doc.qt.io/archives/4.6/tools-completer.html
    【解决方案5】:

    使用QLineEditQCompleter 功能可能是一个更好/更少hacky 的解决方案:

    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
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多