QT 實現類似simulink中跨窗口拖動添加組件的方法


想要實現的功能為:在主窗口中點擊按鈕,彈出一個新的窗口,這個窗口中陳列着可以拖動到主窗口中的組件,拖動這些組件到主窗口,實現在主窗口中生成新組件的功能。

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    static bool MouseIn;//用於判斷鼠標是否在主窗口中(后期可以更改為是否在特定區域)的布爾變量
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow() override;
protected:
    void enterEvent(QEvent *event) override;//鼠標移動進入主窗口的函數(后期可以改為進入特定區域)
    void leaveEvent(QEvent *event) override;//鼠標離開進入主窗口的函數(后期可以改為離開特定區域)
private slots:
    void on_addBtn_clicked();//按鈕,用於彈出組件的陳列窗口
    void newTestButton();//當一切條件滿足之后,執行生成組件的槽函數

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "componentwindow.h"
#include "testbutton.h"
#include <QDebug>
#include <QCursor>
#include <QMouseEvent>
#pragma execution_character_set("utf-8")
bool MainWindow::MouseIn = true;//全局靜態變量初始化
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::enterEvent(QEvent *event)
{
    Q_UNUSED(event);
    MouseIn = true;
}

void MainWindow::leaveEvent(QEvent *event)
{
    Q_UNUSED(event);
    MouseIn = false;
}

void MainWindow::on_addBtn_clicked()
{
    ComponentWindow *window = ComponentWindow::newComponentWindow();//單例模式,調用靜態函數來初始化組件窗口
    window->show();
    connect(window->btn1,SIGNAL(preperNewTestButton()),this,SLOT(newTestButton()),Qt::UniqueConnection);//滿足生成按鈕的條件之后,會由按鈕發出信號,主界面接受信號
}

void MainWindow::newTestButton()
{
    TestButton *btn = new TestButton(this);//生成按鈕
    int x=this->mapFromGlobal(QCursor().pos()).x();
    int y=this->mapFromGlobal(QCursor().pos()).y();//獲取鼠標在窗口中的坐標而不是全局坐標
    btn->move(x,y);//將鼠標移動至鼠標釋放時的位置
    btn->show();
}

ComponentWindow.h

#ifndef COMPONENTWINDOW_H
#define COMPONENTWINDOW_H

#include <QWidget>
#include <QPushButton>
namespace Ui {
class ComponentWindow;
}

class ComponentWindow : public QWidget
{
    Q_OBJECT

public:
    QPushButton *btn1;//聲明一個指針,用於保存UI界面上的組件的指針,偷懶寫成公有變量
    static ComponentWindow *m_instance;//單例會用到的全局變量
    static ComponentWindow *newComponentWindow();//用於創建組件窗口的函數
    ~ComponentWindow();

private:
    explicit ComponentWindow(QWidget *parent = nullptr);//構造函數聲明為私有,就不能用new來創建這個對象,只能通過調用上面的靜態函數來執行這個構造函數
    Ui::ComponentWindow *ui;
};

#endif // COMPONENTWINDOW_H

component.cpp

#include "componentwindow.h"
#include "ui_componentwindow.h"
#include "mainwindow.h"

#pragma execution_character_set("utf-8")
ComponentWindow * ComponentWindow::m_instance=nullptr;//靜態全局變量初始化
ComponentWindow::ComponentWindow(QWidget *parent) :QWidget(parent),ui(new Ui::ComponentWindow)
{
    ui->setupUi(this);
    btn1 = ui->btn_1;//將UI界面上的組件指針賦值給
}

ComponentWindow *ComponentWindow::newComponentWindow()
{
    if(m_instance==nullptr)
    {
        m_instance = new ComponentWindow();
    }
    return m_instance;
    //最最簡單的單例寫法
}

ComponentWindow::~ComponentWindow()
{
    delete ui;
}

由於組件以后還會有一些特殊的功能,所以需要自己去繼承,並完成新的功能編輯,這里繼承了QPushButton。

#ifndef TESTBUTTON_H
#define TESTBUTTON_H
#include <QPushButton>
#include <QMouseEvent>

class TestButton : public QPushButton
{
    Q_OBJECT
public:
    explicit TestButton(QWidget *parent=0);
protected:
    void mousePressEvent(QMouseEvent *e);
    void mouseReleaseEvent(QMouseEvent *e);
    void mouseMoveEvent(QMouseEvent *e);
    //三個鼠標事件
signals:
    void preperNewTestButton();
private slots:

private:
    QPoint pressPoint;
};

#endif // TESTBUTTON_H

testButton.cpp

#include "testbutton.h"
#include "mainwindow.h"
#include <QDebug>
#pragma execution_character_set("utf-8")

TestButton::TestButton(QWidget *parent):QPushButton (parent)
{

}

void TestButton::mousePressEvent(QMouseEvent *event)
{
    /*
    if(event->button() == Qt::LeftButton)
    {
        this->raise(); //將此按鈕移動到頂層顯示
        this->pressPoint = event->pos();
    }
    */
}

void TestButton::mouseReleaseEvent(QMouseEvent *event)
{
    if(MainWindow::MouseIn)//獲取鼠標的位置狀態的布爾函數,由於MouseIn是靜態變量,所以需要用名稱空間符號::來訪問
    {
        emit preperNewTestButton();//當鼠標在指定區域時,發出信號准備生成按鈕
    }
    else
    {
        return;//否則什么都不干,當然這個功能后面會完善
    }
}

void TestButton::mouseMoveEvent(QMouseEvent *event)
{
    /*
    if(event->buttons() == Qt::LeftButton)
    {
        this->move(this->mapToParent(event->pos() - this->pressPoint));
    }
    */
}

基本上拖動的功能是有了,但是后面還需要再完善一下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM