QT上的带存储记忆功能的计算器(完整源码)

calculator.h
#ifndef CALCULATOR_H
#define CALCULATOR_H
​
#include <QWidget>
​
QT_BEGIN_NAMESPACE
class QLineEdit;
QT_END_NAMESPACE
class Button;
​
//! [0]
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(); // 当点击全部清除按钮时触发此槽函数
    void clearMemory(); // 当点击清除内存按钮时触发此槽函数
    void readMemory(); // 当点击读取内存按钮时触发此槽函数
    void setMemory(); // 当点击设置内存按钮时触发此槽函数
    void addToMemory(); // 当点击添加到内存按钮时触发此槽函数
//! [0]
​
//! [1]
private:
//! [1] //! [2]
    Button *createButton(const QString &text, const char *member); // 创建按钮并返回指针
    void abortOperation(); // 中止当前操作
    bool calculate(double rightOperand, const QString &pendingOperator); // 计算表达式的结果
//! [2]
​
//! [3]
    double sumInMemory; // 存储在内存中的数值
//! [3] //! [4]
    double sumSoFar; // 到目前为止的总和
//! [4] //! [5]
    double factorSoFar; // 到目前为止的因子
//! [5] //! [6]
    QString pendingAdditiveOperator; // 待处理的加法运算符
//! [6] //! [7]
    QString pendingMultiplicativeOperator; // 待处理的乘法运算符
//! [7] //! [8]
    bool waitingForOperand; // 是否正在等待操作数
//! [8]
​
//! [9]
    QLineEdit *display; // 显示结果的文本框
//! [9] //! [10]
​
    enum { NumDigitButtons = 10 }; // 数字按钮的数量
    Button *digitButtons[NumDigitButtons]; // 数字按钮数组
​
};
//! [10]
​
#endif
button.h
#ifndef BUTTON_H // 防止头文件重复包含
#define BUTTON_H
​
#include <QToolButton> // 引入QToolButton类,用于创建工具按钮
​
//! [0]
class Button : public QToolButton // 定义一个名为Button的类,继承自QToolButton
{
    Q_OBJECT // 声明这是一个Qt对象,以便使用Qt的信号和槽机制
​
public:
    explicit Button(const QString &text, QWidget *parent = 0); // 构造函数,接受一个文本参数和一个可选的父窗口指针
​
    QSize sizeHint() const override; // 重写sizeHint()函数,返回按钮的建议大小
};
//! [0]
​
#endif // 结束头文件保护宏
​
button.cpp
#include <QtWidgets>
​
#include "button.h"
​
//! [0]
Button::Button(const QString &text, QWidget *parent)
    : QToolButton(parent) // 构造函数,初始化父类为传入的parent参数
{
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); // 设置按钮的大小策略,使其可以自动扩展
    setText(text); // 设置按钮的文本内容为传入的text参数
}
//! [0]
​
//! [1]
QSize Button::sizeHint() const
//! [1] //! [2]
{
    QSize size = QToolButton::sizeHint(); // 获取父类QToolButton的默认大小提示
    size.rheight() += 40; // 增加按钮的高度,这里加40像素
    size.rwidth() = qMax(size.width(), size.height()); // 将按钮的宽度设置为其宽度和高度中的较大值
    return size; // 返回调整后的大小
}
//! [2]
​
calculator.cpp
#include <QtWidgets>
#include <cmath>
#include "button.h"
#include "calculator.h"
​
//! [0]
Calculator::Calculator(QWidget *parent)
    : QWidget(parent)
{
    sumInMemory = 0.0; // 初始化内存中的和为0
    sumSoFar = 0.0; // 初始化到目前为止的和为0
    factorSoFar = 0.0; // 初始化到目前为止的因子为0
    waitingForOperand = true; // 等待操作数的标志设置为true
//! [0]
​
//! [1]
    display = new QLineEdit("0"); // 创建一个显示框,初始值为0
//! [1] //! [2]
    display->setReadOnly(true); // 设置显示框为只读
    display->setAlignment(Qt::AlignRight); // 设置对齐方式为右对齐
    display->setMaxLength(15); // 设置显示框的最大长度为15
​
    QFont font = display->font(); // 获取显示框的字体
    font.setPointSize(font.pointSize() + 40); // 增加字体大小
    display->setFont(font); // 设置新的字体
//! [2]
​
//! [4]
    for (int i = 0; i < NumDigitButtons; ++i) { // 遍历数字按钮
        digitButtons[i] = createButton(QString::number(i), SLOT(digitClicked())); // 创建数字按钮并连接到digitClicked槽函数
    }
​
    Button *pointButton = createButton(tr("."), SLOT(pointClicked())); // 创建小数点按钮并连接到pointClicked槽函数
    Button *changeSignButton = createButton(tr("\302\261"), SLOT(changeSignClicked())); // 创建改变符号按钮并连接到changeSignClicked槽函数
​
    Button *backspaceButton = createButton(tr("Backspace"), SLOT(backspaceClicked())); // 创建退格键按钮并连接到backspaceClicked槽函数
    Button *clearButton = createButton(tr("Clear"), SLOT(clear())); // 创建清除按钮并连接到clear槽函数
    Button *clearAllButton = createButton(tr("Clear All"), SLOT(clearAll())); // 创建清除所有按钮并连接到clearAll槽函数
​
    Button *clearMemoryButton = createButton(tr("MC"), SLOT(clearMemory())); // 创建清除内存按钮并连接到clearMemory槽函数
    Button *readMemoryButton = createButton(tr("MR"), SLOT(readMemory())); // 创建读取内存按钮并连接到readMemory槽函数
    Button *setMemoryButton = createButton(tr("MS"), SLOT(setMemory())); // 创建设置内存按钮并连接到setMemory槽函数
    Button *addToMemoryButton = createButton(tr("M+"), SLOT(addToMemory())); // 创建添加到内存按钮并连接到addToMemory槽函数
​
    Button *divisionButton = createButton(tr("\303\267"), SLOT(multiplicativeOperatorClicked())); // 创建除法按钮并连接到multiplicativeOperatorClicked槽函数
    Button *timesButton = createButton(tr("\303\227"), SLOT(multiplicativeOperatorClicked())); // 创建乘法按钮并连接到multiplicativeOperatorClicked槽函数
    Button *minusButton = createButton(tr("-"), SLOT(additiveOperatorClicked())); // 创建减法按钮并连接到additiveOperatorClicked槽函数
    Button *plusButton = createButton(tr("+"), SLOT(additiveOperatorClicked())); // 创建加法按钮并连接到additiveOperatorClicked槽函数
​
    Button *squareRootButton = createButton(tr("Sqrt"), SLOT(unaryOperatorClicked())); // 创建平方根按钮并连接到unaryOperatorClicked槽函数
    Button *powerButton = createButton(tr("x\302\262"), SLOT(unaryOperatorClicked())); // 创建幂运算按钮并连接到unaryOperatorClicked槽函数
    Button *reciprocalButton = createButton(tr("1/x"), SLOT(unaryOperatorClicked())); // 创建倒数按钮并连接到unaryOperatorClicked槽函数
    Button *equalButton = createButton(tr("="), SLOT(equalClicked())); // 创建等于按钮并连接到equalClicked槽函数
//! [4]
​
//! [5]
    QGridLayout *mainLayout = new QGridLayout; // 创建一个网格布局
//! [5] //! [6]
    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); // 将清除所有按钮添加到布局中
