一个小程序,让你知道Qt一次能支持按下多少个键(二)

一个小程序,让你知道Qt一次能支持按下多少个键(二)

接上次的日志

上次演示程序表明,Qt可以支持多个按键同时按下,这可以激起我们探索按键在游戏中的作用。知道吗?操作感是大多数游戏成功的因素之一,不谈那些网游,那些街机游戏更是将操作感视为其生命线。Qt要成为一款成功的游戏平台,这些因素肯定是不能忽略的。这会儿我将再次演示我们究竟是如何将Qt按键事件来适配我们需要的游戏按键效果的。

程序源代码下载地址:这里

上次我们使用了QList<int>来保存所有按下键的状态,其实啊,那么多按键,我们没有必要全部都利用,除非是那些网络游戏。目前,我觉得将键盘中的某些键定义为游戏中可以操作的键就行了。比如说可以使用键盘的“上、下、左、右”键或者“WSAD”来模拟上下左右键,让zxc键来表示CBA键。让QList<int>来保存少数几个按键的信息,实在是杀鸡用牛刀了,我们可以只使用一个unsignedlong的大小就可以保存32个按键的信息——你应该猜到了,0表示按键弹出,1表示按键按下。

想法倒是不错,但是如何实施呢?这里需要解决的问题有记录下按键的状态和读取按键状态的信息。怎样知道按键按下?使用按位与操作就可以了。怎么样?很简单吧,我们试试。

下面是Widget.h文件,注意其中的SaveKeyPressed()SaveKeyReleased()KeyPressed()函数。

#ifndef WIDGET_H
#define WIDGET_H
#include <QString>
#include <QList>
#include <QWidget>
/*---------------------------------------------------------------------------*/
class Widget: public QWidget
{
    Q_OBJECT
public:
    Widget( void );
    ~Widget( void );
protected:
    void paintEvent( QPaintEvent* event );
    void keyPressEvent( QKeyEvent* event );
    void keyReleaseEvent( QKeyEvent* event );
private:
    void SetShowText( void );
    inline void SaveKeyPressed( int key )
    {
        m_PressedKeys |= ( 1 << key );
    }
    inline void SaveKeyReleased( int key )
    {
        m_PressedKeys &= ~( 1 << key );
    }
    inline bool KeyPressed( int key )
    {
        return m_PressedKeys & ( 1 << key );
    }
    enum Interested_Keys
    {
        Key_Up = 1,
        Key_Down,
        Key_Left,
        Key_Right
    };
    QString                       m_Text;
    QString                       m_ShowText;
    quint32                       m_PressedKeys;
};
/*---------------------------------------------------------------------------*/
#endif // WIDGET_H

在上面我们定义了Interested_Keys枚举。其实枚举的好处还是很大的,它不产生编译单元,枚举的本质是整型数,可以和其它的数字进行加减乘除等等。最好的作用还在于可以让我们通过字面意思了解枚举常量的意思。

下面是Widget.cpp文件,我们捕获keyPressEvent()keyReleaseEvent()函数来记录按键的变化情况。最后我们使用SetShowText()函数来告诉我们究竟是什么按键已经被按下了。

#include <QPoint>
#include <QKeyEvent>
#include <QPainter>
#include "Widget.h"
Widget::Widget( void ): QWidget( 0 ), m_PressedKeys( 0 )
{
    // 设置窗口的一些属性
    setFixedSize( 640, 360 );
    setWindowTitle( tr( "KeyTest" ) );
    // 设置文字
    m_Text = tr( "Try to press key.\n" );
}
/*---------------------------------------------------------------------------*/
Widget::~Widget( void )
{
}
/*---------------------------------------------------------------------------*/
void Widget::paintEvent( QPaintEvent* event )
{
    Q_UNUSED( event )
    QPainter painter( this );
    painter.drawText( QPoint( 32, 32 ), m_Text );
    painter.drawText( QPoint( 32, 64 ), m_ShowText );
}
/*---------------------------------------------------------------------------*/
void Widget::keyPressEvent( QKeyEvent* event )
{
    switch ( event->key( ) )
    {
    case Qt::Key_Up: SaveKeyPressed( Key_Up ); break;
    case Qt::Key_Down: SaveKeyPressed( Key_Down ); break;
    case Qt::Key_Left: SaveKeyPressed( Key_Left ); break;
    case Qt::Key_Right: SaveKeyPressed( Key_Right ); break;
    default: break;
    }
    SetShowText( );
    update( );
}
/*---------------------------------------------------------------------------*/
void Widget::keyReleaseEvent( QKeyEvent* event )
{
    switch ( event->key( ) )
    {
    case Qt::Key_Up: SaveKeyReleased( Key_Up ); break;
    case Qt::Key_Down: SaveKeyReleased( Key_Down ); break;
    case Qt::Key_Left: SaveKeyReleased( Key_Left ); break;
    case Qt::Key_Right: SaveKeyReleased( Key_Right ); break;
    default: break;
    }
    SetShowText( );
    update( );
}
/*---------------------------------------------------------------------------*/
void Widget::SetShowText( void )
{
    m_ShowText = tr( "Pressed Keys: " );
    if ( KeyPressed( Key_Up ) ) m_ShowText += tr( "Up " );
    if ( KeyPressed( Key_Down ) ) m_ShowText += tr( "Down " );
    if ( KeyPressed( Key_Left ) ) m_ShowText += tr( "Left " );
    if ( KeyPressed( Key_Right ) ) m_ShowText += tr( "Right " );
}

main.cpp和以前的内容没有什么区别,就一笔带过吧。

#include <QApplication>
#include <QTranslator>
#include "Widget.h"
int main( int argc, char** argv )
{
    QApplication app( argc, argv );
    QTranslator trans;
    trans.load( ":/zh_CN.qm" );
    app.installTranslator( &trans );
    Widget w;
    w.show( );
    return app.exec( );
}

好了,测试一下效果吧。


经过测试,似乎一起只能按下上下左右中的三个键。这个程序和上篇日志中的程序最大不同在于仅用了一个unsignedlong的空间就储存了我们感兴趣的按键的状态,并且借助位运算的威力,迅速准确地让我们判断按键所处的状态。

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值