C++Qt实现类似multisim中复制拖拽器件并且器件之间连接起来的功能的完整代码
时间: 2023-12-30 19:07:48 浏览: 120
在NI Multisim中创建自定义元器件
4星 · 用户满意度95%
以下是一个简单的 C++ Qt 程序,实现了类似 Multisim 中复制拖拽器件并连接它们之间的功能。该程序使用了 QGraphicsScene 和 QGraphicsView 类来呈现图形界面,使用了 QGraphicsItem 类来创建器件对象,并使用 QGraphicsLineItem 类来创建连接线。
```cpp
#include <QtWidgets>
class CircuitItem : public QGraphicsItem
{
public:
CircuitItem(QGraphicsItem *parent = nullptr);
enum { Type = UserType + 1 };
int type() const override { return Type; }
protected:
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
};
CircuitItem::CircuitItem(QGraphicsItem *parent) :
QGraphicsItem(parent)
{
setFlag(ItemIsMovable);
setFlag(ItemSendsGeometryChanges);
setCacheMode(DeviceCoordinateCache);
}
QRectF CircuitItem::boundingRect() const
{
return QRectF(-15, -15, 30, 30);
}
void CircuitItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
painter->drawEllipse(-10, -10, 20, 20);
}
class CircuitView : public QGraphicsView
{
public:
CircuitView(QWidget *parent = nullptr);
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
private:
QPointF startPoint;
QGraphicsLineItem *lineItem;
CircuitItem *selectedItem;
};
CircuitView::CircuitView(QWidget *parent) :
QGraphicsView(parent)
{
QGraphicsScene *scene = new QGraphicsScene(this);
setScene(scene);
}
void CircuitView::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
startPoint = mapToScene(event->pos());
lineItem = new QGraphicsLineItem(QLineF(startPoint, startPoint));
lineItem->setPen(QPen(Qt::black, 2));
scene()->addItem(lineItem);
QList<QGraphicsItem *> itemList = scene()->items(startPoint, Qt::IntersectsItemShape, Qt::DescendingOrder, QTransform());
foreach (QGraphicsItem *item, itemList) {
if (item->type() == CircuitItem::Type) {
selectedItem = qgraphicsitem_cast<CircuitItem *>(item);
break;
}
}
}
QGraphicsView::mousePressEvent(event);
}
void CircuitView::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
QPointF endPoint = mapToScene(event->pos());
QList<QGraphicsItem *> itemList = scene()->items(endPoint, Qt::IntersectsItemShape, Qt::DescendingOrder, QTransform());
CircuitItem *targetItem = nullptr;
foreach (QGraphicsItem *item, itemList) {
if (item->type() == CircuitItem::Type && item != selectedItem) {
targetItem = qgraphicsitem_cast<CircuitItem *>(item);
break;
}
}
if (targetItem) {
QLineF line(startPoint, endPoint);
QPointF startPointOffset = selectedItem->mapFromScene(startPoint);
QPointF endPointOffset = targetItem->mapFromScene(endPoint);
QGraphicsLineItem *lineItem1 = new QGraphicsLineItem(QLineF(selectedItem->mapToScene(startPointOffset), startPoint));
QGraphicsLineItem *lineItem2 = new QGraphicsLineItem(QLineF(targetItem->mapToScene(endPointOffset), endPoint));
lineItem1->setPen(QPen(Qt::black, 2));
lineItem2->setPen(QPen(Qt::black, 2));
scene()->addItem(lineItem1);
scene()->addItem(lineItem2);
delete lineItem;
lineItem = nullptr;
} else {
delete lineItem;
lineItem = nullptr;
}
selectedItem = nullptr;
}
QGraphicsView::mouseReleaseEvent(event);
}
void CircuitView::mouseMoveEvent(QMouseEvent *event)
{
if (lineItem) {
QPointF endPoint = mapToScene(event->pos());
lineItem->setLine(QLineF(startPoint, endPoint));
}
QGraphicsView::mouseMoveEvent(event);
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
CircuitView view;
view.setWindowTitle("Circuit Simulator");
view.resize(800, 600);
view.show();
for (int i = 0; i < 5; i++) {
CircuitItem *item = new CircuitItem;
item->setPos(50 + i * 100, 50);
view.scene()->addItem(item);
}
return app.exec();
}
```
该程序创建了一个名为 CircuitItem 的自定义图形项类,它表示电路器件。它重载了 boundingRect() 和 paint() 函数,以在 QGraphicsView 中显示圆形图标。
该程序还创建了一个名为 CircuitView 的自定义图形视图类。它重载了 mousePressEvent()、mouseReleaseEvent() 和 mouseMoveEvent() 函数,以处理鼠标事件。当用户单击鼠标左键时,程序会创建一个 QGraphicsLineItem 对象,并将其添加到场景中。程序还会查找鼠标单击位置的所有图形项,并选择第一个 CircuitItem 对象作为当前选定的项。当用户释放鼠标左键时,程序会检查鼠标释放位置的所有图形项,并尝试在选定的项和找到的项之间创建连接线。如果没有找到任何目标项,则删除创建的连接线。
在 main() 函数中,程序创建了一个 CircuitView 对象,并添加了五个 CircuitItem 对象到场景中。用户可以单击 CircuitItem 对象并将其拖动到另一个位置,或者单击并拖动连接线以重新定位其端点。用户还可以在 CircuitItem 对象之间创建连接线,即使这些对象重叠在一起也是如此。
这只是一个简单的示例程序,您可以根据您自己的需求进行修改和扩展。
阅读全文