​
    mainLayout->addWidget(clearMemoryButton, 2, 0); // 将清除内存按钮添加到布局中
    mainLayout->addWidget(readMemoryButton, 3, 0); // 将读取内存按钮添加到布局中
    mainLayout->addWidget(setMemoryButton, 4, 0); // 将设置内存按钮添加到布局中
    mainLayout->addWidget(addToMemoryButton, 5, 0); // 将添加到内存按钮添加到布局中
​
    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(pointButton, 5, 2); // 将小数点按钮添加到布局中
    mainLayout->addWidget(changeSignButton, 5, 3); // 将改变符号按钮添加到布局中
​
    mainLayout->addWidget(divisionButton, 2, 4); // 将除法按钮添加到布局中
    mainLayout->addWidget(timesButton, 3, 4); // 将乘法按钮添加到布局中
    mainLayout->addWidget(minusButton, 4, 4); // 将减法按钮添加到布局中
    mainLayout->addWidget(plusButton, 5, 4); // 将加法按钮添加到布局中
​
    mainLayout->addWidget(squareRootButton, 2, 5); // 将平方根按钮添加到布局中
    mainLayout->addWidget(powerButton, 3, 5); // 将幂运算按钮添加到布局中
    mainLayout->addWidget(reciprocalButton, 4, 5); // 将倒数按钮添加到布局中
    mainLayout->addWidget(equalButton, 5, 5); // 将等于按钮添加到布局中
    setLayout(mainLayout); // 设置窗口的布局为刚刚创建的网格布局
​
    setWindowTitle(tr("Calculator")); // 设置窗口标题为“计算器”
//! [6]
}
//! [7]
void Calculator::digitClicked()
{
    Button *clickedButton = qobject_cast<Button *>(sender()); // 获取发送信号的按钮对象
    int digitValue = clickedButton->text().toInt(); // 获取按钮上的数值
    // 如果当前显示框为空或者点击的是0,则直接显示该数值
    if (display->text() == "0" && digitValue == 0.0)
        return;
​
    if (waitingForOperand) {
        display->clear(); // 如果正在等待操作数,则清空显示框
        waitingForOperand = false;
    }
    display->setText(display->text() + QString::number(digitValue)); // 在显示框上添加新的数值
}
//! [8]
void Calculator::unaryOperatorClicked()
{
    Button *clickedButton = qobject_cast<Button *>(sender()); // 获取发送信号的按钮对象
    QString clickedOperator = clickedButton->text(); // 获取按钮上的运算符
    double operand = display->text().toDouble(); // 获取显示框上的数值
    double result = 0.0;
    if (clickedOperator == tr("Sqrt")) {
        if (operand < 0.0) {
            abortOperation(); // 如果数值小于0,则中止操作
            return;
        }
        result = std::sqrt(operand); // 计算平方根
    } else if (clickedOperator == tr("x\302\262")) {
        result = std::pow(operand, 2.0); // 计算平方
    } else if (clickedOperator == tr("1/x")) {
        if (operand == 0.0) {
            abortOperation(); // 如果数值为0,则中止操作
            return;
        }
        result = 1.0 / operand; // 计算倒数
    }
    display->setText(QString::number(result)); // 在显示框上显示结果
    waitingForOperand = true; // 设置等待操作数标志为true
}
//! [9]
​
//! [10]
void Calculator::additiveOperatorClicked()
//! [10] //! [11]
{
    Button *clickedButton = qobject_cast<Button *>(sender()); // 获取被点击的按钮对象
    QString clickedOperator = clickedButton->text(); // 获取被点击的按钮上的文本,即运算符
    double operand = display->text().toDouble(); // 将显示屏上的数字转换为双精度浮点数
​
//! [11] //! [12]
    if (!pendingMultiplicativeOperator.isEmpty()) { // 如果有待处理的乘法运算符
//! [12] //! [13]
        if (!calculate(operand, pendingMultiplicativeOperator)) { // 如果计算失败
            abortOperation(); // 中止操作
            return; // 返回
        }
        display->setText(QString::number(factorSoFar)); // 将结果显示在显示屏上
        operand = factorSoFar; // 更新操作数为结果
        factorSoFar = 0.0; // 重置因子
        pendingMultiplicativeOperator.clear(); // 清空待处理的乘法运算符
    }
​
//! [13] //! [14]
    if (!pendingAdditiveOperator.isEmpty()) { // 如果有待处理的加法运算符
//! [14] //! [15]
        if (!calculate(operand, pendingAdditiveOperator)) { // 如果计算失败
            abortOperation(); // 中止操作
            return; // 返回
        }
        display->setText(QString::number(sumSoFar)); // 将结果显示在显示屏上
    } else {
        sumSoFar = operand; // 否则,将操作数设置为结果
    }
​
//! [15] //! [16]
    pendingAdditiveOperator = clickedOperator; // 更新待处理的加法运算符为当前点击的运算符
//! [16] //! [17]
    waitingForOperand = true; // 设置等待操作数的标志为真
}
//! [17]
//! [18]
void Calculator::multiplicativeOperatorClicked()
{
    Button *clickedButton = qobject_cast<Button *>(sender()); // 获取被点击的按钮对象
    QString clickedOperator = clickedButton->text(); // 获取被点击的按钮上的文本,即运算符
    double operand = display->text().toDouble(); // 将显示屏上的数字转换为双精度浮点数
​
    if (!pendingMultiplicativeOperator.isEmpty()) { // 如果有待处理的乘法运算符
        if (!calculate(operand, pendingMultiplicativeOperator)) { // 如果计算失败
            abortOperation(); // 中止操作
            return; // 返回
        }
        display->setText(QString::number(factorSoFar)); // 将结果显示在显示屏上
    } else {
        factorSoFar = operand; // 否则,将操作数设置为结果
    }
​
    pendingMultiplicativeOperator = clickedOperator; // 更新待处理的乘法运算符为当前点击的运算符
    waitingForOperand = true; // 设置等待操作数的标志为真
}
//! [18]
​
//! [20]
void Calculator::equalClicked()
{
    double operand = display->text().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; // 否则,将操作数设置为结果
    }
