【问题标题】:Qt: how to make it so that only one of QCompleter::activated() or QLineEdit::returnPressed() gets emitted?Qt:如何使只有一个 QCompleter::activated() 或 QLineEdit::returnPressed() 被发射?
【发布时间】:2010-12-25 22:29:36
【问题描述】:

我有一个带有 QCompleter 的 QLineEdit。我想要一个插槽 myslot() 在发出信号 QCompleter::activated(const QString) 或 QLineEdit::returnPressed() 时调用。

另外,如果用户使用 QCompleter 输入数据,我希望在完成后直接调用此插槽(即,如果用户已经单击 QCompleter,我不希望用户必须按 Enter) .

如果用户不使用完成程序,或者使用鼠标单击完成程序,这将正常工作。但是,如果他在 QCompleter 的弹出窗口中使用 enter 键,则两个信号都会发出,并且 myslot() 会被调用两次。

如何让它在任何情况下都只被调用一次?

【问题讨论】:

  • 那么你只是不连接到 QLineEdit::returnPressed() 信号。
  • 那行不通,因为如果用户不使用 QCompleter,则不会发出任何内容。
  • 您是否尝试过连接到 QLineEdit::editingFinished() (并且只有那个)是否符合您的要求?连接到完成者似乎是错误的(这只是用户更改文本的另一种方式)。
  • @Frank Osterfeld :是的,但是,如果用户只点击 QCompleter 弹出窗口,它不会发送(他必须然后按 Enter,这是不必要的)。是的,这对我来说似乎也是错误的,但我不知道有任何其他方法可以实现我想要的。

标签: c++ qt signals-slots


【解决方案1】:

我建议为 QCompleter 创建一个包装类,在其中重新实现 eventFilter()。包装类可以仅针对鼠标单击发出信号,也可以吃掉返回的按下事件。清晰的文档可以在 Qt 手册中找到。在线副本在这里:http://doc.qt.io/archives/4.6/qobject.html#eventFilter

还有其他方法,但这个方法相当困难。

【讨论】:

    【解决方案2】:

    您可以尝试确保您仅连接到一个适当的信号。如果完成者可见,则连接到其信号并断开与行编辑的连接。当完成者离开时,然后重新连接到行编辑。这是一个按您希望的方式工作的文件示例。

    #include <QAbstractItemView>
    #include <QApplication>
    #include <QCompleter>
    #include <QDebug>
    #include <QLineEdit>
    
    class MyLineEdit : public QLineEdit
    {
    Q_OBJECT
    public:
        MyLineEdit() : m_completer( new QCompleter( QStringList( "foo" ) ) )
        {
            setCompleter( m_completer );
            m_completer->popup()->installEventFilter( this );
            connectReturnPressed();
        }
    
        virtual bool eventFilter( QObject* watched, QEvent* e )
        {
            if ( e->type() == QEvent::Show )
            {
                connectCompleterActivated();
            }
            else if ( e->type() == QEvent::Hide )
            {
                connectReturnPressed();
            }
    
            return QLineEdit::eventFilter( watched, e );
        }
    
    private slots:
        void myslot() { qDebug() << "myslot"; }
    
    private:
        void connectReturnPressed()
        {
            disconnect( m_completer, SIGNAL( activated( const QString& ) )
                      , this, SLOT( myslot() ) );
            connect( this, SIGNAL( returnPressed() )
                         , SLOT( myslot() ) );
        }
        void connectCompleterActivated()
        {
            disconnect( this, SIGNAL( returnPressed() )
                      , this, SLOT( myslot() ) );
            connect( m_completer, SIGNAL( activated( const QString& ) )
                   , SLOT( myslot() ) );
        }
    
        QCompleter*const m_completer;
    };
    
    #include "main.moc"
    
    int main( int argc, char** argv )
    {
        QApplication qapp( argc, argv );
    
        MyLineEdit*const edit = new MyLineEdit;
        edit->show();
    
        return qapp.exec();
    }
    

    【讨论】:

      【解决方案3】:

      我解决了这个问题;它不是特别干净,但它确实有效。 这是我的两个信号的处理程序。如果信号来自 QCompleter,则 caller 设置为 COMPLETER,否则设置为 ENTER_PRESSED。

      void myClass::handler(char caller)
      {
        if ((caller == COMPLETER && lineedit->text().length() != 0) || (caller == ENTER_PRESSED))
        {
          // do stuff here
          lineedit->clear();
        }
      }
      

      通过在完成需要做的工作后清理帮助热线,它可以忽略第二个信号(来自完成者的信号),因为 QCompleter 完成空字符串没有意义。

      此外,我需要这种行为(即,如果 helpline->text().length() 为 0,则不只是忽略信号),因为在我的应用程序中,用户只需按空输入即可字符串。

      【讨论】:

      • 你好。我也有同样的问题。如果您还记得您的解决方案,您的处理程序连接到什么信号? returnPressed() 和activated() 都不会发送任何字符。还是你用过 Qt3?
      • @gxoptg:我相信我将 returnPressed() 和 activate() 都连接到了它们自己的处理程序,后者又用适当的参数调用了这个处理程序。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多