#include "customgraphics.h" #include #include #include #include #include #include #include #include #include #include #include #include #include // 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 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()); }