问:如何使它只发出QCompleter :: activated()或QLineEdit :: returnPressed()中的一个?

时间:2010-12-25 22:29:36

标签: c++ qt signals-slots

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

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

如果用户不使用完成符,或使用鼠标单击完成符,则此工作正常。但是,如果他在QCompleter的弹出窗口中使用回车键,则会发出两个信号,并且会调用两次myslot()。

如何制作它以便只调用一次,无论情况如何?

3 个答案:

答案 0 :(得分:1)

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

还有其他方法,但这个方法相当紧张。

答案 1 :(得分:0)

您可以尝试确保仅根据需要连接到一个信号。如果完成者可见,则连接到其信号并断开线编辑。当完成者离开后,再连接回线编辑。这是一个按您希望的方式工作的文件样本。

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

答案 2 :(得分:0)

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

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

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

此外,我需要这种行为(即,如果帮助热线 - &gt; text()。length()为0,则不仅忽略信号),因为在我的应用中,对于用户来说只需按下Enter即可空字符串。