|
- #include "hmicontrolitem.h"
- #include <QPainter>
- #include <QGraphicsScene>
- #include <QCursor>
- #include <QMenu>
- #include <QAction>
- #include <QGraphicsView>
- #include <QColorDialog>
- #include <QDebug>
- #include <QInputDialog>
- #include "hmibutton.h"
- #include "hmiled.h"
- #include <QMessageBox>
- // 静态剪贴板数据,初始化为空
- QVariantMap HmiControlItem::m_clipboardData;
-
- // 构造函数:初始化控件基本属性
- HmiControlItem::HmiControlItem(QGraphicsItem* parent)
- : QObject(nullptr), QGraphicsItem(parent), m_registerAddress(-1)
- {
- // 设置控件属性:可移动、可选择、发送几何变化通知
- 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()) {
- // 拖动模式:移动控件位置
- QPointF delta = event->pos() - m_dragStartPos;
- QPointF newPos = pos() + delta;
- QRectF itemRect = transform().mapRect(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())));
- if (newPos.x() + itemRect.width() > sceneRect.right()) {
- newPos.setX(sceneRect.right() - itemRect.width());
- }
- if (newPos.y() + itemRect.height() > sceneRect.bottom()) {
- newPos.setY(sceneRect.bottom() - itemRect.height());
- }
- if (newPos.x() < sceneRect.left()) {
- newPos.setX(sceneRect.left());
- }
- if (newPos.y() < sceneRect.top()) {
- newPos.setY(sceneRect.top());
- }
- setPos(newPos);
- if (scene()) {
- // 更新场景和视图
- scene()->update();
- if (scene()->views().size() > 0) {
- scene()->views().first()->viewport()->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<HmiButton*>(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<HmiLed*>(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;
- }
|