Qt 官方示例学习:calculator

1. SLOT() 作为参数传递

Button *Calculator::createButton(const QString &text, const char *member)
{
    Button *button = new Button(text);
    connect(button, SIGNAL(clicked()), this, member);
    return button;
}

Button *pointButton = createButton(tr("."), SLOT(pointClicked()));

// pointClicked() 声明为一个 private slots
void Calculator::pointClicked()
{
    if (waitingForOperand)
        display->setText("0");
    if (!display->text().contains('.'))
        display->setText(display->text() + tr("."));
    waitingForOperand = false;
}

可以看到,createButton 有一个参数 member,类型为 const char*。在调用时直接将 pointClicked()SLOT() 封装后传入。在 createButton() 内部,将 member 当做槽函数使用。

留意到 const char*SLOT(),不由猜想 SLOT() 的返回值为字符串。可以参考此处

2. 特殊符号可以由八进制数体现

在这里插入图片描述
如上图,特殊符号有除号、乘号、正负号、平方号,代码中使用如下表示方法:

Button *changeSignButton = createButton(tr("\302\261"), SLOT(changeSignClicked()));
Button *divisionButton = createButton(tr("\303\267"), SLOT(multiplicativeOperatorClicked()));
Button *timesButton = createButton(tr("\303\227"), SLOT(multiplicativeOperatorClicked()));
Button *powerButton = createButton(tr("x\302\262"), SLOT(unaryOperatorClicked()));

\302\261:\302(八进制) = 0xC2,\261 = 0xB1。0xC2B1 在十六进制转utf8中可以得到字符 ±
同理,\303\267 可以得出 ÷;\303\227 可以得出 ×;\302\262 可以得出 ²

这里八进制、十六进制,都是基于 utf8 编码,即将字符的 utf8 编码转为八进制数表示。

3. 通过转换获取信号发送者

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();
            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();
            return;
        }
        result = 1.0 / operand;
    }
    display->setText(QString::number(result));
    waitingForOperand = true;
}

已知发送信号为 Button,通过 Button *clickedButton = qobject_cast<Button *>(sender()); 强制转换得到发送信号的控件,再处理业务逻辑。

4. 计算顺序

在这个程序中,输入 1+2/3-4 结果等于 -2.33333 而非 -3,采用了乘除号优先级高于加减号的逻辑处理。


疑问?

这个 demo 的 Button 只有 new,并且没有指定 parent,也没有 delete,理论上讲应该存在内存泄漏。但是用工具 valgrind 貌似没有检测出来。

解答

代码中函数 Button *Calculator::createButton(const QString &text, const char *member) 的实现确实没有为 new Button 指定 parent。但是在布局中,所有创建出来的 Button 都被加入到了 QGridLayout 中,

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);
}

并且窗口也是用了这个布局setLayout(mainLayout);

另外,这个程序并没有重新实现析构函数,也就是用了默认析构函数。说明内存问题由 Qt 提供的机制统一管理(释放)。

参考此处可以明白,在调用 setLayoutaddWidget 这些操作时,子控件都会在函数内部被指定上 parent,因此程序关闭时,parent 会逐一释放 children 的内存,不会造成内存泄漏。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值