面向对象程序设计__Task6_Calculator1.6.2

The 4th part of the Calculator program _ Interface

题目链接:第六次作业(计算器第四步)
github链接:Calculator_1.6.2 第六次作业
工具:Qt Creator 5.6.0

讲道理好吧,终于有界面啦= =!!!还是先来说说上次的作业。第五次作业在完成之后各种缝缝补补(版本更迭!1.5.xxx),最大的问题就是偷懒的Scan.cpp里面读取表达式时遗留下来的坑。虽然之后线下自己做了修改,加上了些预处理,但是看到第五次作业结果惨不忍睹的正确率时,内心还是有点小崩溃的(早知道早点改了),另外Printer类的输出方法还是有点乱,各种调用有点理不清。

然后就是这次的作业,界面!version 1.6.2!

一开始是QT和MFC的选择,在各种百度之后,想想就短短几天,果断选择了简单方便的QT,虽然可能MFC不失为更好的选择...

接下来就是Qt的各种尝试历程

Part 1

在经过简单的Qt学习之后,就直接开始征程了。一开始,当然是恬不知耻(hhh~)的开启ui设计模式,各种拖动框框,东拼西凑,欧啦,一个纸面上的界面就完成啦!

接着只要对每一个按钮设置槽,再将第五次作业的各种类导入,当当当当,一个简单的计算器v1.6.0,Over~

Part 2

看完Part 1简单的两段话,是不是觉得步骤太过简单了= =,别急,下面就是不用ui文件这种粗暴的做法,而是代码的实现。

Calculator.h

class Calculator : public QDialog
{
    Q_OBJECT

public:
    explicit Calculator(QWidget *parent = 0);
    ~Calculator();
protected:
    FileOperation *fo;
    Printer *pr;

    QLineEdit *editLine;     // 输入框
    QLabel *answerLine;      // 结果框
    // 按钮
    QPushButton *button_0, *button_1, *button_2, *button_3, *button_4, *button_5, *button_6
        , *button_7, *button_8, *button_9;
    QPushButton *button_point, *button_add, *button_sub, *button_mul, *button_div, *button_equal;
    QPushButton *button_lBracket, *button_rBracket;
    QPushButton *button_file, *button_clear, *button_del;
    string inputExp;
    QString showAnswer;
    double cacheAnswer;
    bool equalFlag;     // 是否已按下等号
private:
    Ui::Calculator *ui;
private slots:
    void button_0_clicked();     // 槽
    void button_1_clicked();
    void button_2_clicked();
    void button_3_clicked();
    void button_4_clicked();
    void button_5_clicked();
    void button_6_clicked();
    void button_7_clicked();
    void button_8_clicked();
    void button_9_clicked();
    void button_point_clicked();
    void button_add_clicked();
    void button_sub_clicked();
    void button_mul_clicked();
    void button_div_clicked();
    void button_equal_clicked();
    void button_file_clicked();
    void button_clear_clicked();
    void button_del_clicked();
    void button_lBracket_clicked();
    void button_rBracket_clicked();
};

Calculator.cpp

Calculator::Calculator(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Calculator)
{
    ui->setupUi(this);
    this->setWindowTitle(QStringLiteral("计算器"));
    this->setFixedSize(300, 230);
    this->setStyleSheet("background-image:url(D:/Qt_Creator_Projects/Calculator_2/bg_6.jpg)");

    fo = NULL;
    pr = new Printer();

    cacheAnswer = 0;
    equalFlag = false;
    editLine = new QLineEdit("0");
    ...
    button_add->setFixedSize(51, 56);
    button_file->setToolTip(QStringLiteral("文件读写操作"));
    button_clear->setFixedSize(51, 56);

    QGridLayout *mainLayout = new QGridLayout(this);
    mainLayout->addWidget(editLine, 0, 0, 1, 5);     // 布局
	...

    connect(button_0, SIGNAL(clicked()), this, SLOT(button_0_clicked()));
    ...

    setLayout(mainLayout);

}

void Calculator::button_0_clicked()
{
   if (editLine->text() == "0" || equalFlag)
   {
       if (equalFlag)
       {
           equalFlag = false;
       }
       editLine->setText(QString('0'));
   }
   else
   {
       editLine->setText(editLine->text() + QString('0'));
   }
}

...

void Calculator::button_add_clicked()
{
    if (equalFlag)
    {
        equalFlag = false;
        editLine->setText(showAnswer);
    }
    editLine->setText(editLine->text() + QString('+'));
}

...

void Calculator::button_equal_clicked()
{
    if (equalFlag)
    {
        editLine->setText(QString('0'));
    }
    else
    {
        answerLine->setText(editLine->text() + QString(" = "));
        editLine->setText(editLine->text() + QString('='));
        inputExp = editLine->text().toStdString();
        cacheAnswer = pr->printResult(inputExp);
        showAnswer = QString::number(cacheAnswer, 10, 12);     // 默认至多保留12位小数
        int pointIndex = showAnswer.indexOf(".");
        bool afterPointNonZeroInt = false;     // 小数点后是否存在非零整数
        int afterPointFirstNonZeroIntIndex = pointIndex;
        for (int i = pointIndex; i < showAnswer.length(); i++)
        {
            if (showAnswer[i] >= '1' && showAnswer[i] <= '9')
            {
                afterPointNonZeroInt = true;
                afterPointFirstNonZeroIntIndex = i;
                break;
            }
        }
        int precision = showAnswer.indexOf("0", afterPointFirstNonZeroIntIndex);
        if (precision != -1 && precision > pointIndex)
        {
            if (!afterPointNonZeroInt)     // 若为整数(.000....),则截取至(不含)小数点
            {
                showAnswer = showAnswer.left(pointIndex);
            }
            else
            {
                showAnswer = showAnswer.left(precision);
            }
        }
        answerLine->setText(answerLine->text() + showAnswer);
    }
    equalFlag = true;
}

