Qt拖放(1):拖放基本原理(QDrag類)

Qt拖放(1):拖放基本原理(QDrag類)

若對C++語法不熟悉,建議參閱《C++語法詳解》一書,電子工業出版社出版,該書語法示例短小精悍,對查閱C++知識點相當方便,並對語法原理進行了透徹、深入詳細的講解,可確保讀者徹底弄懂C++的原理,徹底解惑C++,使其知其然更知其所以然。此書是一本全面瞭解C++不可多得的案頭必備圖書。

本章講解的類及繼承關係如圖9-1所示
在這裏插入圖片描述

9.1 拖放原理

9.1.1 拖放基本原理

拖放操作包括兩個動作:拖動(drag)和放下(drop或稱爲放置)。當被拖動時拖動的數據會被存儲爲MIME類型(見第6章文件對話框)的對象,MIME類型使用QMimeData類來描述。MIME類型通常由剪貼板和拖放系統使用,以識別不同類型的數據。
拖動點(drag site):拖動的起始位置。
放下點(drop site):被拖動的對象放下的位置,若部件不能接受拖動的對象,Qt會改變光標的形狀(一個禁用形狀)來向用戶進行說明。
1、拖放的啓動和結束
(1)、啓動拖放:拖放通過調用QDrag::exec()函數而啓動,該函數是一個阻塞函數(但不會阻塞主事件循環),這意味着在拖放操作結束之前,不會返回該函數,調用QDrag::exe()函數後,Qt擁有對拖動對象的所有權,並會在必要時將其刪除。
2)、結束拖放:當用戶放下拖動或取消拖動操作時結束拖放。
2、拖放產生的過程及事件
(1)、啓動拖放後,會使數據被拖動,這時需要按住鼠標按鍵才能拖動需要拖動的數據,鬆開鼠標按鍵時意味着拖動結束。在這期間會產生如下事件
(2)、默認情況下,部件不接受放下事件。使用QWidget::setAcceptDrops()函數可設置部件是否接受放下事件(即,拖放完成時發送的事件)。只有在部件接受放下事件的情形下,纔會產生以下事件。
 QDragEnterEvent:拖動進入事件。當拖動操作進入部件時,該事件被髮送到部件,忽略該事件,將會導至後續的拖放事件不能被髮送,此時在該部件上光標通常會在外觀上顯示爲禁用的圖形。
 QDragMoveEvnet:拖動移動事件。當拖動操作正在進行時,以及當具有焦點時按下鍵盤的修飾鍵(比如Ctrl)時,發送該事件,要使部件能接收到該事件,則該部件必須接受QDragEnterEvent事件。
 QDropEvent:放下事件。在完成拖放操作時發送該事件,即當用戶在部件上放下一個對象時,發送此事件。要使部件能接收到該事件,則該部件必須接受QDragEnterEvent事件,且不能忽略QDragMoveEvnt事件。
 QDragLeaveEvent:當拖放操作離開部件時發送該事件,注意:要使部件能接收到該事件,必須要使拖動先進入該部件(即產生QDragEnterEvent事件),然後再離開該部件,纔會產生QDragLeaveEvent事件。因很少使用該事件,因此本文不做重點介紹。
 注:必須接受是指必須重新實現該事件的處理函數並接受該事件,不能忽略是指在處件事理函數中不明確調用ignore()函數忽略該事件。
 以上事件產生的順序爲(詳見圖9-2):QDragEnterEvent、QDragMoveEvnet、QDropEvent
在這裏插入圖片描述

3、編寫拖放程序的步驟
(1)、在需要接受放下數據的部件上調用QWidget::setAcceptDrops()函數以使該部件能接受拖放事件。
(2)、啓動拖放:通常在mousePressEvent()或mouseMoveEvent()函數中啓動拖放,記住啓動拖放就是調用QDrag對象的exec()函數,因此也可以在keyPressEvent()等函數中啓動拖放(因很少這樣做,所以本文不予介紹)。在此步把需要拖動的數據保存在QMimeData對象中。
(3)、重新實現需要接受放下數據的部件的dragEnterEvent()事件處理函數。
(4)、根據需要重新實現dragMoveEvent或dropEvent()函數
下面以實現代碼爲例進行講解
示例9.1:簡單的拖放

//m.h文件的內容
#ifndef M_H
#define M_H
#include<QtWidgets>
class C:public QPushButton{Q_OBJECT
public:	 C(QString t="",QWidget *p=0):QPushButton(t,p){}
void  mousePressEvent(QMouseEvent *e){  	//在該事件中啓動拖放
    		QDrag *dg=new QDrag(this);
      //將需要拖動的數據放入QMimedata對象中,該對象用於保存需要傳遞的數據,數據的內
//容完全由程序員自行設定。通常爲界面上所選擇內容。
    		QMimeData *md=new QMimeData;
    		md->setText("FFF");    			//這是md中存儲的內容(即拖放時傳遞的數據)。
    		dg->setMimeData(md);   			//步驟1:設置拖動的數據。該函數會獲得md的所有權。
    		dg->exec();         }   		//步驟2:啓動拖放
 	void dragEnterEvent(QDragEnterEvent  * e){
//步驟3:處理是否接受拖動事件。
    			e->accept();  			//接受拖動進入事件
//e->ignore();  	/*若忽略該事件,則不會再發送之後的事件,拖放至此結束,這會導致鼠標光標顯示爲禁用的圖形。*/
 }
 	void dropEvent(QDropEvent  * e){
		//步驟4:處理拖動中的數據(當然也可不作任何處理)
    		setText(e->mimeData()->text());	//設置此部件的文本爲拖動對象中的文本。
    		//此事件不影響後續事件,可接受也可忽略。
    		//e->accept();
    		//e->ignore();
 		}		};
class B:public QWidget{    Q_OBJECT
public: B(QWidget *p=0):QWidget(p){
    C *pb1=new C("AAA",this);    pb1->move(22,22);  pb1->setIcon(QIcon("F:/1i.png"));
    C *pb2=new C("BBB",this);    pb2->move(99,22);
    pb2->setAcceptDrops(true);     		//pb2接受放下事件
pb1->setAcceptDrops(0);   }	};  		//pb1禁止放下事件。
#endif // M_H

//m.cpp文件的內容
#include "m.h"
int main(int argc, char *argv[]){    QApplication app(argc,argv);
    B w;    w.resize(444,355);    w.show();    return app.exec();  }

運行結果及說明見圖9-3
在這裏插入圖片描述

9.1.2 拖放動作(或稱爲放置動作)

拖放動作是指用戶希望怎樣處理拖放的數據,比如移動、複製、還是創建由目標到源的鏈接等。拖放動作由Qt::DropAction枚舉描述(其取值見第8章表8-3)
QDrag::exe()函數的原型之一如下,詳見後文對QDrag類的講解。

Qt::DropAction QDrag::exec(Qt::DropActions supportedActions, Qt::DropAction defaultDropAction)

1、可能的拖放動作,實際的拖放動作,建議的拖放動作
可能的拖放動作是指用戶在拖放時可能會執行的拖放動作,用戶在拖放時通常可由用戶選擇,比如可以選擇移動、複製或鏈接(可通過同時按住鍵盤修飾鍵進行改變)等動作中的一種,這些動作都是可能的拖放動作。可能的拖放動作在QDrag::exe()函數的第1個參數中指定,同時該函數的返回值是最終的實際拖放動作。
實際的拖放動作是指拖放被最終放置時實際執行的動作,實際拖放動作在dropEvent()函數中使用QDropEvent::setDropAction()函數(還需在之後調用accept()函數)設置,該函數會影響QDrag::exec()函數的返回值。
建議的拖放動作是指當用戶執行拖動而不使用修飾鍵時的默認動作,建議拖放動作可在QDrag::exec()函數的第2個參數中指定,該參數的設置會影響拖動時鼠標光標右下角的外觀,另外QDropEvent::acceptProposedAction()函數表示設置執行操作爲建議操作並接受該事件。
以上三種拖放動作常常相互關聯,比如用戶在拖動時通常可以執行移動、複製或鏈接等動作(可能的拖放動作)中的一種,然而應用程序在拖放被最終放置時並不知道用戶到底需要執行哪種操作,若用戶未指定需要執行的可能的拖放動作中的哪一種動作時,應用程序可以使用設置的建議動作,作爲需要執行的動作。
2、各拖放動作之間的關係
(1)、QDrag::exec()函數的規則
 若QDrag::exec()未指定建議拖放動作,則依順序移動、複製、鏈接進行選擇
 若QDrag::exec()函數在第2個參數上指定了建議拖放動作,但該動作不在可能的拖放動作組合之中,則使用默認的複製拖放動作。比如
