以下是一个基于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` 函数,以便响应计算器界面中的键盘事件。同时,在构造函数中,我们将计算器界面的各个组件添加到了布局中,从而实现了计算器的界面。