C++Qt代码实现类似multisim的器件放置连线功能
时间: 2023-08-27 12:03:51 浏览: 99
实现类似 Multisim 的器件放置和连线功能需要进行如下步骤:
1. 创建器件类(Component),其中包含器件的位置、类型、属性等信息。
2. 创建连线类(Connection),其中包含连接的起点、终点、类型等信息。
3. 在主窗口中创建画布,用于展示器件和连线。
4. 实现鼠标事件处理函数,监听鼠标的按下、移动和释放事件,以便实现器件的放置和连线的绘制。
5. 实现键盘事件处理函数,监听键盘的按下和释放事件,以便实现器件的选择和删除。
6. 实现拖拽事件处理函数,监听拖拽事件,以便实现器件的移动和连线的调整。
下面是一个简单的示例代码:
```
// Component.h
#ifndef COMPONENT_H
#define COMPONENT_H
#include <QObject>
#include <QGraphicsItem>
class Component : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
Component(QGraphicsItem *parent = nullptr);
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
void setType(int type);
int type() const;
void setProperties(const QMap<QString, QVariant> &properties);
QMap<QString, QVariant> properties() const;
signals:
void clicked(Component *component);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
private:
int m_type;
QMap<QString, QVariant> m_properties;
};
#endif // COMPONENT_H
// Component.cpp
#include "Component.h"
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsSceneMouseEvent>
Component::Component(QGraphicsItem *parent)
: QObject(nullptr), QGraphicsItem(parent)
{
setFlag(QGraphicsItem::ItemIsSelectable);
setFlag(QGraphicsItem::ItemIsMovable);
}
QRectF Component::boundingRect() const
{
return QRectF(-25, -25, 50, 50);
}
void Component::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->drawRect(boundingRect());
}
void Component::setType(int type)
{
m_type = type;
}
int Component::type() const
{
return m_type;
}
void Component::setProperties(const QMap<QString, QVariant> &properties)
{
m_properties = properties;
}
QMap<QString, QVariant> Component::properties() const
{
return m_properties;
}
void Component::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mousePressEvent(event);
if (event->button() == Qt::LeftButton)
emit clicked(this);
}
void Component::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mouseReleaseEvent(event);
}
// Connection.h
#ifndef CONNECTION_H
#define CONNECTION_H
#include <QObject>
#include <QGraphicsItem>
class Connection : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
enum Type {
Input,
Output
};
Connection(QGraphicsItem *parent = nullptr);
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
void setType(Type type);
Type type() const;
void setConnected(Connection *connection);
Connection *connected() const;
signals:
void clicked(Connection *connection);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
private:
Type m_type;
Connection *m_connected;
};
#endif // CONNECTION_H
// Connection.cpp
#include "Connection.h"
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsSceneMouseEvent>
Connection::Connection(QGraphicsItem *parent)
: QObject(nullptr), QGraphicsItem(parent)
{
}
QRectF Connection::boundingRect() const
{
return QRectF(-5, -5, 10, 10);
}
void Connection::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->drawEllipse(boundingRect());
}
void Connection::setType(Type type)
{
m_type = type;
}
Connection::Type Connection::type() const
{
return m_type;
}
void Connection::setConnected(Connection *connection)
{
m_connected = connection;
}
Connection *Connection::connected() const
{
return m_connected;
}
void Connection::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mousePressEvent(event);
if (event->button() == Qt::LeftButton)
emit clicked(this);
}
void Connection::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mouseReleaseEvent(event);
}
void Connection::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mouseMoveEvent(event);
QPointF position = mapToScene(event->pos());
if (m_type == Input && m_connected)
m_connected->setPos(position);
else if (m_type == Output)
setPos(position);
}
// MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class QGraphicsScene;
class QGraphicsView;
class Component;
class Connection;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
void createActions();
void createMenus();
void createToolbar();
void createScene();
void createView();
void createStatusBar();
Component *createComponent(int type, const QPointF &position);
Connection *createConnection(const QPointF &start, const QPointF &end);
private slots:
void onComponentClicked(Component *component);
void onConnectionClicked(Connection *connection);
void onDeleteActionTriggered();
private:
QGraphicsScene *m_scene;
QGraphicsView *m_view;
QAction *m_deleteAction;
};
#endif // MAINWINDOW_H
// MainWindow.cpp
#include "MainWindow.h"
#include "Component.h"
#include "Connection.h"
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QToolBar>
#include <QStatusBar>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QKeyEvent>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
createActions();
createMenus();
createToolbar();
createScene();
createView();
createStatusBar();
}
MainWindow::~MainWindow()
{
}
void MainWindow::createActions()
{
m_deleteAction = new QAction(tr("Delete"), this);
m_deleteAction->setShortcut(Qt::Key_Delete);
m_deleteAction->setEnabled(false);
connect(m_deleteAction, &QAction::triggered, this, &MainWindow::onDeleteActionTriggered);
}
void MainWindow::createMenus()
{
QMenu *editMenu = menuBar()->addMenu(tr("Edit"));
editMenu->addAction(m_deleteAction);
}
void MainWindow::createToolbar()
{
QToolBar *editToolBar = addToolBar(tr("Edit"));
editToolBar->addAction(m_deleteAction);
}
void MainWindow::createScene()
{
m_scene = new QGraphicsScene(this);
m_scene->setSceneRect(-5000, -5000, 10000, 10000);
}
void MainWindow::createView()
{
m_view = new QGraphicsView(m_scene, this);
setCentralWidget(m_view);
m_view->setRenderHint(QPainter::Antialiasing);
m_view->setDragMode(QGraphicsView::ScrollHandDrag);
m_view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
}
void MainWindow::createStatusBar()
{
QStatusBar *statusBar = this->statusBar();
statusBar->showMessage(tr("Ready"));
}
Component *MainWindow::createComponent(int type, const QPointF &position)
{
Component *component = new Component();
component->setType(type);
component->setPos(position);
component->setZValue(1);
connect(component, &Component::clicked, this, &MainWindow::onComponentClicked);
m_scene->addItem(component);
return component;
}
Connection *MainWindow::createConnection(const QPointF &start, const QPointF &end)
{
Connection *connection = new Connection();
connection->setPos(start);
connection->setZValue(0);
connect(connection, &Connection::clicked, this, &MainWindow::onConnectionClicked);
m_scene->addItem(connection);
connection->setConnected(createConnection(end, start));
return connection;
}
void MainWindow::onComponentClicked(Component *component)
{
m_deleteAction->setEnabled(true);
}
void MainWindow::onConnectionClicked(Connection *connection)
{
m_deleteAction->setEnabled(true);
}
void MainWindow::onDeleteActionTriggered()
{
QList<QGraphicsItem*> items = m_scene->selectedItems();
for (QGraphicsItem *item : items) {
if (Component *component = qgraphicsitem_cast<Component*>(item)) {
for (QGraphicsItem *connection : component->childItems()) {
m_scene->removeItem(connection);
delete connection;
}
}
m_scene->removeItem(item);
delete item;
}
m_deleteAction->setEnabled(false);
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Delete)
onDeleteActionTriggered();
else
QMainWindow::keyPressEvent(event);
}
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
QPointF position = m_view->mapToScene(event->pos());
createComponent(0, position);
}
else if (event->button() == Qt::RightButton) {
QPointF position = m_view->mapToScene(event->pos());
createConnection(position, position);
}
else {
QMainWindow::mousePressEvent(event);
}
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
QPointF position = m_view->mapToScene(event->pos());
m_scene->addLine(m_scene->sceneRect().bottomRight(), position, QPen(Qt::blue, 5));
}
else {
QMainWindow::mouseMoveEvent(event);
}
}
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
QPointF position = m_view->mapToScene(event->pos());
createConnection(m_scene->items(Qt::DescendingOrder)[0]->pos(), position);
}
else {
QMainWindow::mouseReleaseEvent(event);
}
}
```
这段代码实现了一个简单的器件放置和连线功能的窗口,其中包含了器件类 Component 和连线类 Connection,以及主窗口类 MainWindow。在主窗口类的构造函数中,创建了画布和视图,并初始化了工具栏和菜单。在创建器件和连线时,可以分别通过 createComponent() 和 createConnection() 函数来创建。在鼠标事件处理函数中,监听了鼠标的按下、移动和释放事件,以便实现器件的放置和连线的绘制。在键盘事件处理函数中,监听了键盘的按下和释放事件,以便实现器件的选择和删除。在拖拽事件处理函数中,监听了拖拽事件,以便实现器件的移动和连线的调整。