QDrag *dg = new QDrag(this);
……
dg->exec(Qt::MoveAction|Qt::CopyAction, Qt::LinkAction); //建議動作爲複製。
(2)、QDropEvent::setDropAction()函數的規則
 使用setDropAction()函數設置拖放動作之後應使用accept()函數,而不應使用QDropEvent::acceptProposedAction()函數(因爲該函數會重置拖放動作爲建議拖放動作)
 若QDropEvent::setDropAction()函數設置的拖放動作不在可能的拖放動作組合之中,則使用建議拖放動作。
(3)、dropEvent()函數的規則,該函數是否接受事件直接影響到QDrag::exec()函數的返回值,其規則如下
 若在該函數內調用ignore(),則exec()函數返回Qt::IgnoreAction
 若在該函數內調用accept(),則exec()函數返回在該函數中使用setDropAction()函數設置的拖放動作。詳細規則見示例9.2。

示例9.2:各種拖放動作

Qt::DropAction d= QDrag::exe(Qt::MoveAction | Qt::CopyAction);   //可能的拖放動作(移動、複製)
   		…
 	void drogEvent(QDropEvent *e){
   		//下面分情形講解該函數對exe()返回值(即以上語句的d)的影響
  		//情形1:d = Qt::MoveAction
  		if(…){	e->setDropAction(Qt::MoveAction);		e->accept();}
//情形2:d = Qt::CopyAction
  		else if(…){	e->setDropAction(Qt::CopyAction);	e->accept();}
//情形3:d = 建議的拖放動作
else if(…){	e->acceptProposedAction();	}
//情形4:d = Qt::IgnoreAction
else if(…){	e->ingore();	}   //該部件不接受放置動作
//情形5:d = 建議的拖放動作
else if(…){
e->setDropAction(Qt::MoveAction);
e->acceptProposedAction();  /*使用該函數會把最終拖放動作重置爲建議的拖放動作,因此調用setDropAction()之後應調用accept()函數。*/
e->accept();}
		//情形6:d = Qt::IgnoreAction
else if(…){
e->setDropAction(Qt::MoveAction);
e->ingore();}    	//該函數表示不接受放置操作,這會使之前設置的拖放動無效。
//情形7:d = 建議的拖放動作,因爲Qt::LindAction不是可能的拖放動作之一。
else if(…){e->setDropAction(Qt::LinkAction);e->accept();} 	}

