QGraphicsWidget模仿simulink创建子系统详细的c++代码示例
时间: 2023-07-29 12:09:17 浏览: 115
以下是一个更详细的示例,演示如何使用QGraphicsWidget创建一个类似于Simulink中子系统的图形,并实现拖放连接线的功能。这个示例包括一个MainWindow类和一个Subsystem类。
MainWindow类:
```cpp
#include <QtWidgets>
#include "Subsystem.h"
class MainWindow : public QMainWindow
{
public:
MainWindow(QWidget* parent = nullptr) : QMainWindow(parent)
{
// 创建一个场景和视图
scene_ = new QGraphicsScene(this);
view_ = new QGraphicsView(scene_);
setCentralWidget(view_);
// 设置视图的大小策略
view_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
// 设置场景的大小
scene_->setSceneRect(0, 0, 800, 600);
// 添加一个工具栏
QToolBar* toolbar = addToolBar("Tools");
// 添加一个按钮,用于创建子系统
QAction* addSubsystemAction = new QAction("Add Subsystem", this);
toolbar->addAction(addSubsystemAction);
// 连接按钮的信号和槽函数
connect(addSubsystemAction, &QAction::triggered, this, &MainWindow::addSubsystem);
// 启用拖放
view_->setDragMode(QGraphicsView::RubberBandDrag);
}
private:
void addSubsystem()
{
// 创建一个子系统并添加到场景中
Subsystem* subsystem = new Subsystem();
scene_->addItem(subsystem);
// 将子系统放置在场景的中央
QPointF center = scene_->sceneRect().center() - subsystem->boundingRect().center();
subsystem->setPos(center);
// 启用子系统的拖动功能
subsystem->setFlag(QGraphicsItem::ItemIsMovable, true);
// 启用子系统的接受拖放连接线的功能
subsystem->setAcceptDrops(true);
}
private:
QGraphicsScene* scene_;
QGraphicsView* view_;
};
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.showMaximized();
return app.exec();
}
```
在MainWindow类的构造函数中,我们创建了一个场景和视图,并将视图设置为窗口的中心部分。我们还添加了一个工具栏和一个按钮,用于创建子系统。我们连接了按钮的信号和槽函数,以便在单击按钮时添加一个子系统。最后,我们启用了拖放功能。
Subsystem类:
```cpp
#include <QtWidgets>
class Subsystem : public QGraphicsWidget
{
public:
Subsystem(QGraphicsItem* parent = nullptr) : QGraphicsWidget(parent)
{
// 设置子系统的大小和位置
setGeometry(QRectF(0, 0, 200, 150));
// 添加一个标题
QLabel* titleLabel = new QLabel("Subsystem", this);
titleLabel->setAlignment(Qt::AlignCenter);
titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
titleLabel->setFont(QFont("Arial", 12, QFont::Bold));
// 添加一个输入端口
QGraphicsEllipseItem* inputPort = new QGraphicsEllipseItem(-10, 60, 20, 20, this);
inputPort->setBrush(Qt::yellow);
inputPort->setPen(Qt::black);
// 添加一个输出端口
QGraphicsEllipseItem* outputPort = new QGraphicsEllipseItem(190, 60, 20, 20, this);
outputPort->setBrush(Qt::yellow);
outputPort->setPen(Qt::black);
}
// 返回子系统的矩形区域
QRectF boundingRect() const override
{
return QRectF(0, 0, 200, 150);
}
// 绘制子系统的图形
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override
{
painter->setPen(Qt::black);
painter->setBrush(Qt::white);
painter->drawRect(boundingRect());
}
// 接受拖放事件
void dragEnterEvent(QGraphicsSceneDragDropEvent* event) override
{
if (event->mimeData()->hasFormat("text/plain"))
event->acceptProposedAction();
}
// 处理拖放事件
void dropEvent(QGraphicsSceneDragDropEvent* event) override
{
// 获取拖动操作的源项
QGraphicsWidget* sourceItem = qobject_cast<QGraphicsWidget*>(event->source());
if (sourceItem)
{
// 创建一个连接线
QGraphicsLineItem* line = new QGraphicsLineItem(this);
// 设置连接线的位置和颜色
QPointF start = outputPortPosition();
QPointF end = sourceItem->mapToScene(sourceItem->boundingRect().center());
line->setLine(QLineF(start, end));
line->setPen(QPen(Qt::blue, 2));
// 添加连接线到场景中
scene()->addItem(line);
}
}
private:
QPointF outputPortPosition() const
{
return mapToScene(QPointF(200, 75));
}
};
```
在Subsystem类的构造函数中,我们设置了子系统的大小和位置,并添加了一个标题和输入/输出端口。在boundingRect()函数中,我们返回子系统的矩形区域。在paint()函数中,我们使用QPainter绘制了子系统的图形。
我们还实现了dragEnterEvent()和dropEvent()函数,以便子系统能够接受拖放连接线的事件。在dropEvent()函数中,我们获取拖动操作的源项,并创建一个连接线。我们设置连接线的起始点和终止点,并将连接线添加到场景中。
注意:由于Subsystem类继承自QGraphicsWidget类,因此我们可以直接使用mapToScene()函数来转换端口的坐标。如果我们使用的是QGraphicsItem类,则需要使用mapToParent()或mapToScene()函数来转换坐标。
阅读全文