Home > Mobile >  How to press a key in QT?
How to press a key in QT?

Time:08-20

I am new to QT.

How can I press and release a button in Qt ?

In java I do the below program to control key events ?

Robot r = new Robot();
r.keyPress(KeyEvent.VK_ENTER);
r.keyRelease(KeyEvent.VK_ENTER);

But , How can I do the same thing in QT ?

CodePudding user response:

You can either create QKeyEvent and send them to the application using QApplication::sendEvent(). Or if you want higher level API, you can build your application with QtTest module and use keyClick functions. See https://doc.qt.io/qt-6/qtest.html

CodePudding user response:

In Qt, key presses are handled by the Event System. Like other languages/frameworks events are encapsulated in an object, in Qt's case, QEvent. All subclasses of QObject have a virtual QObject::event(QEvent *e) method to handle event objects sent to it. This method does not directly handle the event, but calls the object's appropriate event handler based on the QEvent::Type enum. In the case of key presses, the QEvent::type() method returns QEvent::KeyPress.

While most events are handled internally without programmer intervention, you may send events manually using the QCoreApplication class or its subclass QGuiApplication. An instance of one of these classes is typically instantiated in the boilerplate main.cpp file created when you generate a new project with Qt Creator. These classes have access to the methods QCoreApplication::sendEvent(QObject *receiver, QEvent *event), which sends an event directly to receiver, and QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority), which sends the event to Qt's event queue to be processed later.

I've created a project to demonstrate this functionality. This app just displays a plain rectangle which can be either red or blue. The rectangle only switches colors when it receives a QKeyEvent indicating that the C key was pressed. Below the rectangle is a button which programmatically produces this event and sends it to the rectangle's widget. The project went on a bit long and is a bit messy, but I hope it helps some.

main.cpp

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    // Here I modify the boilerplate code to allow MainWindow w to have access 
    // to QApplication a so that a widget in MainWindow w can use postEvent()
    MainWindow w(nullptr, &a);
    w.show();
    return a.exec();
}

mainwindow.h

#include <QCoreApplication>
#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr, QCoreApplication* app = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QGridLayout>
#include <QLabel>

#include "keypressacceptor.h"
#include "keypressgenerator.h"

MainWindow::MainWindow(QWidget *parent, QCoreApplication *app)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QGridLayout* layout = new QGridLayout(this);
    KeyPressAcceptor* kpa = new KeyPressAcceptor(this);
    KeyPressGenerator* kpg = new KeyPressGenerator();
    kpg->registerReceiver(kpa);
    kpg->registerApp(app);

    layout->addWidget(kpa);
    layout->addWidget(kpg);

    centralWidget()->setLayout(layout);
}

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

keypressacceptor.h

#include <QWidget>

class KeyPressAcceptor : public QWidget
{
    Q_OBJECT
public:
    explicit KeyPressAcceptor(QWidget *parent = nullptr);

    bool handleKeyPress(const int &key);

protected:
    bool event(QEvent *event) override;
    void paintEvent(QPaintEvent *event) override;

signals:
private:
    QColor m_color;

};

keypressacceptor.cpp

#include "keypressacceptor.h"

#include <QEvent>
#include <QKeyEvent>
#include <QPainter>

KeyPressAcceptor::KeyPressAcceptor(QWidget *parent)
    : QWidget{parent}
    , m_color(QColor(220, 20, 20))
{
    // Setting focus policy so that the widget can accept focus.
    // This is necessary to process key press events.
    setFocusPolicy(Qt::StrongFocus);
}

bool KeyPressAcceptor::handleKeyPress(const int &key)
{
    // This method performs some arbitrary action, in this case changing a
    // color, to indicate that a key press has been processed.
    switch (key) {
    case Qt::Key_C:

        // If the "C" key was pressed, switch m_color
        if (m_color == QColor(220, 20, 20)) {
            m_color = QColor(20, 20, 220);
        } else {
            m_color = QColor(220, 20, 20);
        }

        // Call update() to tell Qt to repaint this widget once Qt has entered
        // the main event loop
        update();
        return true;

    default:

        return false;
    }
}

bool KeyPressAcceptor::event(QEvent *event)
{
    switch (event->type()) {
    case QEvent::KeyPress:

        // If the received event is of type QEvent::KeyPress, then cast the
        // variable event to type QKeyEvent*, then use the event's key()
        // method to pass as an argument to this class's handleKeyPress()
        // method.
        return handleKeyPress(static_cast<QKeyEvent*>(event)->key());

        // Note! This overrides QWidget's default behavior upon receiving a
        // QKeyEvent event

    default:

        // Otherwise, be sure to use the class's superclass to process any
        // other events.
        return QWidget::event(event);
    }
}

void KeyPressAcceptor::paintEvent(QPaintEvent *event)
{
    // Don't need to use the event parameter in this implementation.
    Q_UNUSED(event)

    // Want to draw a rectangle centered in the widget whose height is half
    // the widget's height and whose width is half the widget's width.
    // The color of the rectangle is determined by m_color.

    // First define the rectangle using the height and width properties of
    // QWidget to determine the rectangle's height, width, and coordinates of
    // top left corner.
    QRect rect(width() / 4, height() / 4,  // Coordinates of top left corner
               width() / 2, height() / 2); // Width and height

    // Create a QPainter object to paint with
    QPainter painter(this);

    // Set pen and brush for rectangle's outline and fill respectively.
    painter.setPen(QColor(0,0,0)); // Black 1px pen
    painter.setBrush(QBrush(m_color)); // Solid fill of color m_color

    // Draw the rectangle
    painter.drawRect(rect);
}

keypressgenerator.h

#include <QCoreApplication>
#include <QPushButton>
#include <QObject>

class KeyPressGenerator : public QPushButton
{
    Q_OBJECT
public:
    explicit KeyPressGenerator(QWidget *parent = nullptr);

    void registerApp(QCoreApplication* app);
    void registerReceiver(QObject* receiver);

public slots:
    void generateKeyPress();

private:
    QCoreApplication* m_app;
    QObject* m_receiver;
};

keypressgenerator.cpp

#include "keypressgenerator.h"

#include <QCoreApplication>
#include <QKeyEvent>

KeyPressGenerator::KeyPressGenerator(QWidget *parent)
    : QPushButton{parent}
    , m_app(nullptr)
    , m_receiver(nullptr)
{
    setText("Push Button to Send C Key Press");

    // Connect clicked signal to generateKeyPress so when button is clicked
    // a programmatically generated keypress is sent to m_receiver
    connect(this, &KeyPressGenerator::clicked,
            this, &KeyPressGenerator::generateKeyPress);
}

void KeyPressGenerator::registerApp(QCoreApplication *app)
{
    m_app = app;
}

void KeyPressGenerator::registerReceiver(QObject *receiver)
{
    m_receiver = receiver;
}

void KeyPressGenerator::generateKeyPress()
{
    if (m_app == nullptr || m_receiver == nullptr) return;

    // Generate the key press event. Check documentation for an explanation of
    // the constructor's parameters.
    QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, Qt::Key_C, Qt::NoModifier);

    m_app->postEvent(m_receiver, event);
}
  •  Tags:  
  • c qt
  • Related