3、拖放動作及拖放的程序設計原則
(1)、若在mouseMoveEvent()函數中啓動拖放,則可以編寫避免用戶因爲手握鼠標抖動而產生的拖動,這比在mousePressEvent()函數中啓動拖放效果更好。
(2)、在QDrag::exe()函數的參數中指定可能的拖放動作,比如在其中同時指定移動、複製、鏈接等;但最終是否接受這些動作,由後續的事件處理函數進行判斷,詳見後文。另外需要注意的是QDrag::exec()函數雖是阻塞函數,但在執行完該函數(比如釋放鼠標按鈕完成拖放時)後程序會返回該函數,然後接着執行之後的語句,exec()函數返回的是用戶實際執行的動作。
(3)、dragEnterEvent()函數通常根據該部件或實際使用情況進行篩選,比如若該部件不接受圖片數據,則忽略對該動作的接受,從而阻止事件被進一步傳遞。
(4)、若重新實現了dragMoveEvent()函數,則還可以在該函數內進行進一步的設置,比如默認爲複製動作,若用戶拖動的同時按下了Shift鍵,則設置爲移動動作,若按下了Ctrl鍵,則爲複製動作,若按下了Alt鍵則爲鏈接動作等,這些設置可以影響鼠標光標在外觀上的顯示,比如複製會在光標右下角顯示一個“+”符號等。另外,在該函數內還可以限制用戶拖動到該部件中的某一範圍,比如拖動到某矩形範圍內時,該部件才接受拖放,否則被忽略等。注意:若在dragEnterEvent()函數內也設置了拖放動作,同樣會改變光標的外觀但只會改變進入部件時的外觀,光標最終的外觀以dragMoveEvent()函數設置的爲準(因爲該函數位於dragEnterEvent()之後執行)。
(5)、在drogEvent()函數內最終決定對拖放的數據的處理,以及用戶實際執行的拖放動作,因此該函數決定着QDrag::exe()函數的返回值。這裏要注意的是,對於移動動作,通常原始數據應由源部件(啓動拖放的部件)進行刪除,因此當drogEvent()處理完數據之後,應把拖放動作設置爲移動,QDrag::exec()函數會返回在drogEvent()函數中設置的動作,然後源部件根據QDrag::exe()的返回值是否是移動動作,而作出是否刪除原始數據的決定。注:dragEnterEvent()和dragMoveEvent()對拖放動作的設置不會影響QDrag::exe()的返回值。
(6)、注意:在源部件中創建的QMimeData和QDrag對象不應由程序員銷燬,因爲Qt會自動銷燬,若程序員銷燬了,則可能會出現多次delete同一個指針的錯誤。
(7)、以上只是通常在各函數中的做法,當然你也可以不按照這些步驟來實現,從之前的拖放示例可以看到,對拖放的處理完全是任意的。
(8)、注意:Qt爲某些部件提供了一些標準的拖放支持,在繼承這些部件實現拖放時需要重新實現dragEnterEvent()、dropEvent(),另外還可能需要重新實現dragMoveEvent()函數,以避免與標準實現的拖放支持相沖突或產生預料之外的結果。

示例9.3:拖放動作
//m.h文件的內容  
#ifndef M_H
#define M_H
#include<QtWidgets>
#include<QDebug>
class C:public QPushButton{Q_OBJECT
public:    QPoint p;   										//用於保存點擊鼠標的位置
    C(QString t="",QWidget *pp=0):QPushButton(t,pp){}
void  mousePressEvent(QMouseEvent *e){    p=e->pos(); }   	//第一次點擊鼠標的位置
 	void  mouseMoveEvent(QMouseEvent *e){
      //若拖動的距離大於5個像素則啓用拖放(避免抖動)。
    		if((e->pos()-p).x()>=5||(e->pos()-p).y()>=5) {
    			QDrag *dg=new QDrag(this);    QMimeData *md=new QMimeData;
    			md->setText("FFF");    		dg->setMimeData(md);
    //啓動拖放,該數據可複製、移動、鏈接,具體是否接受這些動作,需由後續程序決定。
//若drogEvent()函數把拖放動作設置爲移動,則需要對原始數據作進一步處理,注意:在完成拖放
//後會返回exec()函數繼續執行其後的語句。。
    			if(dg->exec(Qt::CopyAction|Qt::MoveAction|Qt::LinkAction)==Qt::MoveAction)
   			 	qDebug()<<"AAA";  //本示例沒有可刪除的原始數據,因此只簡單輸出字符串用於測試。
  } 		//if結束
//注:鼠標移動距離也可使用以下語句判斷,其中manhattanLength()表示曼哈頓距離,startDragDistance
//表示系統推薦的拖動起始距離。
    		//if((e->pos()-p).manhattanLength()>=QApplication::startDragDistance())
}    
 	void dragEnterEvent(QDragEnterEvent  * e){
//若拖動的數據中不包含文本FFF則忽略該事件,否則接受該事件。
   		if(e->mimeData()->text()!="FFF")   e->ignore();    else    e->accept();	}
 	void dragMoveEvent(QDragMoveEvent  * e){
/*以下設置會改變鼠標光標的外觀。若拖動的同時按下了CTRL、ALT、SHIFT鍵,則把施放動作設置爲複製、移動、鏈接,否則爲複製。*/
 		if(e->keyboardModifiers()==Qt::CTRL)		e->setDropAction(Qt::CopyAction);
  		else if(e->keyboardModifiers()==Qt::SHIFT)  e->setDropAction(Qt::MoveAction);
  		else if(e->keyboardModifiers()==Qt::ALT)   	e->setDropAction(Qt::LinkAction);
  		else e->setDropAction(Qt::CopyAction);
//限制拖動的範圍:若光標位於矩形r之內,則接受該事件,否則忽略該事件。
   		QRect r(0,0,111,33);	
if(r.contains(e->pos())){    e->accept()	;}    else e->ignore();		}
 	void dropEvent(QDropEvent  * e){
/*若拖動的源和目標在同一個部件,則什麼也不做。注意應使用return;跳出函數,若使用ignore()或accept(),程序還會繼續執行之後的語句。*/
		if(e->source()==this) return;
    		setText(e->mimeData()->text());
    		e->setDropAction(Qt::MoveAction); 	//把拖放動作設置爲移動。
    		e->accept();  }};		//使用此步驟會把QDrag::exe()函數的返回值設置爲上面設置的移動動作
