南昌网站建设方案,网站建设需求分析班级,静态网站策划书,广州微信营销公司Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写#xff0c;所有平台无差别运行#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今#xff0c;Qt已被运用于超过70个行业、数千家企业#xff0c;支持数百万设备及应用。
本文将展示如何使用…Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写所有平台无差别运行更提供了几乎所有开发过程中需要用到的工具。如今Qt已被运用于超过70个行业、数千家企业支持数百万设备及应用。
本文将展示如何使用信号和槽来实现计算器小部件的功能以及如何使用QGridLayout在网格中放置子小部件。在上文中点击这里回顾为大家介绍了实现计算器的Calculator类定义本文将主要介绍Calculator类是如何实现的持续关注我们哦~
点击获取Qt Widget组件下载(Q技术交流166830288 计算器示例的屏幕截图
这个例子由两个类组成
Calculator是计算器小部件具有计算器的所有功能。Button是用于每个计算器按钮的小部件它派生自QToolButton。
我们将从回顾计算器开始然后再看看按钮。
Calculator类实现
Calculator::Calculator(QWidget *parent)
: QWidget(parent), sumInMemory(0.0), sumSoFar(0.0)
, factorSoFar(0.0), waitingForOperand(true)
{
在构造函数中初始化计算器的状态。pendingAdditiveOperator和pendingMultiplicativeOperator变量不需要显式初始化因为QString构造函数将它们初始化为空字符串。也可以直接在header文件中初始化这些变量这称为成员初始化避免了长初始化列表。
display new QLineEdit(0);
display-setReadOnly(true);
display-setAlignment(Qt::AlignRight);
display-setMaxLength(15);QFont font display-font();
font.setPointSize(font.pointSize() 8);
display-setFont(font);
我们创建了表示计算器显示的QLineEdit 并设置了它的一些属性特别地我们将其设置为只读。
我们还将显示器的字体放大了8个点。
for (int i 0; i NumDigitButtons; i)
digitButtons[i] createButton(QString::number(i), Calculator::digitClicked);Button *pointButton createButton(tr(.), Calculator::pointClicked);
Button *changeSignButton createButton(tr(\302\261), Calculator::changeSignClicked);Button *backspaceButton createButton(tr(Backspace), Calculator::backspaceClicked);
Button *clearButton createButton(tr(Clear), Calculator::clear);
Button *clearAllButton createButton(tr(Clear All), Calculator::clearAll);Button *clearMemoryButton createButton(tr(MC), Calculator::clearMemory);
Button *readMemoryButton createButton(tr(MR), Calculator::readMemory);
Button *setMemoryButton createButton(tr(MS), Calculator::setMemory);
Button *addToMemoryButton createButton(tr(M), Calculator::addToMemory);Button *divisionButton createButton(tr(\303\267), Calculator::multiplicativeOperatorClicked);
Button *timesButton createButton(tr(\303\227), Calculator::multiplicativeOperatorClicked);
Button *minusButton createButton(tr(-), Calculator::additiveOperatorClicked);
Button *plusButton createButton(tr(), Calculator::additiveOperatorClicked);Button *squareRootButton createButton(tr(Sqrt), Calculator::unaryOperatorClicked);
Button *powerButton createButton(tr(x\302\262), Calculator::unaryOperatorClicked);
Button *reciprocalButton createButton(tr(1/x), Calculator::unaryOperatorClicked);
Button *equalButton createButton(tr(), Calculator::equalClicked);
对于每个按钮我们使用适当的文本标签和连接到按钮的插槽调用私有createButton()函数。
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);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));
}
布局由单个QGridLayout处理QLayout::setSizeConstraint()调用确保Calculator小部件始终显示为其最佳大小(其大小提示)从而防止用户调整计算器的大小大小提示由子小部件的大小和大小策略决定。
大多数子部件只占用网格布局中的一个单元格对于这些我们只需要将一行和一列传递给QGridLayout::addWidget()。display、backspaceButton、clearButton和clearAllButton小部件占用多于一列对于这些我们还必须船体一个行空间和一个列空间。
void Calculator::digitClicked()
{
Button *clickedButton qobject_castButton *(sender());
int digitValue clickedButton-text().toInt();
if (display-text() 0 digitValue 0.0)
return;if (waitingForOperand) {
display-clear();
waitingForOperand false;
}
display-setText(display-text() QString::number(digitValue));
}
按下计算器的数字按钮时将发出按钮的clicked()信号该信号将触发digitClicked()插槽。
首先我们先使用QObject::sender()找出哪个按钮发送了信号这个函数以QObject指针的形式返回发送方。因为我们知道发送方是一个Button对象所以可以安全地强制转换QObject。本来可以使用C风格的强制转换或c static_cast()但作为一种防御性编程技术我们使用qobject_cast()。这样做的好处是如果对象的类型错误则返回空指针。空指针导致的崩溃比不安全强制转换导致的崩溃更容易诊断。有了按钮后我们使用QToolButton::text()提取操作符。
插槽需要特别考虑两种情况如果显示包含“0”而用户点击了“0”按钮那么显示“00”将是愚蠢的。如果计算器处于等待新操作数的状态新数字就是新操作数的第一位在这种情况下必须首先清除先前计算的任何结果。
最后我们将新数字附加到显示的值后面。
void Calculator::unaryOperatorClicked()
{
Button *clickedButton qobject_castButton *(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;
}
每当单击一个一元操作符按钮时就调用unaryOperatorClicked()插槽再次使用QObject::sender()获取指向被单击按钮的指针。操作符从按钮的文本中提取并存储在clickoperator中操作数从display中获得。
然后我们执行这个操作如果Sqrt应用于负数或1/x到零调用abortOperation()。如果一切顺利我们将在行编辑中显示操作的结果并将waitingForOperand设置为true。这确保了如果用户键入一个新数字该数字将被视为一个新的操作数而不是附加到当前值。
void Calculator::additiveOperatorClicked()
{
Button *clickedButton qobject_castButton *(sender());
if (!clickedButton)
return;
QString clickedOperator clickedButton-text();
double operand display-text().toDouble();
当用户单击或-按钮时调用additiveOperatorClicked()槽。
在对单击的操作符进行实际操作之前我们必须处理所有挂起的操作。从乘法运算符开始因为它们的优先级高于加法运算符
if (!pendingMultiplicativeOperator.isEmpty()) {
if (!calculate(operand, pendingMultiplicativeOperator)) {
abortOperation();
return;
}
display-setText(QString::number(factorSoFar));
operand factorSoFar;
factorSoFar 0.0;
pendingMultiplicativeOperator.clear();
}
如果之前已经单击了x或÷而没有随后单击则显示中的当前值是x或÷操作符的右操作数我们最终可以执行该操作并更新显示。
if (!pendingAdditiveOperator.isEmpty()) {
if (!calculate(operand, pendingAdditiveOperator)) {
abortOperation();
return;
}
display-setText(QString::number(sumSoFar));
} else {
sumSoFar operand;
}
如果前面已经单击了或-则sumSoFar是左操作数而显示的当前值是操作符的右操作数。如果没有挂起的加法运算符则简单地将sumSoFar设置为显示中的文本。
pendingAdditiveOperator clickedOperator;
waitingForOperand true;
}
最后我们可以处理刚刚点击的操作符。由于还没有右操作数所以将单击的操作符存储在pendingAdditiveOperator变量中。稍后当有一个右操作数而左操作数为sumSoFar时将应用该操作。
void Calculator::multiplicativeOperatorClicked()
{
Button *clickedButton qobject_castButton *(sender());
if (!clickedButton)
return;
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;
}
multiplicativeOperatorClicked()插槽类似于additiveOperatorClicked()不需要担心挂起的加法运算符因为乘法运算符优先于加法运算符。
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;
}
与additiveOperatorClicked()一样我们首先处理任何挂起的乘法和加法操作符然后显示sumSoFar并将变量重置为零。必须将变量重置为零以避免对值进行两次计数。
void Calculator::pointClicked()
{
if (waitingForOperand)
display-setText(0);
if (!display-text().contains(.))
display-setText(display-text() tr(.));
waitingForOperand false;
}
pointClicked()槽向显示的内容添加一个小数点。
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);
}
changeSignClicked()槽改变显示值的符号如果当前值为正则在前面加一个负号如果当前值为负则从值中删除第一个字符(负号)。
void Calculator::backspaceClicked()
{
if (waitingForOperand)
return;QString text display-text();
text.chop(1);
if (text.isEmpty()) {
text 0;
waitingForOperand true;
}
display-setText(text);
}
backspaceclick()将删除显示中最右边的字符如果得到一个空字符串则显示“0”并将waitingForOperand设置为true。
void Calculator::clear()
{
if (waitingForOperand)
return;display-setText(0);
waitingForOperand true;
}
clear()槽将当前操作数重置为零这相当于按退格键多次擦除整个操作数。
void Calculator::clearAll()
{
sumSoFar 0.0;
factorSoFar 0.0;
pendingAdditiveOperator.clear();
pendingMultiplicativeOperator.clear();
display-setText(0);
waitingForOperand true;
}
clearAll()槽将计算器重置为初始状态。
void Calculator::clearMemory()
{
sumInMemory 0.0;
}void Calculator::readMemory()
{
display-setText(QString::number(sumInMemory));
waitingForOperand true;
}void Calculator::setMemory()
{
equalClicked();
sumInMemory display-text().toDouble();
}void Calculator::addToMemory()
{
equalClicked();
sumInMemory display-text().toDouble();
}
clearMemory()插槽擦除保存在内存中的总和readMemory()将总和显示为操作数setMemory()将内存中的总和替换为当前的总和addtommemory()将当前值添加到内存中的值。对于setMemory()和addtommemory()我们首先调用equalClicked()来更新sumSoFar和显示中的值。
templatetypename PointerToMemberFunction
Button *Calculator::createButton(const QString text, const PointerToMemberFunction member)
{
Button *button new Button(text);
connect(button, Button::clicked, this, member);
return button;
}
私有的createButton()函数从构造函数中被调用来创建计算器按钮。
void Calculator::abortOperation()
{
clearAll();
display-setText(tr(####));
}
私有的abortOperation()函数在计算失败时被调用重置计算器状态显示“####”。
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)
return false;
factorSoFar / rightOperand;
}
return true;
}
私有的calculate()函数执行一个二进制操作右操作数由rightOperand给出。对于加法操作符左操作数为sumSoFar;对于乘法运算符左操作数是factorSoFar。如果发生除零函数返回false。
Qt Widget组件推荐
QtitanRibbon - Ribbon UI组件是一款遵循Microsoft Ribbon UI Paradigm for Qt技术的Ribbon UI组件QtitanRibbon致力于为Windows、Linux和Mac OS X提供功能完整的Ribbon组件。QtitanChart - Qt类图表组件是一个C 库代表一组控件这些控件使您可以快速地为应用程序提供漂亮而丰富的图表。QtitanDataGrid - Qt网格组件提供了一套完整的标准 QTableView 函数和传统组件无法实现的独特功能。使您能够将不同来源的各类数据加载到一个快速、灵活且功能强大的可编辑网格中支持排序、分组、报告、创建带状列、拖放按钮和许多其他方便的功能。QtitanDocking允许您像 Visual Studio 一样为您的伟大应用程序配备可停靠面板和可停靠工具栏。黑色、白色、蓝色调色板完全支持 Visual Studio 2019 主题