0.面向对象的Qt编程
完全不适用任何面向对象技术,而只是利用Qt所提供的类创建对象,并调用对象的接口以满足用户的需求是可能的,但这样构建的应用程序其功能必然是十分有限的。
首先,Qt类保护成员中的诸多实现无法在类的外部被复用,Qt试图通过多态实现的很多机制,如事件处理,完全无法使用。
再次,Qt提供的信号和槽不可能满足用户所有的需求,自定义信号和槽需要面向对象技术。
最后,Qt设计师,Qt创造器等工具链都在以面向对象的方式使用Qt,反其道而行之不会有好结果。
1.通过面向对象的编程思想实现加法计算器
- 输入两个数字,按"="按钮显示计算结果
- 两个操作数必须都是合法的数字,拒绝结构任何非法字符
- 两个操作数必须全部合法,“=”按钮才被激活,否则禁用(不可以点击)
- 显示结果的空间只可查看不可修改,但支持复制到粘贴板
- 所有子窗口的大小和位置随主窗口的缩放自动调整至最佳
dialog.h:
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QLineEdit> // 行编辑控件
#include <QHBoxLayout> // 水平布局器
#include <QDoubleValidator> // 验证器
#pragma execution_character_set("utf-8")
QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE
class Dialog : public QDialog
{
Q_OBJECT
public slots:
// 使能等号按钮的槽操作数
void enableButton(void);
// 计算结果和显示的槽函数
void calcClicked(void);
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
private:
Ui::Dialog *ui;
QLineEdit* m_editX; // 左操作数
QLineEdit* m_editY; // 右操作数
QLineEdit* m_editZ; // 显示结果
QLabel* m_label; // "+"
QPushButton* m_button; // "="等号按钮
};
#endif // DIALOG_H
dialog.cpp:
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::Dialog)
{
ui->setupUi(this);
// 界面初始化
setWindowTitle("计算器");
// 左操作数,this即为当前父窗口指针
m_editX=new QLineEdit(this);
// 设置文本对齐方式:右对齐
m_editX->setAlignment(Qt::AlignRight);
// 设置数字验证器,只能输入数字形式内容
m_editX->setValidator(new QDoubleValidator(this));
// 右操作数
m_editY=new QLineEdit(this);
m_editY->setAlignment(Qt::AlignRight);
m_editY->setValidator(new QDoubleValidator(this));
// 显示结果控件
m_editZ=new QLineEdit(this);
m_editZ->setAlignment(Qt::AlignRight);
m_editZ->setReadOnly(true); // 设置只读
// "+"
m_label=new QLabel("+",this);
// "="
m_button=new QPushButton("=",this);
m_button->setEnabled(false);//设置禁用
// 创建布局器:自动调用每个控件的大小和位置
QHBoxLayout* layout = new QHBoxLayout(this);
// 按水平方向,依次将控件添加到布局器中
layout->addWidget(m_editX);
layout->addWidget(m_label);
layout->addWidget(m_editY);
layout->addWidget(m_button);
layout->addWidget(m_editZ);
// 设置布局器
setLayout(layout);
// 信号和槽函数连接
// 左右操作数文本改变时,发送信号textChanged()
connect(m_editX,SIGNAL(textChanged(QString)),
this,SLOT(enableButton(void)));
connect(m_editY,SIGNAL(textChanged(QString)),
this,SLOT(enableButton(void)));
// 点击按钮,发送信号clicked
connect(m_button,SIGNAL(clicked(void)),
this,SLOT(calcClicked(void)));
}
Dialog::~Dialog()
{
delete ui;
}
// 使能等号按钮的槽操作数
void Dialog::enableButton(void)
{
bool bXOk,bYOk;
// text():获取输入文本(QString)
// toDouble():QString转换为double,参数保存转换是否成功结果
m_editX->text().toDouble(&bXOk);
m_editY->text().toDouble(&bYOk);
// 当左右操作数都输入了有效数据,则使能等号按钮,否则设置禁用
m_button->setEnabled(bXOk && bYOk);
}
// 计算结果和显示的槽函数
void Dialog::calcClicked(void)
{
double res = m_editX->text().toDouble() +
m_editY->text().toDouble();
// number():将double转换为QString
QString str = QString::number(res);
// 显示字符串形式结果
m_editZ->setText(str);
}
2.案例:获取系统时间
要求:
- 使用面向对象的Qt编程技术创建获取时间窗口
- 点击按钮,通过自定义的槽函数获取时间并显示到标签
dialog.h:
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout> // 垂直布局器
#include <QTime> // 获取时间
#include <QDebug> // 打印调试
#pragma execution_character_set("utf-8")
QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
public slots:
void getTime(void); // 获取时间的槽函数
signals:
// 自定义信号函数,只需声明,不能写定义
void mySignal(const QString&);
private:
Ui::Dialog *ui;
QLabel* m_label; // 显示时间label
QPushButton* m_button; // 获取时间button
};
#endif // DIALOG_H
dialog.cpp:
#include "dialog.h"
#include "ui_dialog.h"
#include <QFont>
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::Dialog)
{
ui->setupUi(this);
// 初始化界面
// 显示时间标签控件
m_label = new QLabel(this);
// 设置label边框消息,凹陷面板
m_label->setFrameStyle(QFrame::Panel|QFrame::Sunken);
// 设置label文本对齐方式:水平/垂直居中
m_label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
// 设置label的字体大小
QFont font;
font.setPointSize(20);
m_label->setFont(font);
// 获取系统时间的按钮
m_button = new QPushButton("获取当前时间",this);
m_button->setFont(font);
// 创建垂直布局器
QVBoxLayout* layout=new QVBoxLayout(this);
layout->addWidget(m_label);
layout->addWidget(m_button);
// 设置布局器
setLayout(layout);
// 信号和槽函数连接
connect(m_button,SIGNAL(clicked()),
this,SLOT(getTime(void)));
// 通过自定义信号,触发label的setText函数执行
connect(this,SIGNAL(mySignal(QString)),
m_label,SLOT(setText(QString)));
}
Dialog::~Dialog()
{
delete ui;
}
// 获取系统时间的槽函数
void Dialog::getTime(void)
{
qDebug("getTime");
qDebug()<<"getTime";
// 获取当前系统时间
QTime time = QTime::currentTime();
// 将时间对象转换为字符串
QString str = time.toString("hh:mm:ss");
// 显示时间
//m_label->setText(str);
// emit:是Qt关键字,标记当前是发射信号
emit mySignal(str); // 发射信号
}