class B:public QWidget{    Q_OBJECT
public:    
B(QWidget *p=0):QWidget(p){
    		C *pb1=new C("AAA",this);    pb1->move(22,22);
    		C *pb2=new C("BBB",this);    pb2->resize(111,66);   pb2->move(99,22);
    		pb1->setIcon(QIcon("F:/1i.png"));    
pb2->setAcceptDrops(true);    pb1->setAcceptDrops(0);       }};
#endif // M_H

//m.cpp文件的內容
#include "m.h"
int main(int argc, char *argv[]){    QApplication app(argc,argv);
    B w;    w.resize(444,355);    w.show();    return app.exec();  }

運行結果及說明(見圖9-4),當拖放被成功放置到按鈕BBB上時,程序會輸出字符串AAA。
在這裏插入圖片描述

9.1.3 使用拖放打開文件

拖放文件的基本步驟:文件需要使用QFile類來打開,然後才能讀取或存入其內容,因此對拖放的文件進行處理,其實就是獲取文件的地址,而地址是使用URL來表示的,因此首先需要判斷拖放的數據是否含有URL,然後讀取出URL中保存的文件的地址,再打開文件,然後讀取文件的內容,有關流和文件的內容本章暫時不用深入瞭解,明白示例9.4代碼的作用即可。

示例9.4:拖放文件
//m.h文件的內容
#ifndef M_H
#define M_H
#include<QtWidgets>
class C:public QPushButton{Q_OBJECT
public:    C(QString t="",QWidget *p=0):QPushButton(t,p){}
 	void dragEnterEvent(QDragEnterEvent  * e){
		//若拖動的數據包含一個URL則接受該事件,否則忽略該事件。
   		if(e->mimeData()->hasUrls()){	e->accept();   }   	else e->ignore();	 }
 	void dropEvent(QDropEvent  * e){
   		const QMimeData *pm=e->mimeData();
    		QList<QUrl> u=pm->urls();    				//讀取出URL的地址列表。
   	 	QString pth=u.at(0).toLocalFile();   			//將地址轉換爲QString
    		if(!pth.isEmpty()){     					//判斷地址pth是否爲空
        		QFile file(pth);     					//創建文件file
            	if(!file.open(QIODevice::ReadOnly));   	//以只讀方式打開文件
        			QTextStream in(&file);     			//創建流用於讀取文件的內容。
          		setText(in.readAll());    } } }; 	//讀出文件的內容,並設置爲該部件的文本
class B:public QWidget{    Q_OBJECT
public:
B(QWidget *p=0):QWidget(p){
/*注:實際編程時只需把按鈕替換爲QTexeEdit之類的部件即可,此處爲避免複雜性及明白其原理,使用簡單的按鈕就可以了。*/
    		C *pb1=new C("AAA",this);    pb1->move(22,22);   pb1->setAcceptDrops(true);   }		};
