我有一个GameScreen小部件,它使用keyPressEvent和keyReleaseEvent来获取L / R箭头键输入。这些事件连接到一个信号,该信号告诉GameScreen里面的QGraphicsItem叫做Paddle前进,而Paddle有一个更新屏幕的paint事件。从我的qDebug语句中,似乎keyReleaseEvent总是在keyPressEvent之前触发,强制用户在keyPressEvent可以处理任何内容之前强制触发keyReleaseEvent。
有效的方法: 我原来的实现没有使用QGraphicsScene或QGraphicsView,并且在GameScreen中使用了由计时器触发的QPainter paint()。 keyPressEvent或keyReleaseEvent没有问题。
在研究了碰撞小鼠的例子之后,我改变了GameScreen以使用QGraphicsScene而不是QPainter; keyPressEvent和keyReleaseEvent代码保持不变。问题出现的地方。
解决方法:在切换到QGraphicsScene之后,最初keyEventPress和keyReleaseEvent根本没有触发。在阅读this SO帖子之后,我设法通过在keyReleaseEvent中放置setFocus()来再次使用输入。
问题#1 :如果我根本没有在代码中或在keyPressEvent内部没有setFocus(),则只处理keyReleaseEvent。因此,除非keyReleaseEvent首先激活,否则会阻止keyPressEvent触发。
问题#2 :如第一段所述,keyReleaseEvent setFocus()变通方法需要在程序开始触发keyPressEvent之前按下并释放L / R键。在这一点上,我可能不得不做一个肮脏的黑客并使用刺激的按键按下,这样用户就不必这样做了。
这是我的相关代码。我将看看this solution是否有效,但我宁愿不依赖黑客来实现这一目标。对于长篇文章感到抱歉,如果任何勇敢的灵魂能够解释导致这个奇怪问题的原因以及解决问题的方法,我将非常感激!提前谢谢。
GameScreen.cpp:
GameScreen::GameScreen(QWidget *parent) : QWidget(parent)
{
paddle = new Paddle();
scene = new QGraphicsScene(0, 0, 640, 480, this);
timer = new QTimer(this);
timer->start(20);
connect(timer, SIGNAL(timeout()), scene, SLOT(advance()));
}
void GameScreen::keyReleaseEvent(QKeyEvent *e){
setFocus();
if(!e->isAutoRepeat()){
switch(e->key()){
case Qt::Key_Left:{
paddle->setKeepLeft(false);
qDebug() << "Left released";
break;
}
case Qt::Key_Right:{
paddle->setKeepRight(false);
qDebug() << "Right released";
break;
}
default:
QWidget::keyReleaseEvent(e);
}
}
}
void GameScreen::keyPressEvent(QKeyEvent *e){
if(!e->isAutoRepeat()){
switch(e->key()){
case Qt::Key_Left:{
paddle->setKeepLeft(true);
qDebug() << "Left";
break;
}
case Qt::Key_Right:{
paddle->setKeepRight(true);
qDebug() << "Right";
break;
}
default:
QWidget::keyPressEvent(e);
}
}
}
Paddle.cpp:
Paddle::Paddle()
{
x = 280, y = 400, speed = 8;
width = 80, height = 10;
QColor color("powderblue");
style = new QBrush(color, Qt::SolidPattern); //not sure how to add QColor inline
keepLeft = false, keepRight = false;
}
QRectF Paddle::boundingRect() const{
return QRectF(x, y, width, height);
}
void Paddle::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *){
painter->setPen(Qt::NoPen);
painter->setBrush(*style);
painter->drawRect(getShape());
}
void Paddle::advance(int step){
if(!step)
return;
if(keepLeft == true){
moveLeft();
update();
}
else if(keepRight == true){
moveRight();
update();
}
return;
}
void Paddle::moveLeft(){
if(x > 0){
x -= speed;
}
}
void Paddle::moveRight(){
if(x < (640-width)){
x += speed;
}
}
QRectF Paddle::getShape(){
return QRectF(x, y, width, height);
}
QBrush Paddle::getBrushStyle(){
return *style;
}
void Paddle::setKeepLeft(bool val){
keepLeft = val;
}
void Paddle::setKeepRight(bool val){
keepRight = val;
}