|
- #include "customgraphics.h"
- #include <QPainter>
- #include <QGraphicsSceneMouseEvent>
- #include <QMenu>
- #include <QGraphicsScene>
- #include <QColorDialog>
- #include <QInputDialog>
- #include <QDialog>
- #include <QLabel>
- #include <QSpinBox>
- #include <QHBoxLayout>
- #include <QVBoxLayout>
- #include <QPushButton>
- #include <QGraphicsView>
-
- // HmiComponent 基类实现
- HmiComponent::HmiComponent(QGraphicsItem *parent) : QGraphicsObject(parent)
- {
- setFlag(QGraphicsItem::ItemIsMovable, true);
- setFlag(QGraphicsItem::ItemIsSelectable, true);
- setAcceptHoverEvents(true);
- }
-
- void HmiComponent::setColor(const QColor& color) {
- if (m_color != color) {
- m_color = color;
- update();
- }
- }
-
- QColor HmiComponent::color() const {
- return m_color;
- }
-
- void HmiComponent::setComponentName(const QString& name) {
- m_componentName = name;
- }
-
- QString HmiComponent::componentName() const {
- return m_componentName;
- }
-
- void HmiComponent::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
- {
- Q_UNUSED(option);
- Q_UNUSED(widget);
- painter->setRenderHint(QPainter::Antialiasing);
-
- paintShape(painter);
-
- if (isSelected()) {
- painter->setBrush(Qt::NoBrush);
- painter->setPen(QPen(Qt::darkRed, 2, Qt::DashLine));
- painter->drawRect(boundingRect());
- }
- }
-
- void HmiComponent::setAddress(int address)
- {
- if (m_address != address) {
- m_address = address;
- update();
- }
- }
-
- int HmiComponent::address() const
- {
- return m_address;
- }
-
- void HmiComponent::mousePressEvent(QGraphicsSceneMouseEvent *event)
- {
- // 右键不触发选中信号,留给 contextMenuEvent 处理
- if (event->button() == Qt::LeftButton) {
- emit selected(this);
- }
- QGraphicsObject::mousePressEvent(event);
- }
-
- void HmiComponent::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
- {
- scene()->clearSelection();
- setSelected(true);
- emit selected(this);
-
- QMenu menu;
-
- QAction *propertyAction = menu.addAction("属性");
- QAction *copyAction = menu.addAction("复制");
- QAction *deleteAction = menu.addAction("删除");
-
- connect(propertyAction, &QAction::triggered, this, [this]() {
- // 弹出属性对话框
- QDialog dialog;
- dialog.setWindowTitle("属性");
-
- QLabel* addressLabel = new QLabel("地址: ");
- QSpinBox* addressSpin = new QSpinBox();
- addressSpin->setRange(0, 4000);
- addressSpin->setValue(m_address); // 使用当前组件地址初始化
-
- // ON状态颜色设置
- QLabel* onColorLabel = new QLabel("ON状态外观: ");
- // 颜色显示,用QLabel设置背景色简单示范
- QLabel* onColorDisplay = new QLabel;
- onColorDisplay->setFixedSize(40, 20);
- onColorDisplay->setAutoFillBackground(true);
- QPalette onPal = onColorDisplay->palette();
- onPal.setColor(QPalette::Window, m_onColor);
- onColorDisplay->setPalette(onPal);
- onColorDisplay->setFrameShape(QFrame::Box);
-
- QPushButton* onColorBtn = new QPushButton("选择颜色");
-
- // OFF状态颜色设置
- QLabel* offColorLabel = new QLabel("OFF状态外观: ");
- QLabel* offColorDisplay = new QLabel;
- offColorDisplay->setFixedSize(40, 20);
- offColorDisplay->setAutoFillBackground(true);
- QPalette offPal = offColorDisplay->palette();
- offPal.setColor(QPalette::Window, m_offColor);
- offColorDisplay->setPalette(offPal);
- offColorDisplay->setFrameShape(QFrame::Box);
-
- QPushButton* offColorBtn = new QPushButton("选择颜色");
-
- QObject::connect(offColorBtn, &QPushButton::clicked, [&]() {
- QColor color = QColorDialog::getColor(m_offColor, nullptr, "选择 OFF 状态颜色");
- if (color.isValid()) {
- m_offColor = color;
- QPalette pal = offColorDisplay->palette();
- pal.setColor(QPalette::Window, color);
- offColorDisplay->setPalette(pal);
- offColorDisplay->update();
- setColor(color); // 默认显示OFF状态颜色
- }
- });
-
- // 地址布局
- QHBoxLayout* addressLayout = new QHBoxLayout();
- addressLayout->addWidget(addressLabel);
- addressLayout->addWidget(addressSpin);
-
- // ON颜色布局
- QHBoxLayout* onColorLayout = new QHBoxLayout();
- onColorLayout->addWidget(onColorLabel);
- onColorLayout->addWidget(onColorDisplay);
- onColorLayout->addWidget(onColorBtn);
-
- // OFF颜色布局
- QHBoxLayout* offColorLayout = new QHBoxLayout();
- offColorLayout->addWidget(offColorLabel);
- offColorLayout->addWidget(offColorDisplay);
- offColorLayout->addWidget(offColorBtn);
-
- // 确定/取消按钮
- QPushButton* okBtn = new QPushButton("确定");
- QPushButton* cancelBtn = new QPushButton("取消");
- QHBoxLayout* btnLayout = new QHBoxLayout();
- btnLayout->addStretch();
- btnLayout->addWidget(okBtn);
- btnLayout->addWidget(cancelBtn);
-
- // 颜色选择按钮点击槽
- QObject::connect(onColorBtn, &QPushButton::clicked, [&]() {
- QColor color = QColorDialog::getColor(m_onColor, nullptr, "选择 ON 状态颜色");
- if (color.isValid()) {
- m_onColor = color;
- QPalette pal = onColorDisplay->palette();
- pal.setColor(QPalette::Window, color);
- onColorDisplay->setPalette(pal);
- onColorDisplay->update();
- }
- });
-
- QVBoxLayout* mainLayout = new QVBoxLayout();
- mainLayout->addLayout(addressLayout);
- mainLayout->addLayout(onColorLayout);
- mainLayout->addLayout(offColorLayout);
- mainLayout->addLayout(btnLayout);
-
- dialog.setLayout(mainLayout);
-
- // 关闭逻辑
- QObject::connect(okBtn, &QPushButton::clicked, [&]() {
- // 保存地址
- int newAddress = addressSpin->value();
- setAddress(newAddress);
-
- // 已经在onColorBtn / offColorBtn中修改了m_onColor / m_offColor,需要触发界面更新
- update();
- dialog.accept();
- });
- QObject::connect(cancelBtn, &QPushButton::clicked, &dialog, &QDialog::reject);
-
- dialog.exec();
- });
-
- connect(copyAction, &QAction::triggered, this, [this]() {
- emit copyRequested(this);
- });
-
- connect(deleteAction, &QAction::triggered, this, [this]() {
- emit deleteRequested(this);
- });
-
- menu.exec(event->screenPos());
- }
-
- void HmiComponent::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
- {
- if (!(flags() & QGraphicsItem::ItemIsMovable)) {
- // 如果项不可移动,直接调用基类处理
- QGraphicsObject::mouseMoveEvent(event);
- return;
- }
-
- // 计算拖动后的位置
- QPointF delta = event->scenePos() - event->lastScenePos();
- QPointF newPos = pos() + delta;
-
- // 获取视图(假设只有1个视图)
- QList<QGraphicsView*> views = scene()->views();
- if (views.isEmpty()) {
- // 没有视图则默认处理
- QGraphicsObject::mouseMoveEvent(event);
- return;
- }
- QGraphicsView* view = views.first();
-
- // 获取视口矩形(像素坐标)
- QRect viewportRect = view->viewport()->rect();
-
- // 将视口矩形映射到场景坐标
- QPointF topLeftScene = view->mapToScene(viewportRect.topLeft());
- QPointF bottomRightScene = view->mapToScene(viewportRect.bottomRight());
- QRectF visibleSceneRect(topLeftScene, bottomRightScene);
-
- // 组件的边界矩形(局部坐标)
- QRectF bounds = boundingRect();
-
- // 计算移动后组件边界矩形(在场景坐标)
- QRectF newBounds = bounds.translated(newPos);
-
- // 限制组件边界必须完全在视图可见区域内
- qreal limitedX = newPos.x();
- qreal limitedY = newPos.y();
-
- if (newBounds.left() < visibleSceneRect.left())
- limitedX += visibleSceneRect.left() - newBounds.left();
- if (newBounds.top() < visibleSceneRect.top())
- limitedY += visibleSceneRect.top() - newBounds.top();
- if (newBounds.right() > visibleSceneRect.right())
- limitedX -= newBounds.right() - visibleSceneRect.right();
- if (newBounds.bottom() > visibleSceneRect.bottom())
- limitedY -= newBounds.bottom() - visibleSceneRect.bottom();
-
- setPos(QPointF(limitedX, limitedY));
- event->accept();
- }
-
-
- void HmiComponent::setOnColor(const QColor& color) {
- m_onColor = color;
- }
-
- void HmiComponent::setOffColor(const QColor& color) {
- m_offColor = color;
- setColor(color); // 默认展示 OFF 状态颜色
- }
-
- QColor HmiComponent::onColor() const {
- return m_onColor;
- }
-
- QColor HmiComponent::offColor() const {
- return m_offColor;
- }
-
-
- HmiButton::HmiButton(QGraphicsItem *parent) : HmiComponent(parent)
- {
- m_color = Qt::gray;
- m_offColor = m_color; // OFF状态颜色设为默认颜色
- m_onColor = Qt::green; // ON状态颜色为绿色
- m_componentName = "Button";
- setColor(m_offColor); // 当前显示OFF颜色
- }
-
- QRectF HmiButton::boundingRect() const
- {
- return QRectF(0, 0, 65, 30);
- }
-
- void HmiButton::paintShape(QPainter *painter)
- {
- painter->setPen(Qt::NoPen);
- painter->setBrush(m_color);
- painter->drawRect(boundingRect());
- }
-
- HmiIndicator::HmiIndicator(QGraphicsItem *parent) : HmiComponent(parent)
- {
- m_color = Qt::red;
- m_offColor = m_color; // OFF状态颜色设为默认颜色
- m_onColor = Qt::green; // ON状态颜色为绿色
- m_componentName = "Indicator";
- setColor(m_offColor); // 当前显示OFF颜色
- }
-
- QRectF HmiIndicator::boundingRect() const
- {
- return QRectF(0, 0, 30, 30);
- }
-
- void HmiIndicator::paintShape(QPainter *painter)
- {
- painter->setPen(Qt::NoPen);
- painter->setBrush(m_color);
- painter->drawEllipse(boundingRect());
- }
|