#endif // M_H

//m.cpp文件的內容
#include "m.h"
int main(int argc, char *argv[]){    QApplication app(argc,argv);
    B w;    w.resize(444,355);    w.show();    return app.exec();  }

運行結果及說明見圖9-5
在這裏插入圖片描述

9.2 與拖放事件有關的類及函數

本小節所講的內容在上一小節幾乎都已介紹了,此處僅列出其原型並作一簡要介紹。

9.2.1 QDropEvent類

1、QDropEvent繼承自QEvent,在完成拖放操作時發送該事件,具體規則見前文
2、QDropEvent類中的函數

1)、QDropEvent(const QPointF &pos, Qt::DropActions actions, const QMimeData *data,  Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Type type = Drop);
	構造函數,因很少需要創建該事件,所以僅列出其原型
2)、const QMimeData *mimeData() const;   			//返回被放置到部件上的QMimeData對象。
3)、QPoint pos() const;   						//返回鼠標光標的位置
4)、const QPointF &posF() const;					//返回鼠標光標的位置
5)、Qt::KeyboardModifiers keyboardModifiers() const;  //返回按下的鍵盤修飾鍵(比如Ctrl)
6)、Qt::MouseButtons mouseButtons() const;     		//返回按下的鼠標按鈕。
7)、Qt::DropAction dropAction() const;				//返回數據執行的拖放動作
void setDropAction(Qt::DropAction action)	
	設置數據執行的拖放動作,使用該函數後應調用accept()而不是acceptProposedAction()。
8)、void acceptProposedAction();  				//把拖放操作設置爲建議的操作並接受該事件。
9)、Qt::DropActions possibleActions() const;   
	返回可能的拖放動作或其組合,即QDrag::exe()函數中指定的參數。
10)、Qt::DropAction proposedAction() const;  		//返回建議的拖放動作。
11)、QObject *source() const
	若拖動操作的源部件是該程序中的一個部件,則返回該源部件,否則返回0,源部件是實例化QDrag對象的第一個參數。比如QDrag *dg=new QDrag(this);則該函數將返回部件this。

9.2.2 QDragMoveEvent類

QDragMoveEvent繼承自QDropEvent,當拖動操作正在進行時,以及當具有焦點時按下鍵盤的修飾鍵(比如Ctrl)時,發送該事件,具體規則見前文
QDragMoveEvent類中的函數如下

1)、QDragMoveEvent(const QPoint &pos, Qt::DropActions actions, const QMimeData *data, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Type type = DragMove)
	構造函數,因很少需要創建該事件,所以僅列出其原型
2)、void accept(const QRect &rectangle)
	與accept()相同,但若以後的移動仍在矩形rectangle內,則是可以接受的,這對於源在計時器事件中滾動非常有用。該函數可提高性能,但有可能被底層系統忽略。
3)、void ignore(const QRect &rectangle)
	與accept(const QRect&)相反,在矩形內移動是不可接受的,且將被忽略。
4)、QRect answerRect() const
	若accept()函數的參數設置了矩形,則返回該矩形,否則返回的該矩形的左上角是鼠標光標的位置,其大小爲1*1,即返回的矩形爲(pos().x(), pos.y(), 1, 1);

9.2.3 QDragEnterEvent類和QDragLeaveEvent類

QDragEnterEvent繼承自QDragMoveEvent,當拖動操作進入部件時,該事件被髮送到該部件,具體規則見前文
QDragEnterEvent類僅有一個構造函數,原型如下所示

