#include "hmicontrolitem.h" #include #include #include #include #include #include #include #include #include #include "hmibutton.h" #include "hmiled.h" #include // 静态剪贴板数据,初始化为空 QVariantMap HmiControlItem::m_clipboardData; // 构造函数:初始化控件基本属性 HmiControlItem::HmiControlItem(QGraphicsItem* parent) : QObject(nullptr), QGraphicsItem(parent), m_registerAddress() { // 设置控件属性:可移动、可选择、发送几何变化通知 setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges); // 启用鼠标悬停事件 setAcceptHoverEvents(true); // 设置变换原点为控件左上角 setTransformOriginPoint(0, 0); } // 检查鼠标是否在右下角缩放区域 // 返回:true(在缩放区域内),false(不在) bool HmiControlItem::isInScaleArea(const QPointF& pos) { QRectF contentRect = boundingRect().adjusted(1, 1, -1, -1); return (pos.x() >= contentRect.width() - m_scaleAreaSize && pos.x() <= contentRect.width()) && (pos.y() >= contentRect.height() - m_scaleAreaSize && pos.y() <= contentRect.height()); } // 鼠标悬停事件处理:根据鼠标位置设置光标样式 void HmiControlItem::hoverMoveEvent(QGraphicsSceneHoverEvent* event) { if (isSelected()) { // 如果控件被选中 if (isInScaleArea(event->pos())) { // 鼠标在右下角缩放区域,显示缩放光标 setCursor(Qt::SizeFDiagCursor); } else { // 鼠标在控件其他区域,显示移动光标 setCursor(Qt::SizeAllCursor); } } else { // 控件未选中,显示默认光标 setCursor(Qt::ArrowCursor); } QGraphicsItem::hoverMoveEvent(event); } // 鼠标按下事件处理:开始拖动或缩放 void HmiControlItem::mousePressEvent(QGraphicsSceneMouseEvent* event) { if (isSelected() && isInScaleArea(event->pos())) { // 选中控件且点击缩放区域,进入缩放模式 m_isScaling = true; m_originalRect = boundingRect().adjusted(1, 1, -1, -1); m_scaleStartPos = event->pos(); event->accept(); return; } // 记录拖动开始位置 m_dragStartPos = event->pos(); QGraphicsItem::mousePressEvent(event); } // 鼠标移动事件处理:处理控件拖动或缩放 void HmiControlItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { if (m_isScaling) { // 缩放模式:根据鼠标移动调整控件大小 qreal deltaX = event->pos().x() - m_scaleStartPos.x(); QRectF currentRect = transform().mapRect(m_originalRect); qreal newWidth = currentRect.width() + deltaX; newWidth = qMax(m_minWidth, qMin(newWidth, m_maxWidth)); qreal aspectRatio = getAspectRatio(); qreal newHeight = newWidth / aspectRatio; newHeight = qMax(m_minHeight, qMin(newHeight, m_maxHeight)); newWidth = newHeight * aspectRatio; if (qAbs(newWidth - currentRect.width()) > 1 || qAbs(newHeight - currentRect.height()) > 1) { // 更新控件大小,应用缩放变换 prepareGeometryChange(); qreal scaleX = newWidth / m_originalRect.width(); qreal scaleY = newHeight / m_originalRect.height(); resetTransform(); setTransform(QTransform::fromScale(scaleX, scaleY), false); update(); } event->accept(); return; } if (isSelected()) { // 使用scenePos计算偏移量,更准确 QPointF delta = event->scenePos() - event->lastScenePos(); QPointF newPos = pos() + delta; // 获取变换后的边界矩形 QRectF itemRect = mapToScene(boundingRect()).boundingRect(); QRectF sceneRect = scene()->sceneRect(); // 限制控件在场景边界内 newPos.setX(qMax(sceneRect.left(), qMin(newPos.x(), sceneRect.right() - itemRect.width()))); newPos.setY(qMax(sceneRect.top(), qMin(newPos.y(), sceneRect.bottom() - itemRect.height()))); setPos(newPos); update(); event->accept(); return; } QGraphicsItem::mouseMoveEvent(event); } // 鼠标释放事件处理:结束缩放或拖动 void HmiControlItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { m_isScaling = false; QGraphicsItem::mouseReleaseEvent(event); } // 右键菜单事件处理:显示控件特定的上下文菜单 void HmiControlItem::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) { QMenu menu; createContextMenu(menu); // 子类实现具体菜单项 menu.exec(event->screenPos()); event->accept(); } // 删除控件:从场景中移除并释放内存 void HmiControlItem::deleteItem() { if (scene()) { scene()->removeItem(this); } delete this; } // 更改控件颜色:弹出颜色对话框选择ON或OFF状态颜色 void HmiControlItem::changeAppearanceColor(bool isOnState, QColor& onColor, QColor& offColor) { QColor newColor = QColorDialog::getColor( Qt::white, nullptr, isOnState ? "选择ON状态颜色" : "选择OFF状态颜色" ); if (newColor.isValid()) { if (isOnState) { onColor = newColor; } else { offColor = newColor; } update(); } } // 设置寄存器绑定 bool HmiControlItem::setRegisterBinding(int address) { if (address >= 0 && address <= 4000) { m_registerAddress = address; return true; } else { qDebug() << "Invalid register binding: address=" << address; return false; } } // 存储数据到剪贴板 void HmiControlItem::copyToClipboard(const QVariantMap& data) { m_clipboardData = data; qDebug() << "Copied to clipboard:" << data; } // 获取剪贴板数据 QVariantMap HmiControlItem::getClipboardData() { return m_clipboardData; } // 检查剪贴板是否有数据 bool HmiControlItem::hasClipboardData() { return !m_clipboardData.isEmpty(); } // 从剪贴板数据创建控件,指定粘贴位置 HmiControlItem* HmiControlItem::createFromClipboard(const QVariantMap& data, const QPointF& pos, QGraphicsItem* parent) { QString type = data.value("type").toString(); HmiControlItem* item = nullptr; if (type == "按钮") { // 创建按钮控件并恢复属性 item = new HmiButton(parent); HmiButton* button = static_cast(item); button->setButtonState(data.value("isButtonOn", false).toBool()); button->setOnColor(QColor(data.value("onColor").toString())); button->setOffColor(QColor(data.value("offColor").toString())); } else if (type == "指示灯") { // 创建指示灯控件并恢复属性 item = new HmiLed(parent); HmiLed* led = static_cast(item); led->setOnColor(QColor(data.value("onColor").toString())); led->setOffColor(QColor(data.value("offColor").toString())); } if (item) { // 设置粘贴位置 item->setPos(pos); // 恢复缩放 qreal scaleX = data.value("scaleX", 1.0).toDouble(); qreal scaleY = data.value("scaleY", 1.0).toDouble(); item->setTransform(QTransform::fromScale(scaleX, scaleY)); // 恢复寄存器绑定 item->setRegisterBinding(data.value("registerAddress", -1).toInt()); } return item; } // 创建右键菜单(默认实现,子类可扩展) void HmiControlItem::createContextMenu(QMenu& menu) { // 默认添加"设置寄存器"选项 QAction* setRegisterAction = new QAction("设置寄存器", &menu); QObject::connect(setRegisterAction, &QAction::triggered, [this]() { bool ok; // 显示当前绑定的寄存器地址作为默认值 int currentAddress = m_registerAddress >= 0 ? m_registerAddress : 0; int address = QInputDialog::getInt(nullptr, "输入寄存器地址", QString("地址 (0-4000):\n当前地址: %1").arg(currentAddress), currentAddress, 0, 4000, 1, &ok); if (ok) { if (!setRegisterBinding(address)) { QMessageBox::warning(nullptr, "错误", "无效的寄存器地址"); } } }); menu.addAction(setRegisterAction); } // 存储控件数据到剪贴板(默认实现) QVariantMap HmiControlItem::saveToClipboard() const { QVariantMap data; data["type"] = getItemType(); data["posX"] = pos().x(); data["posY"] = pos().y(); data["scaleX"] = transform().m11(); data["scaleY"] = transform().m22(); data["registerAddress"] = m_registerAddress; return data; }