想要實現的功能為:在主窗口中點擊按鈕,彈出一個新的窗口,這個窗口中陳列着可以拖動到主窗口中的組件,拖動這些組件到主窗口,實現在主窗口中生成新組件的功能。
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)); } */ }
基本上拖動的功能是有了,但是后面還需要再完善一下。