QDragEnteVrEvent(const QPoint &point, Qt::DropActions actions, const QMimeData *data, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
QDragLeaveEvent繼承自QEvent,當拖放操作離開部件時發送該事件,具體規則見前文,不應創建一個QDragLeaveEvent類,該類依賴於Qt的內部狀態。該類僅有一個默認構造函數。

9.2.4 QWidget類中與拖放有關的函數

QWidget類中與拖放有關的函數就是拖放事件的處理函數,這些函數都是受保護的虛擬函數,現列出如下:

virtual QWidget::dragEnterEvent(QDragEnterEvent *e);   	//受保護的,虛擬的
   virtual QWidget::dragMoveEvent(QDragMoveEvent *e);   	//受保護的,虛擬的
   virtual QWidget::dropEvent(QDropEvent *e);   			//受保護的,虛擬的
   virtual QWidget::dragLeaveEvent(QDragLeaveEvent *e);   	//受保護的,虛擬的

9.3 QDrag類

QDrag繼承自QObject,該類支持基於QMimeData對象數據的拖放。該類主要成員函數的使用方式在前文已介紹過,該類的其他成員函數可設置拖放時的外觀等其他設置,比如拖放時顯示一個圖標而不是鼠標光標等。
QDrag類中的函數如下

1)、QDrag(QObject *dragSource)
	構造函數,注意:該類沒有默認構造函數,必須爲其指定一個參數,這個參數通常會作爲source()函數返回的對象。
2)、Qt::DropAction exec(Qt::DropActions supportedActions = Qt::MoveAction)
Qt::DropAction exec(Qt::DropActions supportedActions, Qt::DropAction defaultDropAction)
	以上函數表示,啓用拖放操作,並在拖放完成時返回最終的拖放動作的值。
	可能的拖放動作由supportedActions指定,參數defaultDropAction用於設置建議的拖放動作,若該動作不在supportedActions的組合中,則建議的拖放動作爲複製。若未使用defaultDropAction參數,則默認建議拖放動作按照順序移動、複製、鏈接進行選擇。
	注:在Linux和macOS上,拖放操作不會阻止事件循環,其他事件仍會傳遞給應用程序。但在windows上,Qt事件循環在操作過程中會被阻塞。
3)、QMimeData *mimeData() const;        	//返回拖動的QMimeData對象
void setMimeData(QMimeData *data)
	設置要拖動的QMimeData對象(即拖動的數據),該函數會獲得data的所有權。
4)、QPixmap dragCursor(Qt::DropAction action) const
void setDragCursor(const QPixmap &cursor, Qt::DropAction action)
	設置相對於拖放動作的拖動光標(即拖動時的光標)爲cursor,該函數可使拖動時使用本地系統之外的光標(即可改變光標的外形),若cursor爲空,則恢復本地系統的光標,action只能是CopyAction、MoveAction、LinkAction,其他值將會被忽略。
	示例(見圖9-6)
QDrag *dg = new QDrag(this);
……
dg->setDragCursor(QPixmap("F:/1i.png"), Qt::CopyAction);
dg->exec(Qt::MoveAction|Qt::CopyAction, Qt::CopyAction); 

在這裏插入圖片描述

5)、QPixmap pixmap() const
void setPixmap(const QPixmap &pixmap)
	把拖動操作中的數據顯示的像素圖設置爲pixmap。見圖9-7
6)、QPoint hotSpot() const
void setHotSpot(const QPoint &hotspot)
	將熱點(即光標的實際有效點)設置爲相對於像素圖左上角的位置hotspot,注:在X11上,像素圖可能無法跟上鼠標移動。原理見圖9-8
7)、static void cancel();    					//取消由Qt啓動的拖放操作。靜態的。qt5.7
8)、Qt::DropAction defaultAction() const;   		//返回該拖放操作的默認建議放置動作。
9)、Qt::DropActions supportedActions() const;	//返回此拖放可能的拖放動作組合。
10)、QObject *source() const;				//返回拖動對象的源部件(即啓用拖放的部件)。
11)、QObject *target() const;				
	返回拖放的目標部件(即拖放對象被放下的部件)。可把該函數放置於exec()之後來獲取放置的目標,比如
QDrag *dg = new QDrag(this);
……
dg->target();     	//此時不能成功獲取放置的目標部件。
dg->exec(); 
dg->target();		//獲取放置的目標部件。
12)、void actionChanged(Qt::DropAction action); 	//當與拖動相關的動作改變時,發送該信號。信號
13)、void targetChanged(QObject *newTarget); 	//當拖放的目標部件發生變化時,發送該信號。信號

在這裏插入圖片描述

在這裏插入圖片描述

本文作者:黃邦勇帥(原名:黃勇)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章