Qt 信号与槽——温度转换器
目标
演示 Qt 核心机制「信号与槽」:一个摄氏/华氏温度互转的小工具,输入即实时转换。
完整代码
main.cpp
#include <QApplication>
#include "TemperatureConverter.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
TemperatureConverter window;
window.setWindowTitle("温度转换器 - Qt 示例");
window.resize(350, 150);
window.show();
return app.exec();
}
TemperatureConverter.h
#ifndef TEMPERATURECONVERTER_H
#define TEMPERATURECONVERTER_H
#include <QWidget>
#include <QLineEdit>
#include <QLabel>
class TemperatureConverter : public QWidget {
Q_OBJECT
public:
explicit TemperatureConverter(QWidget *parent = nullptr);
private slots:
void onCelsiusChanged(const QString &text);
void onFahrenheitChanged(const QString &text);
private:
QLineEdit *celsiusInput;
QLineEdit *fahrenheitInput;
QLabel *statusLabel;
bool updating = false; // 防止信号循环
};
#endif
TemperatureConverter.cpp
#include "TemperatureConverter.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QDoubleValidator>
TemperatureConverter::TemperatureConverter(QWidget *parent)
: QWidget(parent) {
auto *validator = new QDoubleValidator(-273.15, 10000, 2, this);
celsiusInput = new QLineEdit(this);
celsiusInput->setPlaceholderText("摄氏度");
celsiusInput->setValidator(validator);
fahrenheitInput = new QLineEdit(this);
fahrenheitInput->setPlaceholderText("华氏度");
fahrenheitInput->setValidator(validator);
statusLabel = new QLabel("请在上面输入温度", this);
auto *mainLayout = new QVBoxLayout(this);
auto *inputLayout = new QHBoxLayout();
inputLayout->addWidget(new QLabel("°C:"));
inputLayout->addWidget(celsiusInput);
inputLayout->addWidget(new QLabel("°F:"));
inputLayout->addWidget(fahrenheitInput);
mainLayout->addLayout(inputLayout);
mainLayout->addWidget(statusLabel);
connect(celsiusInput, &QLineEdit::textChanged,
this, &TemperatureConverter::onCelsiusChanged);
connect(fahrenheitInput, &QLineEdit::textChanged,
this, &TemperatureConverter::onFahrenheitChanged);
}
void TemperatureConverter::onCelsiusChanged(const QString &text) {
if (updating) return;
bool ok;
double c = text.toDouble(&ok);
if (!ok || text.isEmpty()) {
statusLabel->setText("请输入有效数字");
return;
}
double f = c * 9.0 / 5.0 + 32;
updating = true;
fahrenheitInput->setText(QString::number(f, 'f', 2));
updating = false;
statusLabel->setText(QString("%1°C = %2°F").arg(c).arg(f, 0, 'f', 2));
}
void TemperatureConverter::onFahrenheitChanged(const QString &text) {
if (updating) return;
bool ok;
double f = text.toDouble(&ok);
if (!ok || text.isEmpty()) {
statusLabel->setText("请输入有效数字");
return;
}
double c = (f - 32) * 5.0 / 9.0;
updating = true;
celsiusInput->setText(QString::number(c, 'f', 2));
updating = false;
statusLabel->setText(QString("%1°F = %2°C").arg(f).arg(c, 0, 'f', 2));
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(TemperatureConverter LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON) # 关键:自动处理 Q_OBJECT 宏
find_package(Qt6 REQUIRED COMPONENTS Widgets)
add_executable(${PROJECT_NAME}
main.cpp
TemperatureConverter.cpp
)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Widgets)
运行步骤
mkdir build &
cmake ..
make -j$(nproc)
./TemperatureConverter
关键点
- 信号与槽是 Qt 最核心的设计:
connect(sender, SIGNAL, receiver, SLOT)
CMAKE_AUTOMOC ON 自动处理 Q_OBJECT 宏,必须开启
updating 标志防止两个输入框互相触发形成无限循环
QDoubleValidator 限制输入为合法数值