[Qt]姿态显示仪

——————pro————————
QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
AttitudeDisplay.cpp \
main.cpp \
mainwindow.cpp

HEADERS += \
AttitudeDisplay.h \
mainwindow.h

FORMS += \
mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

———————-AttitudeDisplay.h————————-
#ifndef ATTITUDEDISPLAY_H
#define ATTITUDEDISPLAY_H

#include

class AttitudeDisplay : public QWidget {
Q_OBJECT
public:
explicit AttitudeDisplay(QWidget *parent = nullptr);

void setAttitude(double roll, double pitch, double yaw);

protected:
void paintEvent(QPaintEvent *event) override;

private:
double m_roll; // 滚转角 (Roll)
double m_pitch; // 俯仰角 (Pitch)
double m_yaw; // 偏航角 (Yaw)
};

#endif // ATTITUDEDISPLAY_H

——————————mainwindow.h—————————
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include
#include “AttitudeDisplay.h”

class MainWindow : public QMainWindow {
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();

private:
AttitudeDisplay *attitudeDisplay;
};

#endif // MAINWINDOW_H

————AttitudeDisplay.cpp——————————————-
#include “AttitudeDisplay.h”
#include
#include

AttitudeDisplay::AttitudeDisplay(QWidget *parent)
: QWidget(parent), m_roll(0), m_pitch(0), m_yaw(0) {
setMinimumSize(300, 300); // 设置最小尺寸
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // 允许自动调整大小
}

void AttitudeDisplay::setAttitude(double roll, double pitch, double yaw) {
m_roll = roll;
m_pitch = pitch;
m_yaw = yaw;
update(); // 触发重绘
}

void AttitudeDisplay::paintEvent(QPaintEvent *event) {
Q_UNUSED(event);

QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);

int centerX = width() / 2;
int centerY = height() / 2;
int radius = qMin(width(), height()) / 2 – 10;

// 绘制圆形背景
painter.setBrush(QColor(30, 30, 30));
painter.setPen(Qt::NoPen);
painter.drawEllipse(centerX – radius, centerY – radius, radius * 2, radius * 2);

// 绘制天空和地面(改为圆形分段显示)
painter.save();
painter.translate(centerX, centerY); // 移动坐标系统到圆心
painter.rotate(-m_roll); // 根据滚转角旋转地平线

// 绘制天空部分(上半圆)
painter.setBrush(QColor(100, 150, 255)); // 天空蓝
painter.setPen(Qt::NoPen);
painter.drawPie(-radius, -radius, radius * 2, radius * 2, 90 * 16, 180 * 16); // 绘制上半圆

// 绘制地面部分(下半圆)
painter.setBrush(QColor(180, 100, 50)); // 地面棕
painter.setPen(Qt::NoPen);
painter.drawPie(-radius, -radius, radius * 2, radius * 2, -90 * 16, 180 * 16); // 绘制下半圆

painter.restore();

// 绘制俯仰线
painter.setPen(QPen(Qt::white, 2));
int pitchOffset = static_cast(m_pitch * radius / 90.0);
painter.drawLine(centerX – radius, centerY + pitchOffset, centerX + radius, centerY + pitchOffset);

// 绘制刻度
for (int i = -90; i <= 90; i += 15) { int offset = static_cast(i * radius / 90.0);
painter.drawLine(centerX – radius / 4, centerY + offset, centerX + radius / 4, centerY + offset);
if (i != 0) {
painter.drawText(QPointF(centerX + radius / 4 + 5, centerY + offset + 5), QString::number(i));
}
}

// 绘制指针
painter.setPen(QPen(Qt::yellow, 2));
painter.drawLine(centerX, centerY – radius, centerX, centerY + radius);

// 绘制中心指针
painter.setBrush(Qt::red);
painter.setPen(Qt::NoPen);
painter.drawEllipse(QPointF(centerX, centerY), 5, 5);

// 绘制仪表盘外圈
painter.setPen(QPen(Qt::white, 2));
painter.setBrush(Qt::NoBrush);
painter.drawEllipse(centerX – radius, centerY – radius, radius * 2, radius * 2);

// 绘制文字信息
painter.setPen(Qt::black);
painter.setFont(QFont(“Arial”, 12, QFont::Bold));
QString text = QString(“Roll: %1°\nPitch: %2°\nYaw: %3°”)
.arg(m_roll, 0, ‘f’, 1)
.arg(m_pitch, 0, ‘f’, 1)
.arg(m_yaw, 0, ‘f’, 1);
painter.drawText(centerX – radius + 15, centerY + radius + 0, text);
}
—————————main.cpp—————————
#include “mainwindow.h”
#include

int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

————————-mainwindow.cpp—————————–
#include “mainwindow.h”
#include
#include

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), attitudeDisplay(new AttitudeDisplay(this)) {
setWindowTitle(“圆形姿态仪”);
setMinimumSize(400, 400);

// 设置布局,将仪表盘放在中央
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
layout->addWidget(attitudeDisplay);
layout->setAlignment(attitudeDisplay, Qt::AlignCenter);

// 模拟姿态数据更新
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, [this]() {
static double roll = 0, pitch = 0, yaw = 0;
roll += 1.0;
pitch += 0.5;
yaw += 0.3;

if (roll > 180) roll = -180;
if (pitch > 90) pitch = -90;
if (yaw > 360) yaw -= 360;

attitudeDisplay->setAttitude(roll, pitch, yaw);
});
timer->start(50); // 每 50 毫秒更新一次
}

MainWindow::~MainWindow() {
delete attitudeDisplay;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注