void Calculator::button_file_clicked()
{
    fo = new FileOperation();
    fo->show();
}

void Calculator::button_clear_clicked()
{
    editLine->setText(QString('0'));
    answerLine->setText(QString('0'));
}

void Calculator::button_del_clicked()
{
    if (equalFlag)
    {
        equalFlag = false;
        editLine->setText(QString('0'));
        answerLine->setText(QString('0'));
    }
    else
    {
        QString qs = editLine->text();
        int len = qs.length();
        if (len == 1)
        {
            editLine->setText(QString('0'));
        }
        else
        {
            editLine->setText(qs.left(len - 1));
        }
    }
}

眼花缭乱有没有!想砸了它有没有!要多少个按钮就定义了多少个PushButton和槽!

不过程序还是不难理解的。按下按钮后对应显示区显示对应符号,在deadline更新到5号之后,多出来的两天也让我有时间将自己的想法多修修补补,比如,"="按下后,在v1.6.1中是固定显示3位小数的,包括"x.000","x.xxx(xxx...万分位开始被截断)"的情况,后来在v1.6.2中改进,寻找最佳的精度(默认至多不超过12位小数)并显示到显示区。再如,v1.6.2比起v1.6.1也加上了图标、背景等等。

Part 3

在Calculator中,File按钮对应的是打开文件操作窗口,即第五次作业所要求的文件读写,该部分写在FileOperation类中

FileOperation.h

class FileOperation : public QDialog
{
    Q_OBJECT
public:
    explicit FileOperation(QWidget *parent = 0);
    ~FileOperation();
protected:
    Printer *pr;
    QLabel *input_1;
    QLabel *input_2;
    QLineEdit *inputAddrLine;
    QLineEdit *outputAddrLine;
    QPushButton *findAddr_1;
    QPushButton *findAddr_2;
    QPushButton *finish;
    QPushButton *cancel;
    string inputAddr;
    string outputAddr;
signals:
    void clicked();
private slots:
    void findAddr_1_clicked();
    void findAddr_2_clicked();
    void finish_clicked();
    void cancel_clicked();
};

FileOperation.cpp

FileOperation::FileOperation(QWidget *parent) :
    QDialog(parent)
{
    this->setWindowTitle(QStringLiteral("文件读写操作"));
    this->setFixedSize(250, 150);
    this->setStyleSheet("background-image:url(D:/Qt_Creator_Projects/Calculator_2/bg_6.jpg)");

    pr = new Printer();
    input_1 = new QLabel("the input file address :");
	...
    findAddr_1->setToolTip(QStringLiteral("选择输入文件路径"));
    findAddr_2->setToolTip(QStringLiteral("选择输出文件路径"));
    QGridLayout *fileDialogLayout = new QGridLayout(this);
    fileDialogLayout->addWidget(input_1, 0, 0, 1, 4);
    ...

    connect(findAddr_1, SIGNAL(clicked()), this, SLOT(findAddr_1_clicked()));
    ...

    setWindowFlags(Qt::WindowStaysOnTopHint);
    setLayout(fileDialogLayout);
}

void FileOperation::findAddr_1_clicked()
{
    QString fil = QFileDialog::getOpenFileName(this, tr("Open txt"), ".", tr("txt Files(*.txt)"));
    inputAddrLine->setText(fil);
}

void FileOperation::findAddr_2_clicked()
{
    QString fil = QFileDialog::getOpenFileName(this, tr("Open txt"), ".", tr("txt Files(*.txt)"));
    outputAddrLine->setText(fil);
}

void FileOperation::finish_clicked()
{
    inputAddr = inputAddrLine->text().toStdString();
    outputAddr = outputAddrLine->text().toStdString();
    if (inputAddr.empty() || outputAddr.empty())
    {
        cout << "无效地址" << endl;
    }
    else
    {
        pr->printResult_f(inputAddr, outputAddr);
    }
    this->close();
}

void FileOperation::cancel_clicked()
{
    this->close();
}

一个简单的文件操作界面就完成了,v1.6.1测试时发现当有文件路径为空时,点finished程序会gg,在v1.6.2的时候也做了简单的处理

Part 4

那么再说说这次的Qt之旅上的问题,除了上面涉及的之外,还有一点就是乱码的问题,百度上众云纷说,最后发现Qt5的QStringLiteral(const char*),用来从“字符串常量”创建QString对象的宏,避免了各种编码转换带来的乱码的问题。

再来就是qmake这玩意,并不是很理解,但有一点是,有时候你在往你的项目中添加文件时,没有加到项目中(有点懵逼...),导致出现无法解析的外部符号的error,再重新qmake之后,瞬间构建成功了。

还有就是遗留的Printer类的调用问题,加上暂未实现的提示对话框...等等等等

Part 5

这次的Qt的学习收获还是挺大的,对一个新的东西先有了大概上的了解,再加之以应用,总是能学到很多,当蹦出来的红色的error一个个消散时,当总算蹦出一个稍微能看点的界面时,总还是很激动的。

另外,感觉这次稍微多出来了点的时间,让自己闲着没事时不时想到了一些想法也能加以尝试、实现,再一次在自己的代码上不断的改进,看着它一点一点的改善也是有点小happy,而改进之路上遇到的新的问题,更多依靠百度加以理解最后解决。

毕竟,一路百度,一路前行(2333...)

最后,就不贴参考博客什么的了(毕竟问题太多参考得也多...),只附上运行图:

计算器运行图_1

计算器运行图_2

计算器运行图_3

计算器运行图_4

The End

posted @ 2016-06-05 16:48  酒晓语令  阅读(274)  评论(8编辑  收藏  举报