[Qt]如何屏蔽QPushButton的键盘事件

今天想实现一种效果:当界面上的QPushButton获得焦点后,点击键盘的上、下、左、右方向键,则QPushButton随之前后左右移动。
很简单的一种效果,但是实现起来却绕了弯路。
最初的想法就是在界面类中重载keyPressEvent(),当键值为方向键时对QPushButton对象进行相应的移动操作,非常简单。编译运行,选中QPushButton控件,点击键盘的左右方向键,控件并没有发生预期的移动,而是焦点转移到相邻的可tab控件上了。
Why?原来此时母窗体并没有收到键盘事件,当然也就不会处理键盘事件。键盘事件到哪去了呢?必然是QPushButton自身拦截了键盘事件,实现了焦点切换的操作,然后就丢弃了,弃了,了。。。
怎么办?天无绝人之路,为了规避这种情况,需要屏蔽QPushButton自身特有的keyPressEvent()事件处理逻辑。因此由QPushButton派生出新类UserButton,重载keyPressEvent()和keyReleaseEvent():

void UserButton::keyPressEvent(QKeyEvent* event)
{
    QWidget::keyPressEvent(event);
}
void UserButton::keyReleaseEvent(QKeyEvent* event)
{
    QWidget::keyPressEvent(event);
}

QPushButton本身也是派生自QWidget的一种类,QWidget中的按键事件只要没有处理,都会继续向其母窗体传递,直到被某一层窗体处理为止。直接调用QWidget的按键处理事件就能屏蔽QPushButton自身的按键处理逻辑,达到目的。是不是很简单?
另外,只有获得焦点的控件才能接收按键事件,因此,如果要处理按键事件,必须先确定目标窗体得到了焦点,否则也达不到目的。窗体获得焦点的方法:

QWidget *widget = new QWidget();
widget->show();
widget->setFocus();
  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个基于Qt的简单计算器,可以响应键盘事件: ``` #include <QtGui> class Calculator : public QWidget { Q_OBJECT public: Calculator(QWidget *parent = 0); private slots: void digitClicked(); void unaryOperatorClicked(); void additiveOperatorClicked(); void multiplicativeOperatorClicked(); void equalClicked(); void pointClicked(); void changeSignClicked(); void backspaceClicked(); void clear(); void clearAll(); protected: void keyPressEvent(QKeyEvent *event); private: QPushButton *createButton(const QString &text, const char *member); void abortOperation(); bool calculate(double rightOperand, const QString &pendingOperator); double sumSoFar; double factorSoFar; QString pendingAdditiveOperator; QString pendingMultiplicativeOperator; QString displayedValue; bool waitingForOperand; QLineEdit *display; QPushButton *backspaceButton; QPushButton *clearButton; QPushButton *clearAllButton; QPushButton *changeSignButton; QPushButton *pointButton; enum { NumDigitButtons = 10 }; QPushButton *digitButtons[NumDigitButtons]; QPushButton *divisionButton; QPushButton *timesButton; QPushButton *minusButton; QPushButton *plusButton; QPushButton *equalButton; QGridLayout *mainLayout; }; Calculator::Calculator(QWidget *parent) : QWidget(parent) { sumSoFar = 0.0; factorSoFar = 0.0; pendingAdditiveOperator.clear(); pendingMultiplicativeOperator.clear(); displayedValue = "0"; waitingForOperand = true; display = new QLineEdit("0"); digitButtons[0] = createButton(tr("0"), SLOT(digitClicked())); digitButtons[1] = createButton(tr("1"), SLOT(digitClicked())); digitButtons[2] = createButton(tr("2"), SLOT(digitClicked())); digitButtons[3] = createButton(tr("3"), SLOT(digitClicked())); digitButtons[4] = createButton(tr("4"), SLOT(digitClicked())); digitButtons[5] = createButton(tr("5"), SLOT(digitClicked())); digitButtons[6] = createButton(tr("6"), SLOT(digitClicked())); digitButtons[7] = createButton(tr("7"), SLOT(digitClicked())); digitButtons[8] = createButton(tr("8"), SLOT(digitClicked())); digitButtons[9] = createButton(tr("9"), SLOT(digitClicked())); divisionButton = createButton(tr("/"), SLOT(multiplicativeOperatorClicked())); timesButton = createButton(tr("*"), SLOT(multiplicativeOperatorClicked())); minusButton = createButton(tr("-"), SLOT(additiveOperatorClicked())); plusButton = createButton(tr("+"), SLOT(additiveOperatorClicked())); equalButton = createButton(tr("="), SLOT(equalClicked())); pointButton = createButton(tr("."), SLOT(pointClicked())); changeSignButton = createButton(tr("\302\261"), SLOT(changeSignClicked())); backspaceButton = createButton(tr("Backspace"), SLOT(backspaceClicked())); clearButton = createButton(tr("Clear"), SLOT(clear())); clearAllButton = createButton(tr("Clear All"), SLOT(clearAll())); QGridLayout *mainLayout = new QGridLayout; mainLayout->setSizeConstraint(QLayout::SetFixedSize); mainLayout->addWidget(display, 0, 0, 1, 6); mainLayout->addWidget(backspaceButton, 1, 0, 1, 2); mainLayout->addWidget(clearButton, 1, 2, 1, 2); mainLayout->addWidget(clearAllButton, 1, 4, 1, 2); for (int i = 1; i < NumDigitButtons; ++i) { int row = ((9 - i) / 3) + 2; int column = ((i - 1) % 3) + 1; mainLayout->addWidget(digitButtons[i], row, column); } mainLayout->addWidget(digitButtons[0], 5, 1); mainLayout->addWidget(changeSignButton, 5, 2); mainLayout->addWidget(pointButton, 5, 3); mainLayout->addWidget(divisionButton, 2, 4); mainLayout->addWidget(timesButton, 3, 4); mainLayout->addWidget(minusButton, 4, 4); mainLayout->addWidget(plusButton, 5, 4); mainLayout->addWidget(equalButton, 5, 5); setLayout(mainLayout); setWindowTitle(tr("Calculator")); } QPushButton *Calculator::createButton(const QString &text, const char *member) { QPushButton *button = new QPushButton(text); connect(button, SIGNAL(clicked()), this, member); return button; } void Calculator::digitClicked() { QPushButton *clickedButton = qobject_cast<QPushButton *>(sender()); int digitValue = clickedButton->text().toInt(); if (displayedValue == "0" && digitValue == 0.0) return; if (waitingForOperand) { displayedValue = QString::number(digitValue); waitingForOperand = false; } else { displayedValue = displayedValue + QString::number(digitValue); } display->setText(displayedValue); } void Calculator::unaryOperatorClicked() { QPushButton *clickedButton = qobject_cast<QPushButton *>(sender()); QString clickedOperator = clickedButton->text(); double operand = displayedValue.toDouble(); double result = 0.0; if (clickedOperator == tr("Sqrt")) { if (operand < 0.0) { abortOperation(); return; } result = sqrt(operand); } else if (clickedOperator == tr("%")) { result = operand / 100.0; } displayedValue = QString::number(result); display->setText(displayedValue); waitingForOperand = true; } void Calculator::additiveOperatorClicked() { QPushButton *clickedButton = qobject_cast<QPushButton *>(sender()); QString clickedOperator = clickedButton->text(); double operand = displayedValue.toDouble(); if (!pendingMultiplicativeOperator.isEmpty()) { if (!calculate(operand, pendingMultiplicativeOperator)) { abortOperation(); return; } operand = factorSoFar; factorSoFar = 0.0; pendingMultiplicativeOperator.clear(); displayedValue = QString::number(operand); display->setText(displayedValue); } if (!pendingAdditiveOperator.isEmpty()) { if (!calculate(operand, pendingAdditiveOperator)) { abortOperation(); return; } sumSoFar = displayedValue.toDouble(); } else { sumSoFar = operand; } pendingAdditiveOperator = clickedOperator; waitingForOperand = true; } void Calculator::multiplicativeOperatorClicked() { QPushButton *clickedButton = qobject_cast<QPushButton *>(sender()); QString clickedOperator = clickedButton->text(); double operand = displayedValue.toDouble(); if (!pendingMultiplicativeOperator.isEmpty()) { if (!calculate(operand, pendingMultiplicativeOperator)) { abortOperation(); return; } operand = factorSoFar; factorSoFar = 0.0; pendingMultiplicativeOperator.clear(); displayedValue = QString::number(operand); display->setText(displayedValue); } pendingMultiplicativeOperator = clickedOperator; if (pendingAdditiveOperator.isEmpty()) { factorSoFar = operand; } else { if (!calculate(operand, pendingAdditiveOperator)) { abortOperation(); return; } sumSoFar = displayedValue.toDouble(); factorSoFar = sumSoFar; sumSoFar = 0.0; pendingAdditiveOperator.clear(); } waitingForOperand = true; } void Calculator::equalClicked() { double operand = displayedValue.toDouble(); if (!pendingMultiplicativeOperator.isEmpty()) { if (!calculate(operand, pendingMultiplicativeOperator)) { abortOperation(); return; } operand = factorSoFar; factorSoFar = 0.0; pendingMultiplicativeOperator.clear(); } if (!pendingAdditiveOperator.isEmpty()) { if (!calculate(operand, pendingAdditiveOperator)) { abortOperation(); return; } pendingAdditiveOperator.clear(); } else { sumSoFar = operand; } displayedValue = QString::number(sumSoFar); display->setText(displayedValue); sumSoFar = 0.0; waitingForOperand = true; } void Calculator::pointClicked() { if (waitingForOperand) display->setText("0"); if (!displayedValue.contains(".")) displayedValue += "."; display->setText(displayedValue); waitingForOperand = false; } void Calculator::changeSignClicked() { QString text = display->text(); double value = text.toDouble(); if (value > 0.0) { text.prepend(tr("-")); } else if (value < 0.0) { text.remove(0, 1); } display->setText(text); } void Calculator::backspaceClicked() { if (waitingForOperand) return; QString text = display->text(); text.chop(1); if (text.isEmpty()) { text = "0"; waitingForOperand = true; } display->setText(text); } void Calculator::clear() { if (waitingForOperand) return; display->setText("0"); waitingForOperand = true; } void Calculator::clearAll() { sumSoFar = 0.0; factorSoFar = 0.0; pendingAdditiveOperator.clear(); pendingMultiplicativeOperator.clear(); displayedValue = "0"; waitingForOperand = true; display->setText(displayedValue); } void Calculator::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_0: digitButtons[0]->animateClick(); break; case Qt::Key_1: digitButtons[1]->animateClick(); break; case Qt::Key_2: digitButtons[2]->animateClick(); break; case Qt::Key_3: digitButtons[3]->animateClick(); break; case Qt::Key_4: digitButtons[4]->animateClick(); break; case Qt::Key_5: digitButtons[5]->animateClick(); break; case Qt::Key_6: digitButtons[6]->animateClick(); break; case Qt::Key_7: digitButtons[7]->animateClick(); break; case Qt::Key_8: digitButtons[8]->animateClick(); break; case Qt::Key_9: digitButtons[9]->animateClick(); break; case Qt::Key_Plus: plusButton->animateClick(); break; case Qt::Key_Minus: minusButton->animateClick(); break; case Qt::Key_Asterisk: timesButton->animateClick(); break; case Qt::Key_Slash: divisionButton->animateClick(); break; case Qt::Key_Enter: case Qt::Key_Return: equalButton->animateClick(); break; default: QWidget::keyPressEvent(event); } } void Calculator::abortOperation() { clearAll(); display->setText(tr("####")); } bool Calculator::calculate(double rightOperand, const QString &pendingOperator) { if (pendingOperator == tr("+")) { sumSoFar += rightOperand; } else if (pendingOperator == tr("-")) { sumSoFar -= rightOperand; } else if (pendingOperator == tr("*")) { factorSoFar *= rightOperand; } else if (pendingOperator == tr("/")) { if (rightOperand == 0.0) return false; factorSoFar /= rightOperand; } return true; } ``` 在上面的代码中,我们重载了 `keyPressEvent` 函数,以便响应计算器界面中的键盘事件。同时,在构造函数中,我们将计算器界面的各个组件添加到了布局中,从而实现了计算器的界面。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值