C++Qt实现类似multisim中复制拖拽器件并且器件之间连接起来的功能的完整代码实现
时间: 2023-12-30 11:07:44 浏览: 156
以下是一个简单的C++ Qt程序,实现了类似Multisim的电路设计软件的复制、拖拽和连接器件的功能。这个程序有一个主窗口,里面有一个画板和一个工具栏。在工具栏上有一些预定义的器件,可以将它们拖拽到画板上,并且它们可以用鼠标连接起来。这个程序只是一个基础实现,您可以根据自己的需求扩展它。
```
#include <QtGui>
class CircuitComponent : public QGraphicsItem
{
public:
CircuitComponent(QPixmap pixmap);
void addConnection(QGraphicsLineItem *connection);
void removeConnection(QGraphicsLineItem *connection);
enum { Type = UserType + 1 };
int type() const override { return Type; }
protected:
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget) override;
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
private:
QPixmap m_pixmap;
QList<QGraphicsLineItem *> m_connections;
};
CircuitComponent::CircuitComponent(QPixmap pixmap)
: m_pixmap(pixmap)
{
setFlags(ItemIsMovable | ItemIsSelectable | ItemSendsGeometryChanges);
}
void CircuitComponent::addConnection(QGraphicsLineItem *connection)
{
m_connections.append(connection);
}
void CircuitComponent::removeConnection(QGraphicsLineItem *connection)
{
m_connections.removeOne(connection);
}
QRectF CircuitComponent::boundingRect() const
{
return QRectF(-m_pixmap.width() / 2, -m_pixmap.height() / 2,
m_pixmap.width(), m_pixmap.height());
}
void CircuitComponent::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
painter->drawPixmap(-m_pixmap.width() / 2, -m_pixmap.height() / 2, m_pixmap);
}
QVariant CircuitComponent::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == ItemPositionChange) {
foreach (QGraphicsLineItem *connection, m_connections) {
connection->setLine(mapToScene(0, 0), connection->line().p2());
}
}
return QGraphicsItem::itemChange(change, value);
}
class CircuitConnection : public QGraphicsLineItem
{
public:
CircuitConnection(QPointF startPoint, QPointF endPoint);
enum { Type = UserType + 2 };
int type() const override { return Type; }
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
};
CircuitConnection::CircuitConnection(QPointF startPoint, QPointF endPoint)
: QGraphicsLineItem(QLineF(startPoint, endPoint))
{
}
QVariant CircuitConnection::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == ItemPositionHasChanged) {
QPointF newStartPoint = mapFromItem(fromItem(), 0, 0);
QPointF newEndPoint = mapFromItem(toItem(), 0, 0);
setLine(QLineF(newStartPoint, newEndPoint));
}
return QGraphicsLineItem::itemChange(change, value);
}
class CircuitScene : public QGraphicsScene
{
public:
CircuitScene(QObject *parent = nullptr);
void startConnection(CircuitComponent *component, QPointF point);
void endConnection(CircuitComponent *component, QPointF point);
private:
CircuitComponent *m_startComponent;
CircuitConnection *m_connection;
};
CircuitScene::CircuitScene(QObject *parent)
: QGraphicsScene(parent), m_startComponent(nullptr), m_connection(nullptr)
{
}
void CircuitScene::startConnection(CircuitComponent *component, QPointF point)
{
m_startComponent = component;
m_connection = new CircuitConnection(point, point);
addItem(m_connection);
}
void CircuitScene::endConnection(CircuitComponent *component, QPointF point)
{
if (m_startComponent != nullptr && m_startComponent != component) {
CircuitConnection *connection = new CircuitConnection(mapFromItem(m_startComponent, 0, 0),
mapFromItem(component, 0, 0));
addItem(connection);
m_startComponent->addConnection(connection);
component->addConnection(connection);
}
removeItem(m_connection);
delete m_connection;
m_connection = nullptr;
m_startComponent = nullptr;
}
class CircuitView : public QGraphicsView
{
public:
CircuitView(QWidget *parent = nullptr);
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private:
QPoint m_lastMousePos;
};
CircuitView::CircuitView(QWidget *parent)
: QGraphicsView(parent), m_lastMousePos(QPoint())
{
setDragMode(RubberBandDrag);
setRenderHint(QPainter::Antialiasing);
}
void CircuitView::mousePressEvent(QMouseEvent *event)
{
m_lastMousePos = event->pos();
QGraphicsView::mousePressEvent(event);
}
void CircuitView::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
QPoint delta = event->pos() - m_lastMousePos;
if (qAbs(delta.x()) > 5 || qAbs(delta.y()) > 5) {
setDragMode(ScrollHandDrag);
}
}
QGraphicsView::mouseMoveEvent(event);
}
void CircuitView::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && dragMode() == ScrollHandDrag) {
setDragMode(RubberBandDrag);
}
QGraphicsView::mouseReleaseEvent(event);
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QPixmap andPixmap(":/and.png");
CircuitComponent andComponent(andPixmap);
QPixmap orPixmap(":/or.png");
CircuitComponent orComponent(orPixmap);
QPixmap notPixmap(":/not.png");
CircuitComponent notComponent(notPixmap);
CircuitScene scene;
scene.setSceneRect(0, 0, 800, 600);
scene.addItem(&andComponent);
scene.addItem(&orComponent);
scene.addItem(¬Component);
CircuitView view;
view.setScene(&scene);
QWidget window;
QVBoxLayout *layout = new QVBoxLayout();
layout->addWidget(&view);
QToolBar *toolbar = new QToolBar();
QAction *andAction = new QAction("AND", &window);
andAction->setIcon(QIcon(andPixmap));
QAction *orAction = new QAction("OR", &window);
orAction->setIcon(QIcon(orPixmap));
QAction *notAction = new QAction("NOT", &window);
notAction->setIcon(QIcon(notPixmap));
toolbar->addAction(andAction);
toolbar->addAction(orAction);
toolbar->addAction(notAction);
layout->addWidget(toolbar);
window.setLayout(layout);
window.show();
QObject::connect(andAction, &QAction::triggered, [&scene]() {
CircuitComponent *andComponent = new CircuitComponent(QPixmap(":/and.png"));
scene.addItem(andComponent);
});
QObject::connect(orAction, &QAction::triggered, [&scene]() {
CircuitComponent *orComponent = new CircuitComponent(QPixmap(":/or.png"));
scene.addItem(orComponent);
});
QObject::connect(notAction, &QAction::triggered, [&scene]() {
CircuitComponent *notComponent = new CircuitComponent(QPixmap(":/not.png"));
scene.addItem(notComponent);
});
QObject::connect(&scene, &CircuitScene::selectionChanged, [&scene]() {
QList<QGraphicsItem *> items = scene.selectedItems();
if (items.count() == 2 && items.at(0)->type() == CircuitComponent::Type
&& items.at(1)->type() == CircuitComponent::Type) {
CircuitComponent *startComponent = static_cast<CircuitComponent *>(items.at(0));
CircuitComponent *endComponent = static_cast<CircuitComponent *>(items.at(1));
scene.startConnection(startComponent, startComponent->pos());
scene.endConnection(endComponent, endComponent->pos());
}
});
view.setDragMode(QGraphicsView::RubberBandDrag);
return app.exec();
}
```
阅读全文