​
    display->setText(QString::number(sumSoFar)); // 将结果显示在显示屏上
    sumSoFar = 0.0; // 重置求和结果
    waitingForOperand = true; // 设置等待操作数的标志为真
}
//! [22]
void Calculator::pointClicked()
{
    // 如果等待操作数,将显示屏文本设置为"0"
    if (waitingForOperand)
        display->setText("0");
    // 如果显示屏文本中不包含小数点,则在文本末尾添加一个小数点
    if (!display->text().contains('.'))
        display->setText(display->text() + tr("."));
    // 设置等待操作数标志为false
    waitingForOperand = false;
}
//! [22]
​
//! [24]
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);
}
//! [24]
​
//! [26]
void Calculator::backspaceClicked()
{
    // 如果等待操作数,直接返回
    if (waitingForOperand)
        return;
​
    QString text = display->text();
    // 移除文本末尾的一个字符
    text.chop(1);
    // 如果文本为空,则将其设置为"0",并将等待操作数标志设置为true
    if (text.isEmpty()) {
        text = "0";
        waitingForOperand = true;
    }
    // 将修改后的文本设置回显示屏
    display->setText(text);
}
//! [26]
​
//! [28]
void Calculator::clear()
{
    // 如果等待操作数,直接返回
    if (waitingForOperand)
        return;
​
    // 将显示屏文本设置为"0",并将等待操作数标志设置为true
    display->setText("0");
    waitingForOperand = true;
}
//! [28]
// Calculator类的成员函数clearAll(),用于清除计算器的所有状态
void Calculator::clearAll()
{
    sumSoFar = 0.0; // 将累加结果清零
    factorSoFar = 0.0; // 将乘除结果清零
    pendingAdditiveOperator.clear(); // 清空待处理的加法运算符
    pendingMultiplicativeOperator.clear(); // 清空待处理的乘除运算符
    display->setText("0"); // 将显示屏显示为"0"
    waitingForOperand = true; // 设置等待操作数的标志为true
}
​
// Calculator类的成员函数clearMemory(),用于清除内存中的值
void Calculator::clearMemory()
{
    sumInMemory = 0.0; // 将内存中的值清零
}
​
// Calculator类的成员函数readMemory(),用于读取内存中的值并显示在显示屏上
void Calculator::readMemory()
{
    display->setText(QString::number(sumInMemory)); // 将内存中的值转换为字符串并显示在显示屏上
    waitingForOperand = true; // 设置等待操作数的标志为true
}
​
// Calculator类的成员函数setMemory(),用于将显示屏上的值存入内存中
void Calculator::setMemory()
{
    equalClicked(); // 执行等号点击事件
    sumInMemory = display->text().toDouble(); // 将显示屏上的值转换为双精度浮点数并存入内存中
}
​
// Calculator类的成员函数addToMemory(),用于将显示屏上的值加到内存中的值上
void Calculator::addToMemory()
{
    equalClicked(); // 执行等号点击事件
    sumInMemory += display->text().toDouble(); // 将显示屏上的值转换为双精度浮点数并加到内存中的值上
}
​
// Calculator类的成员函数createButton(),用于创建一个按钮并将其与指定的成员函数连接起来
Button *Calculator::createButton(const QString &text, const char *member)
{
    Button *button = new Button(text); // 创建一个新的按钮
    connect(button, SIGNAL(clicked()), this, member); // 将按钮的点击事件与指定的成员函数连接起来
    return button; // 返回创建的按钮
}
​
// Calculator类的成员函数abortOperation(),用于中止当前的操作并将显示屏显示为"####"
void Calculator::abortOperation()
{
    clearAll(); // 调用clearAll()函数清除所有状态
    display->setText(tr("####")); // 将显示屏显示为"####"
}
​
// Calculator类的成员函数calculate(),用于根据给定的操作数和运算符进行计算
bool Calculator::calculate(double rightOperand, const QString &pendingOperator)
{
    if (pendingOperator == tr("+")) { // 如果待处理的运算符是加法
        sumSoFar += rightOperand; // 将右操作数加到累加结果上
    } else if (pendingOperator == tr("-")) { // 如果待处理的运算符是减法
        sumSoFar -= rightOperand; // 将右操作数从累加结果中减去
    } else if (pendingOperator == tr("\303\227")) { // 如果待处理的运算符是乘法
        factorSoFar *= rightOperand; // 将右操作数乘以乘除结果
    } else if (pendingOperator == tr("\303\267")) { // 如果待处理的运算符是除法
        if (rightOperand == 0.0) // 如果右操作数为0
            return false; // 返回false表示计算失败
        factorSoFar /= rightOperand; // 将右操作数从乘除结果中除以
    }
    return true; // 返回true表示计算成功
}
​
main.cpp
#include <QApplication> // 引入Qt框架的QApplication类,用于处理应用程序的事件循环和退出
​
#include "calculator.h" // 引入名为"calculator.h"的头文件,该文件定义了Calculator类
​
int main(int argc, char *argv[]) // 主函数,程序的入口点
{
    QApplication app(argc, argv); // 创建一个QApplication对象,用于管理应用程序的事件循环和退出
    Calculator calc; // 创建一个Calculator对象,用于显示计算器界面
    calc.show(); // 调用Calculator对象的show()方法,显示计算器界面
    return app.exec(); // 进入应用程序的事件循环,等待用户操作并处理事件
}
​
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值