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

本文探讨了如何利用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的空间就储存了我们感兴趣的按键的状态,并且借助位运算的威力,迅速准确地让我们判断按键所处的状态。

<think>我们正在讨论Qt Creator中如何一次性修改多个控件的文字大小和样式等属性。 在Qt Creator中,可以通过样式表(QSS)或者属性编辑器的多选功能来实现一次性修改多个控件的属性。 方法1:使用样式表(推荐) 1. 在Qt Creator的设计模式下,选中多个控件(按住Ctrl并逐个点击控件)。 2. 在右侧属性编辑器中,找到“styleSheet”属性。 3. 点击输入框旁边的省略号按钮,打开样式表编辑器。 4. 在编辑器中编写样式,例如设置字体大小和颜色: font-size: 12pt; color: red; 5. 点击“确定”后,所有选中的控件都会应用这个样式。 方法2:使用属性编辑器的多选功能 1. 同样,在设计模式下选中多个控件。 2. 在属性编辑器中,找到需要修改的属性(例如字体font属性)。 3. 在font属性处,点击下拉箭头,选择“更改所有选中项的此属性”。 4. 然后设置字体、大小等,这样所有选中控件的字体属性都会被修改。 注意:方法2只能修改控件共有的属性,如果某个控件没有该属性则不会生效。而方法1通过样式表设置,如果控件支持样式表,则会生效。 另外,还可以使用“属性编辑器”上方的“应用到所有选中项”按钮(一个复选框),当选中多个控件并修改某个属性时,该属性会应用到所有选中的控件[^1]。 示例:修改多个QLabel的字体大小 1. 选中多个QLabel。 2. 在属性编辑器中找到font属性。 3. 展开font属性,设置pointSize为12。 4. 由于在选中多个控件时修改属性,会自动应用到所有选中的控件(注意观察属性编辑器的顶部,有一个“应用到所有选中项”的按钮,默认是选中的)。 但是,如果控件类型不同,可能某些属性不是共有的,这时使用样式表会更加统一。 注意事项:样式表会覆盖通过属性设置的样式,而且样式表可能会影响控件的子控件。如果只需要简单的属性修改,使用属性编辑器可能更直接。 根据实际需求选择方法。 以上方法在Qt 5和Qt 6的Qt Creator中均适用。 §§相关问题§§ 1. 如何在Qt Creator中为多个控件设置相同的布局属性? 2. 如何使用Qt样式表(QSS)来自定义整个应用程序的外观? 3. 在Qt Designer中如何创建和使用自定义控件? </think>在Qt Creator中一次性修改多个控件的文字大小、样式等属性,可以通过以下两种高效方法实现: ### 方法1:多选控件统一修改属性(推荐) 1. **多选控件** 在设计视图(Design Mode)中按住 `Ctrl` ,依点击需要修改的控件 2. **统一修改属性** 在右侧 **属性编辑器** 中: - 找到 `font` 属性组 - 修改 `pointSize`(字号)、`family`(字体)、`weight`(粗细)等 - 所有选中控件的属性将 **同步更新** > ![属性编辑器多选修改示意图](https://doc.qt.io/qt-6/images/qtcreator-design-mode-property-editor.png) > *通过属性编辑器批量修改字体属性[^1]* 3. **扩展样式** 如需设置文字颜色等高级样式,可在 `styleSheet` 属性中添加QL代码: ```css color: #FF0000; /* 红色文字 */ font-weight: bold; ``` ### 方法2:样式表批量应用(适合复杂项目) 1. **创建样式类** 在父容器(如QWidget)的 `styleSheet` 中添加类选择器: ```css .MyTextStyle { font-size: 14px; font-family: "Microsoft YaHei"; color: #333333; } ``` 2. **批量应用样式** 在代码中为所有目标控件设置类名: ```cpp // 批量设置样式类 for (QLabel* label : findChildren<QLabel*>()) { label->setProperty("class", "MyTextStyle"); } ``` 或通过属性编辑器为每个控件添加 `class` 属性为 `MyTextStyle` ### ⚠️ 注意事项 1. **继承关系** 修改父容器的字体属性时,子控件默认继承该属性(除非单独设置了样式) 2. **样式优先级** `styleSheet` > 单独设置的属性 > 父控件继承属性 *(可通过设置 `!important` 强制覆盖)* 3. **实时预览** 修改样式表后按 `Ctrl+R` 刷新预览,确保效果符合预期 4. **类型兼容性** 多选编辑时仅显示 **公共属性**(如同时选择QLabel和QPushButton时只显示两者共有的属性) > 💡 **技巧**:使用 **对象选择器** (`QObjectName`) 可实现更精细的样式控制,例如: > `#titleLabel { font-size: 18px; }` 仅作用于特定命名的控件
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值