简体   繁体   English

如何在 QT 中按一个键?

[英]How to press a key in QT?

I am new to QT.我是 QT 的新手。

How can I press and release a button in Qt?如何按下并释放 Qt 中的按钮?

In java I do the below program to control key events?在 java 我执行以下程序来控制关键事件?

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

But, How can I do the same thing in QT?但是,我怎样才能在 QT 中做同样的事情?

You can either create QKeyEvent and send them to the application using QApplication::sendEvent() .您可以创建QKeyEvent并使用QApplication::sendEvent()将它们发送到应用程序。 Or if you want higher level API, you can build your application with QtTest module and use keyClick functions.或者,如果您想要更高级别的 API,您可以使用QtTest模块构建您的应用程序并使用keyClick函数。 See https://doc.qt.io/qt-6/qtest.htmlhttps://doc.qt.io/qt-6/qtest.html

In Qt, key presses are handled by the Event System .在 Qt 中,按键由事件系统处理。 Like other languages/frameworks events are encapsulated in an object, in Qt's case, QEvent .与其他语言/框架一样,事件被封装在 object 中,在 Qt 的情况下为QEvent All subclasses of QObject have a virtual QObject::event(QEvent *e) method to handle event objects sent to it. QObject 的所有子类都有一个虚拟的QObject::event(QEvent *e)方法来处理发送给它的事件对象。 This method does not directly handle the event, but calls the object's appropriate event handler based on the QEvent::Type enum.此方法不直接处理事件,而是根据QEvent::Type枚举调用对象的相应事件处理程序。 In the case of key presses, the QEvent::type() method returns QEvent::KeyPress .在按键的情况下, QEvent::type()方法返回QEvent::KeyPress

While most events are handled internally without programmer intervention, you may send events manually using the QCoreApplication class or its subclass QGuiApplication .虽然大多数事件在内部处理而无需程序员干预,但您可以使用QCoreApplication class 或其子类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.这些类之一的实例通常在您使用 Qt Creator 生成新项目时创建的样板main.cpp文件中实例化。 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.这些类可以访问方法QCoreApplication::sendEvent(QObject *receiver, QEvent *event) ,它直接向接收器发送事件,以及QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority) ,它发送事件到 Qt 的事件队列以供稍后处理。

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.该矩形仅在接收到指示按下 C 键的QKeyEvent时切换 colors。 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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM