1. 程式人生 > >Qt淺談之十二:拖拽文字圖片

Qt淺談之十二:拖拽文字圖片

一、簡介

       首先選擇窗體顯示風格,接著顯現拖拽效果,文字和圖示都可以作為拖拽的物件,在窗體中的文字圖示可以拖拽到視窗的任意位置,它們在兩個獨立執行的程式間也可相互拖拽(此時是複製一份到拖拽目的程式視窗中),文字拖拽的範圍更廣(須注意字符集的轉換)。本文解決這種比較神祕的效果,熟悉拖拽的基本流程。

二、執行圖

(1)總體效果圖如下圖1所示。左邊風格設定,中間文字區,右側拖拽區。

(2)拖拽的實現過程,如下圖2所示。

實現拖拽最基本的工作有3部分:一、在可拖拽物件的mousePressEvent()函式中構建QDrag物件,並呼叫start()函式等待DropAction的返回。二、在放置可拖拽物件的容器類中,實現dragEnterEvent()函式,判斷並設定應採用何種DropAction,返回給start()函式。三、在放置可拖拽物件的容器類中,實現dragEnterEvent()函式,建立一個新的可拖拽物件並在當前滑鼠位置進行顯示,同時判斷並設定應採用何種DropAction,返回給start()函式。

三、詳解

1、窗體風格

(1)系統支援的7中窗體風格,如下圖所示。

QLabel *label = new QLabel(QObject::tr("窗體風格:"));
QComboBox *styleComboBox = new QComboBox;
styleComboBox->addItems(QStyleFactory::keys());
styleComboBox->setCurrentIndex(5);

void DragWidget::slotChangeStyle(QString style)
{
    QApplication::setStyle(QStyleFactory::create(style));
    QApplication::setPalette(QApplication::style()->standardPalette());
}
      QStyleFactory::keys()獲得當前系統支援的窗體風格,QApplication的setStyle()函式設定為剛建立的風格,呼叫setPalette()完成窗體顯示的改變。

2、拖拽文字

(1)同一例項程式拖拽(移動)

中間控制元件的文字都拖放到右側,通過游標的選擇分解它們。

void DragLabel::mousePressEvent(QMouseEvent * e)
{
     QString str = text();
     QPixmap pix;
     pix = pix.grabWidget(this);

     QByteArray data;
     QDataStream stream(&data,QIODevice::WriteOnly);
     stream << str << QPoint(e->pos()-rect().topLeft());
     QMimeData *mimeData = new QMimeData;
     mimeData->setData("Drag-Text",data);
     mimeData->setText(str);

     QDrag *drag = new QDrag(this);
     drag->setMimeData(mimeData);
     drag->setHotSpot(QPoint(e->pos() - rect().topLeft()));
     drag->setPixmap(pix);

     hide();

     Qt::DropAction dropAction = drag->start(Qt::CopyAction | Qt::MoveAction);

     if (dropAction == Qt::MoveAction)
         close();
     else
         show();
}

(2)不同例項程式拖拽(複製)

左側文字向右側程式中拖拽。


(3)外部程式拖拽互動

文字間的來回移動,以空格為分隔標誌,也可以複製一段文字,但暫時沒法控制文字的長度顯示。

void DragWidget::dropEvent(QDropEvent *e)
{
    if (e->mimeData()->hasFormat("Drag-Icon")) {
        QByteArray data = e->mimeData()->data("Drag-Icon");
        QDataStream stream(&data,QIODevice::ReadOnly);
        QPixmap pix;
        QPoint offset;
        stream >> pix >> offset;

        DragIcon *icon = new DragIcon(pix,this);
        icon->move(e->pos() - offset);
        icon->resize(50, 50);
        icon->show();
        if (children().contains(e->source())) {
          e->setDropAction(Qt::MoveAction);
          e->accept();
        }
        else e->acceptProposedAction();
    }
    else if (e->mimeData()->hasFormat("Drag-Text"))
    {
        QByteArray data = e->mimeData()->data("Drag-Text");
        QDataStream stream(&data,QIODevice::ReadOnly);
        QString text;
        QPoint offset;
        stream >> text >> offset;

        DragLabel *label = new DragLabel(text,this);
        label->move(e->pos() - offset);
        label->show();

        if (children().contains(e->source())) {
          e->setDropAction(Qt::MoveAction);
          e->accept();
        }
        else  e->acceptProposedAction();
    }
    else if (e->mimeData()->hasText())
    {
        QStringList strList = e->mimeData()->text().split(QRegExp("\\s+"),QString::SkipEmptyParts);
        QPoint pos = e->pos();

        foreach(QString str, strList) {
          DragLabel *dragLabel = new DragLabel(str,this);
          dragLabel->move(pos);
          dragLabel->show();
          pos += QPoint(dragLabel->width(),0);
        }
       if (children().contains(e->source())) {
          e->setDropAction(Qt::MoveAction);
          e->accept();
       }
       else {
         e->acceptProposedAction();
       }
    }
    else {
        e->ignore();
    }
}
     上程式碼的if判斷可知,拖拽文字不僅支援自定義的格式hasFormat("Drag-Text"),而且還支援簡單的文字格式e->mimeData()->hasText(),因此其他的文字也可來回共享(圖片僅支援自己的格式)。

3、拖拽圖示

(1)同一例項程式拖拽(移動)

void DragIcon::mousePressEvent(QMouseEvent * e)
{
    if(e->button() == Qt::LeftButton)
        startPos = e->pos();
}

void DragIcon::mouseMoveEvent(QMouseEvent * e)
{
    if (!e->buttons()&Qt::LeftButton)
        return;
    if ((e->pos() - startPos).manhattanLength() < QApplication::startDragDistance())
        return;

    QPixmap pix = *pixmap();

    QByteArray data;
    QDataStream stream(&data,QIODevice::WriteOnly);
    stream << pix << QPoint(e->pos()-rect().topLeft());
    QMimeData *mimeData = new QMimeData;
    mimeData->setData("Drag-Icon",data);

    QDrag *drag = new QDrag(this);
    drag->setMimeData(mimeData);
    drag->setHotSpot(QPoint(e->pos() - rect().topLeft()));
    drag->setPixmap(pix);

    hide();

    Qt::DropAction dropAction = drag->start(Qt::CopyAction | Qt::MoveAction);

    if (dropAction == Qt::MoveAction)
        close();
    else
        show();
}
void DragWidget::dragEnterEvent(QDragEnterEvent *e)
{
    if (e->mimeData()->hasText() || e->mimeData()->hasFormat("Drag-Icon"))
    {
        if(children().contains(e->source()))
        {
            e->setDropAction(Qt::MoveAction);
            e->accept();
    }
    else
        e->acceptProposedAction();
    }
}

void DragWidget::dragMoveEvent(QDragMoveEvent *e)
{
    if (e->mimeData()->hasText() || e->mimeData()->hasFormat("Drag-Icon"))
    {
        if(children().contains(e->source()))
        {
            e->setDropAction(Qt::MoveAction);
            e->accept();
    }
    else
        e->acceptProposedAction();
    }
}
在本視窗的右側元件中可以來回拖放圖片,因改程式自定義了圖片格式hasFormat("Drag-Icon"),因此其他的圖片無法拖入。

(2)不同例項程式拖拽(複製)

void DragWidget::dropEvent(QDropEvent *e)
{
    if (e->mimeData()->hasFormat("Drag-Icon")) {
        QByteArray data = e->mimeData()->data("Drag-Icon");
        QDataStream stream(&data,QIODevice::ReadOnly);
        QPixmap pix;
        QPoint offset;
        stream >> pix >> offset;

        DragIcon *icon = new DragIcon(pix,this);
        icon->move(e->pos() - offset);
        icon->resize(50, 50);
        icon->show();
        if (children().contains(e->source())) {
          e->setDropAction(Qt::MoveAction);
          e->accept();
        }
        else e->acceptProposedAction();
    }
//.........................
}

四、總結

(1)本文僅簡單總結,還可以擴充套件到類似於剪貼簿的機制,拖拽文字可以加入字符集的轉換,拖拽圖片可以考慮外部圖片的轉換,還可以擴充套件到檔案的拖拽。

(2)對部分程式碼的理解也是不太深入,還得進一步深究。

(4)本人思路有限,若有更好的設計建議,也可發郵件溝通,在此先感謝!郵箱地址[email protected]

相關推薦

Qt文字圖片

一、簡介        首先選擇窗體顯示風格,接著顯現拖拽效果,文字和圖示都可以作為拖拽的物件,在窗體中的文字圖示可以拖拽到視窗的任意位置,它們在兩個獨立執行的程式間也可相互拖拽(此時是複製一份到拖拽目的程式視窗中),文字拖拽的範圍更廣(須注意字符集的轉換)。本文解決這種

QtTCP和UDP(之一)

一、簡介        Qt使用QtNetwork模組來進行網路程式設計,提供了一層統一的套接字抽象用於編寫不同層次的網路程式,避免了應用套接字進行網路編的繁瑣(因有時需引用底層作業系統的相關資料結構)。有較底層次的類如QTcpSocket、QTcpServer和QUdp

Qt一log調試日誌

gms 生成文件 _file__ ica 沒有 rest delet mar 排除 一、簡單介紹 近期因調試code時,想了解程序的流程,但苦於沒有一個簡易的日誌記錄,不停使用qDebug打印輸出,而終於提交代碼時得去多次刪除信息打印,有時還會出現新改動

Qt維碼條形碼解析

一、簡介         二維條碼/二維碼(2-dimensional bar code)是用某種特定的幾何圖形按一定規律在平面(二維方向上)分佈的黑白相間的圖形記錄資料符號資訊的,其應用廣泛,如:產品防偽/溯源、廣告推送、網站連結、資料下載、商品交易、定位/導航、電子憑

Qt五2048遊戲(原始程式碼來自網路)

一、簡介         Qt改寫2048遊戲,在linux系統下找尋android的視覺效果。 二、執行圖         啟動執行圖: 三、詳解 1、程式碼 (1)widget.h #ifndef WIDGET_H #define WIDGET_H #inclu

Qt一log除錯日誌

一、簡介       最近因除錯code時,想了解程式的流程,但苦於沒有一個簡易的日誌記錄,不停使用qDebug列印輸出,而最終提交程式碼時得去多次刪除列印資訊,有時還會出現新修改的程式碼分不清是哪些部分。而使用#ifdef _DEBUG又比較煩這套,因此寫了些簡單的日誌

Qt八解析XML檔案

一、簡介         QtXml模組提供了一個讀寫XML檔案的流,解析方法包含DOM和SAX。DOM(Document ObjectModel):將XML檔案表示成一棵樹,便於隨機訪問其中的節點,但消耗記憶體相對多一些。SAX(Simple APIfor XML):一

QtQt樣式表

一、簡介       不斷總結好的樣式表,美化自己的介面(在實際工作中會不斷的更新)。 二、詳解 1、載入樣式表文件 QFile file(":/qss/stylesheet.qss"); file.open(QFile::ReadOnly); QString sty

Qt總結C/C++記憶體分配方式與儲存區

一、C/C++記憶體分配有三種方式   從靜態儲存區域分配。記憶體在程式編譯的時候就已經分配好,這塊記憶體在程式的整個執行期間都存在。例如全域性變數,static變數。 在棧上建立。在執行函式時,函式內區域性變數的儲存單元都可以在棧上建立,函式執行結束時這些儲存單元

Qt八視窗下方彈出提示資訊

一、簡介       在專案中一般都會彈出新的子對話方塊顯示提示資訊,但對於一些因後臺資料變化引發的提示還是在視窗下方彈出提示資訊比較合理。點選按鈕彈出提示資訊,當滑鼠放在提示資訊對話方塊上時,暫停動畫可長時間檢視提示資訊。 二、詳解 1、程式碼 (1)fader

Qt一QT_OpenGL

一、簡介           最近想了解些Qt的OpenGL程式設計,可能以後會使用。Opengl是對2D和3D圖形支援很好,有非常多的優化函式,而且是個跨平臺的開源庫。Qt的Opengl封裝的很好,通過Qt的QGLWidget類,將opengl的函式和Qt的介面結合了

Qt介面自定義

一、簡介       Qt自帶的介面不利於樣式的調整和美化,自定義介面便於設計風格。 二、詳解 1、程式碼 (1)pagenumbercontrol.h #ifndef PAGENUMBERCONTROL_H #define PAGENUMBERCONTROL_H

Qt一QLineEdit的新樣式和補全歷史記錄

一、簡介        利用背景圖片設計出QLineEdit新的樣式,起到美化介面的效果,並增加自動補全歷史記錄的功能,就可以作為一個完整的庫。  二、詳解 1、知識點 (1)切換QLineEdit的背景 void InnerLineEdit::setNormal()

QtCentos下Qt結合v4l2實現的視訊顯示

一、簡介        v4l2是針對uvc免驅usb裝置的程式設計框架,主要用於採集usb攝像頭。 可從網上下載最新的原始碼(包括v4l2.c和v4l2.h兩個檔案),本文中修改過。       Qt執行介面如下(動態變化的): 二、詳解 1、準備 (1)插入usb攝

Mysql學習JDBC連接數據庫DriverManager方法

url state 種類 delet rom 條件 管理系 ont into JDBC連接數據庫 ?創建一個以JDBC連接數據庫的程序,包括7個步驟: 1、載入JDBC驅動程序: 在連接數據庫之前。首先要載入想要連接的數據庫的驅動到JVM

【Java並發編程】線程間通信中notifyAll造成的早期通知問題(含代碼)

data light lan 添加項 article util tool 元素 seconds 轉載請註明出處:http://blog.csdn.net/ns_code/article/details/17229601 如果線程在等待時接到通知,但線程等待的條件

Tensorflow深度學習基礎圖像處理

fcm 數字 ssi port con tty .net term file Tensorflow深度學習之十二:基礎圖像處理之二 from:https://blog.csdn.net/davincil/article/details/76598474 首先放出

skyfans每天一個Liunx命令系列mpstat、vmstat、iostat

今天我們繼續來學習PERFORMANCE MONITORING AND STATISTICS(效能監測與統計),今天學習的是什麼命令呢,那就是mpstat、vmstat、iostat Ready Go!!! 命令使用方法:命令 + 時長+次數,例如檢視處理器相關內容,每2秒收集一次,

PID控制器開發筆記模糊PID控制器的實現

poi 技術 last 全部 arr linear 數值 .com 數據   在現實控制中,被控系統並非是線性時不變的,往往需要動態調整PID的參數,而模糊控制正好能夠滿足這一需求,所以在接下來的這一節我們將討論模糊PID控制器的相關問題。模糊PID控制器是將模糊算法與PI

Java代理Cglib動態代理-MethodInterceptor

 淺談Java代理二:Cglib動態代理-MethodInterceptor   CGLib動態代理特點: 使用CGLib實現動態代理,完全不受代理類必須實現介面的限制,而且CGLib底層採用ASM位元組碼生成框架,使用位元組碼技術生成代理類,比使用Java反射效率要高。唯一需要注意