0

I'm new to Qt and I have a very simple demo app. It just include a QLineEdit widget and I want to invoke a function test() when I press ctrl+p in the QLineEdit.

Below are the related files.

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QShortcut>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QShortcut *s = new QShortcut(QKeySequence("Ctrl+P"), ui->lineEdit);
    connect(s, SIGNAL(activated()), ui->lineEdit, SLOT(test()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void test(){
    qDebug() << "test() triggered!" << endl;
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void test();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

When I compile the application, I saw below messages in the debug panel and the application didn't respond to ctrl+p.

QObject::connect: No such slot QLineEdit::test() in ..\ShortcutIssueDemo\mainwindow.cpp:13
QObject::connect:  (receiver name: 'lineEdit')

What's the problem with it?

Just a learner
  • 26,690
  • 50
  • 155
  • 234

2 Answers2

4

You have 2 misconceptions:

  • The connection indicates the link between the object that emits the signal, the signal, the object to which the slot belongs and the slot. In your case it is obvious that the object to which the slot "slot" belongs is this.

  • If the old syntax (SIGNAL & SLOT) is to be used then "test" must be declared as slot.

So for the above there are 2 possible solutions:

  1. Change to :
connect(s, SIGNAL(activated()), this, SLOT(test()));
public slots:
    void test();
  1. Or use new syntax:
connect(s, &QShortcut::activated, this, &MainWindow::test);

Between both solutions, the second one is better since it will indicate errors in compile-time instead of silent errors in run-time.

By default, the context of the shortcut is Qt::WindowShortcut, that is, it will fire when the key combination is pressed and the window has focus, if only when QLineEdit has focus then you have to change the context to Qt::WidgetShortcut:

s->setContext(Qt::WidgetShortcut);
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thanks for the answer! I tried your first solution and it works. However, when I added another QLineEdit to the window and click on the new QLineEdit (so the focus is on it), I press ctrl+p can still trigger the `test()` function. How can I restrict the shortcut ctrl+p only to the first QLineEdit? – Just a learner Aug 16 '20 at 22:47
  • Btw, when I try your solution 2, I got a compile time error `C:\Users\Administrator\Documents\ShortcutIssueDemo\mainwindow.cpp:14: error: use of undeclared identifier 'QShorcut'`. It comes from `connect(s, >>>&QShorcut<<<::activated, this, &MainWindow::test);`. Are there any requirements to use this syntax? – Just a learner Aug 16 '20 at 22:50
  • @Justalearner What version of Qt are you using? Have you included QShorcut: `#include `? – eyllanesc Aug 16 '20 at 22:52
  • I'm using Qt 5.14.2. Yes I have `#include `. – Just a learner Aug 16 '20 at 22:54
  • Thanks again! Solution 2 works great and is a little big easier to use. – Just a learner Aug 16 '20 at 22:57
1

You have received the error message saying there is no such slot...

Note that u haven't marked test() as slot, hence in <mainwindow.h>, replace

void test();

by

public slots: void test();

And the slot test() belongs to the mainwindow not to s, hence use this instead of s

asmmo
  • 6,922
  • 1
  • 11
  • 25
  • There needs to be a second fix `connect(s, SIGNAL(activated()), ui->lineEdit, SLOT(test()));` the line edit does not have a test slot – drescherjm Aug 16 '20 at 22:47