--------------------------------------------------------------------------------------------------------------------------------
QPixmap輪廓剪裁?
?去掉Pixmap的外圍部分,如下:
QPixmap pixmap("./img");
//調用createHeuristicMask(),再調用setMask
pixmap.setMask(pixmap.createHeuristicMask());
效果對比:
?——》
可以看到以圖像內輪廓為邊界線,無關的白色區域被抹去了
---------------------------------------------------------------------------------------------------------------------------------
QGraphicsItem中開啟拖動QDrag
重寫QGraphicsItem的鼠標移動事件,在移動事件中開啟拖動
void ColorItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event) {//判斷拖動距離,使用qt推薦的距離QApplication::startDragDistance()if (QLineF(event -> screenPos(), event -> buttonDownScreenPos(Qt::LeftButton)).length() < QApplication::startDragDistance()) {return;}//創建拖動對象QDrag * drag = new QDrag(event -> widget());//創建數據對象,并設置給本次拖動,這樣本次拖動就有數據了QMimeData * mime = new QMimeData;drag -> setMimeData(mime);QImage image(":/images/head.png");mime -> setImageData(image);//可以設置圖像數據mime -> setColorData(color);//顏色數據mime -> setText(QString("#%1%2%3").arg(color.red(), 2, 16, QLatin1Char('0')).arg(color.green(), 2, 16, QLatin1Char('0')).arg(color.blue(), 2, 16, QLatin1Char('0')));//字符串數據QPixmap pixmap(34, 34);pixmap.fill(Qt::white);drag -> setPixmap(pixmap);//設置拖動過程中在鼠標處顯示的圖片drag->setHotSpot(QPoint(15, 20));//設置鼠標在圖片里的位置偏移drag -> exec();//開啟本次拖動
}
qt推薦的拖動距離閾值:QApplication::startDragDistance() ,超過這個距離才啟用拖動
創建的拖動對象(QDrag * drag)可以指定父對象也可以不指定,他會在這次拖動結束時自動釋放,無論這次拖動有沒有被drop接收?
創建的數據對象QMimeData在設置給拖動對象后也不用管他的釋放(drag -> setMimeData(mime);),會跟著拖動對象一起釋放
同時還可以設置鼠標在拖動的過程下面跟隨著圖片drag -> setPixmap(pixmap)
拖動執行函數
Qt::DropAction QDrag::exec(Qt::DropActions supportedActions = Qt::MoveAction)
Qt::DropAction QDrag::exec(Qt::DropActions supportedActions, Qt::DropAction defaultDropAction)
常用的行為就是復制、移動、空操作?
這是一個阻塞函數,
拖動結束后可以獲取到返回值,?來獲取到本次拖動最終執行了什么行為
supportedActions可以指定本次拖動支持的行為
defaultDropAction可以指定本次拖動默認的行為
---------------------------------------------------------------------------------------------------------------------------------
QMimeData攜帶自定義數據
其中QMimeData可以設置自定義的數據,需要繼承重寫或者調用setData方法??
- 使用setData方法
他的第一個參數是一個字符串,指定數據的類型,可以自己定義
第二個參數是QByteArray,即要傳輸的數據
比如數據是1個結構體
結構體需要提供轉成QByteArray的方法和從QByteArray轉到結構體的方法
// 自定義數據結構
struct Person {QString name;int age;// 序列化到 QByteArrayQByteArray serialize() const {QByteArray data;QDataStream stream(&data, QIODevice::WriteOnly);stream << name << age;return data;}// 從 QByteArray 反序列化static Person deserialize(const QByteArray &data) {QDataStream stream(data);QString name;int age;stream >> name >> age;return {name, age};}
};
創建自定義數據?,指定類型的字符串可以自己隨便寫
// 創建自定義數據
Person person{"Alice", 30};// 序列化并設置到 QMimeData
QMimeData *mimeData = new QMimeData;
mimeData->setData("application/x-custom-person", person.serialize());
接收方解析自定義數據
// 獲取 QMimeData(例如從拖放事件)
const QMimeData *mimeData = event->mimeData();// 檢查是否存在自定義數據
if (mimeData->hasFormat("application/x-custom-person")) {// 提取數據并反序列化QByteArray data = mimeData->data("application/x-custom-person");Person person = Person::deserialize(data);qDebug() << "Received person:" << person.name << person.age;
}
- 最小子類化QMimeData
即不重寫相關虛函數,直接將數據作為其子類的成員變量,如下
比如把Person傳出去
//自定義數據
struct Person{QString name="11" ;int age=15;
};//子類化QMimeData,將自定義的類型作為其成員變量
class PersonMimeData: public QMimeData
{
public:Person person;//...還可以攜帶N多數據成員
};
創建自定義的MimeData
//創建自定義的MimeData,并初始化里面自定義的數據,然后設置給QDrag對象
QDrag * drag = new QDrag(event -> widget());
PersonMimeData * mime = new PersonMimeData;
mime -> person = {"May", 18};
drag -> setMimeData(mime);
接受方解析收到的數據
//從事件中獲取mimedata(例如拖放事件),并強轉成對應的類型
PersonMimeData * data = (PersonMimeData * ) event -> mimeData();
//取出內部攜帶的數據
qDebug() << data -> person.name << " " << data -> person.age;
---------------------------------------------------------------------------------------------------------------------------------
QGraphicsItem中的drop拖放
- 需要QGraphicsItem接受拖放
setAcceptDrops(true);
- 需要重寫dragEnterEvent事件,拖動進入事件
可對拖動攜帶數據做一些判斷,判斷是否有想要的數據
若需要接受拖動,則需要顯示的調用?event->setAccepted(true),否則后面的拖放事件會收不到數據
void CustomItem::dragEnterEvent(QGraphicsSceneDragDropEvent * event) {//可以對拖過來的數據進行一些判斷,有沒有想要的數據if (event -> mimeData() -> hasColor()) {event -> setAccepted(true); //然后要接受這次拖放,否則后面drop事件無法收到拖放//同時可以改變下item的樣式,isDragging = true; //自己定義的標志變量,標記拖動進入了update();} else {event -> setAccepted(false); //否則拒絕這次拖放}
}
- 需要重寫拖放事件
主要就是獲取本次拖放的mimeData
設置本次拖放最后采用的行為
void CustomItem::dropEvent(QGraphicsSceneDragDropEvent *event)
{isDragging = false;update();auto data=event->mimeData();//取mimeData里的數據//data->text();...event->setDropAction(Qt::CopyAction);//還可以設置本次拖放最后使用的行為,QDrag的exec函數的返回值就會變成這里設置的
}
- 需要重寫拖動離開事件
主要就是設置標記變量,表示拖動離開了
同時刷新下樣式
void CustomItem::dragLeaveEvent(QGraphicsSceneDragDropEvent * event) {Q_UNUSED(event);isDragging = false;update();
}
---------------------------------------------------------------------------------------------------------------------------------
并行動畫組QParallelAnimationGroup
可以在動畫組里添加多個動畫,這些動畫可以同時進行
QParallelAnimationGroup * animation = new QParallelAnimationGroup(this);QPropertyAnimation * a1 = new QPropertyAnimation(target1, "rotation");
a1 -> setStartValue(5);
a1 -> setEndValue(-20);
animation -> addAnimation(a1);QPropertyAnimation * a2 = new QPropertyAnimation(target2, "rotation");
a2 -> setStartValue(15);
a2 -> setEndValue(-30);
animation -> addAnimation(a2);
//.....可以添加多個動畫,這些動畫可以同時執行animation -> setLoopCount(-1); //無限循環
animation -> start(); //并行動畫組開啟,多個動畫同時運行
其中animation -> setLoopCount(-1); 參數設置為-1,可讓動畫無限循環
---------------------------------------------------------------------------------------------------------------------------------
正弦動畫曲線
動畫曲線類型QEasingCurve::SineCurve,正弦曲線
可以使動畫在1個執行周期內產生一來一回的效果,來和回是完全相反的兩個動畫,如下
其他曲線沒有來回的效果
比如QEasingCurve::OutQuad,如下