C++Qt实现类似multisim中复制拖拽器件并且器件之间连接起来的功能的完整代码实现
时间: 2023-12-30 12:07:44 浏览: 138
以下是一个简单的示例程序,演示了如何使用Qt实现类似Multisim中复制拖拽器件并连接它们的功能。该程序包含了一个主窗口类`MainWindow`和一个自定义控件类`CircuitComponent`。
首先,我们需要在`CircuitComponent`中实现拖拽和复制功能。我们可以使用`QDrag`和`QMimeData`类来实现拖拽功能,使用`QClipboard`和`QDataStream`类来实现复制功能。下面是`CircuitComponent`的相关代码:
```cpp
#include <QtWidgets>
class CircuitComponent : public QWidget
{
public:
CircuitComponent(QWidget *parent = nullptr)
: QWidget(parent)
{
setFixedSize(60, 60);
setStyleSheet("background-color: white; border: 1px solid black;");
setAcceptDrops(true);
}
void mousePressEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton) {
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
QPoint offset = event->pos();
stream << offset;
mimeData->setData("application/x-circuit-component", data);
drag->setMimeData(mimeData);
drag->setPixmap(grab());
drag->setHotSpot(offset);
drag->exec(Qt::CopyAction | Qt::MoveAction);
}
}
void mouseMoveEvent(QMouseEvent *event) override
{
if (event->buttons() & Qt::LeftButton) {
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
QPoint offset = event->pos();
stream << offset;
mimeData->setData("application/x-circuit-component", data);
drag->setMimeData(mimeData);
drag->setPixmap(grab());
drag->setHotSpot(offset);
drag->exec(Qt::CopyAction | Qt::MoveAction);
}
}
void dragEnterEvent(QDragEnterEvent *event) override
{
if (event->mimeData()->hasFormat("application/x-circuit-component")) {
event->acceptProposedAction();
}
}
void dropEvent(QDropEvent *event) override
{
if (event->mimeData()->hasFormat("application/x-circuit-component")) {
QByteArray data = event->mimeData()->data("application/x-circuit-component");
QDataStream stream(&data, QIODevice::ReadOnly);
QPoint offset;
stream >> offset;
CircuitComponent *component = new CircuitComponent;
component->move(event->pos() - offset);
component->show();
event->setDropAction(Qt::CopyAction);
event->accept();
}
}
};
```
接下来,我们需要在`MainWindow`中实现连接器件的功能。我们可以使用`QGraphicsScene`和`QGraphicsView`类来绘制和管理连接线,使用`QGraphicsItem`类来实现连接线和器件的图形表示。下面是`MainWindow`的相关代码:
```cpp
#include <QtWidgets>
class MainWindow : public QMainWindow
{
public:
MainWindow(QWidget *parent = nullptr)
: QMainWindow(parent)
{
setCentralWidget(new QGraphicsView);
scene = new QGraphicsScene(this);
QGraphicsView *view = qobject_cast<QGraphicsView *>(centralWidget());
view->setScene(scene);
view->setRenderHint(QPainter::Antialiasing);
view->setDragMode(QGraphicsView::RubberBandDrag);
QAction *copyAction = new QAction(tr("&Copy"), this);
connect(copyAction, &QAction::triggered, this, &MainWindow::copyComponent);
addAction(copyAction);
QAction *pasteAction = new QAction(tr("&Paste"), this);
connect(pasteAction, &QAction::triggered, this, &MainWindow::pasteComponent);
addAction(pasteAction);
setWindowTitle(tr("Circuit Designer"));
resize(800, 600);
}
private:
QGraphicsScene *scene;
CircuitComponent *copiedComponent = nullptr;
QGraphicsLineItem *currentLine = nullptr;
QPointF currentStartPos;
void copyComponent()
{
if (!scene->selectedItems().isEmpty()) {
QGraphicsItem *item = scene->selectedItems().first();
if (item->type() == CircuitComponent::Type) {
copiedComponent = qgraphicsitem_cast<CircuitComponent *>(item);
}
}
}
void pasteComponent()
{
if (copiedComponent) {
CircuitComponent *component = new CircuitComponent;
component->move(mapFromGlobal(QCursor::pos()));
component->show();
scene->addItem(component);
}
}
void mousePressEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton) {
QGraphicsItem *item = scene->itemAt(event->pos(), QTransform());
if (item && item->type() == CircuitComponent::Type) {
currentStartPos = item->mapToScene(item->boundingRect().center());
currentLine = new QGraphicsLineItem(QLineF(currentStartPos, event->scenePos()));
currentLine->setPen(QPen(Qt::black, 2));
scene->addItem(currentLine);
}
}
}
void mouseMoveEvent(QMouseEvent *event) override
{
if (currentLine) {
currentLine->setLine(QLineF(currentStartPos, event->scenePos()));
}
}
void mouseReleaseEvent(QMouseEvent *event) override
{
if (currentLine) {
QGraphicsItem *startItem = scene->itemAt(currentStartPos, QTransform());
QGraphicsItem *endItem = scene->itemAt(event->scenePos(), QTransform());
if (startItem && startItem->type() == CircuitComponent::Type &&
endItem && endItem->type() == CircuitComponent::Type &&
startItem != endItem) {
QPointF start = startItem->mapToScene(startItem->boundingRect().center());
QPointF end = endItem->mapToScene(endItem->boundingRect().center());
QGraphicsLineItem *lineItem = new QGraphicsLineItem(QLineF(start, end));
lineItem->setPen(QPen(Qt::black, 2));
scene->addItem(lineItem);
}
delete currentLine;
currentLine = nullptr;
}
}
};
```
最后,在`main()`函数中创建`MainWindow`并运行程序:
```cpp
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
window.show();
return app.exec();
}
```
这样,我们就完成了一个简单的类似Multisim的电路设计程序。完整代码可以在下面找到:
```cpp
#include <QtWidgets>
class CircuitComponent : public QWidget
{
public:
CircuitComponent(QWidget *parent = nullptr)
: QWidget(parent)
{
setFixedSize(60, 60);
setStyleSheet("background-color: white; border: 1px solid black;");
setAcceptDrops(true);
}
void mousePressEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton) {
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
QPoint offset = event->pos();
stream << offset;
mimeData->setData("application/x-circuit-component", data);
drag->setMimeData(mimeData);
drag->setPixmap(grab());
drag->setHotSpot(offset);
drag->exec(Qt::CopyAction | Qt::MoveAction);
}
}
void mouseMoveEvent(QMouseEvent *event) override
{
if (event->buttons() & Qt::LeftButton) {
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
QPoint offset = event->pos();
stream << offset;
mimeData->setData("application/x-circuit-component", data);
drag->setMimeData(mimeData);
drag->setPixmap(grab());
drag->setHotSpot(offset);
drag->exec(Qt::CopyAction | Qt::MoveAction);
}
}
void dragEnterEvent(QDragEnterEvent *event) override
{
if (event->mimeData()->hasFormat("application/x-circuit-component")) {
event->acceptProposedAction();
}
}
void dropEvent(QDropEvent *event) override
{
if (event->mimeData()->hasFormat("application/x-circuit-component")) {
QByteArray data = event->mimeData()->data("application/x-circuit-component");
QDataStream stream(&data, QIODevice::ReadOnly);
QPoint offset;
stream >> offset;
CircuitComponent *component = new CircuitComponent;
component->move(event->pos() - offset);
component->show();
event->setDropAction(Qt::CopyAction);
event->accept();
}
}
};
class MainWindow : public QMainWindow
{
public:
MainWindow(QWidget *parent = nullptr)
: QMainWindow(parent)
{
setCentralWidget(new QGraphicsView);
scene = new QGraphicsScene(this);
QGraphicsView *view = qobject_cast<QGraphicsView *>(centralWidget());
view->setScene(scene);
view->setRenderHint(QPainter::Antialiasing);
view->setDragMode(QGraphicsView::RubberBandDrag);
QAction *copyAction = new QAction(tr("&Copy"), this);
connect(copyAction, &QAction::triggered, this, &MainWindow::copyComponent);
addAction(copyAction);
QAction *pasteAction = new QAction(tr("&Paste"), this);
connect(pasteAction, &QAction::triggered, this, &MainWindow::pasteComponent);
addAction(pasteAction);
setWindowTitle(tr("Circuit Designer"));
resize(800, 600);
}
private:
QGraphicsScene *scene;
CircuitComponent *copiedComponent = nullptr;
QGraphicsLineItem *currentLine = nullptr;
QPointF currentStartPos;
void copyComponent()
{
if (!scene->selectedItems().isEmpty()) {
QGraphicsItem *item = scene->selectedItems().first();
if (item->type() == CircuitComponent::Type) {
copiedComponent = qgraphicsitem_cast<CircuitComponent *>(item);
}
}
}
void pasteComponent()
{
if (copiedComponent) {
CircuitComponent *component = new CircuitComponent;
component->move(mapFromGlobal(QCursor::pos()));
component->show();
scene->addItem(component);
}
}
void mousePressEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton) {
QGraphicsItem *item = scene->itemAt(event->pos(), QTransform());
if (item && item->type() == CircuitComponent::Type) {
currentStartPos = item->mapToScene(item->boundingRect().center());
currentLine = new QGraphicsLineItem(QLineF(currentStartPos, event->scenePos()));
currentLine->setPen(QPen(Qt::black, 2));
scene->addItem(currentLine);
}
}
}
void mouseMoveEvent(QMouseEvent *event) override
{
if (currentLine) {
currentLine->setLine(QLineF(currentStartPos, event->scenePos()));
}
}
void mouseReleaseEvent(QMouseEvent *event) override
{
if (currentLine) {
QGraphicsItem *startItem = scene->itemAt(currentStartPos, QTransform());
QGraphicsItem *endItem = scene->itemAt(event->scenePos(), QTransform());
if (startItem && startItem->type() == CircuitComponent::Type &&
endItem && endItem->type() == CircuitComponent::Type &&
startItem != endItem) {
QPointF start = startItem->mapToScene(startItem->boundingRect().center());
QPointF end = endItem->mapToScene(endItem->boundingRect().center());
QGraphicsLineItem *lineItem = new QGraphicsLineItem(QLineF(start, end));
lineItem->setPen(QPen(Qt::black, 2));
scene->addItem(lineItem);
}
delete currentLine;
currentLine = nullptr;
}
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
window.show();
return app.exec();
}
```
阅读全文