亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Qt實(shí)現(xiàn)拖拽功能圖文教程(支持拖放文件、拖放操作)

 更新時(shí)間:2023年11月28日 15:22:39   作者:林夕07  
這篇文章主要給大家介紹了關(guān)于Qt實(shí)現(xiàn)拖拽功能(支持拖放文件、拖放操作)的相關(guān)資料,Qt是一款多平臺(tái)的C++應(yīng)用程序開(kāi)發(fā)框架,它的獨(dú)特之處在于可以快速開(kāi)發(fā)出拖放式的開(kāi)發(fā)桌面程序,需要的朋友可以參考下

拖放

拖放是在一個(gè)應(yīng)用程序內(nèi)或者多個(gè)應(yīng)用程序之間傳遞信息的一種直觀的現(xiàn)代操作方式。除了為剪貼板提供支持外,通常它還提供數(shù)據(jù)移動(dòng)和復(fù)制的功能。

拖放操作包括兩個(gè)截然不同的動(dòng)作:拖動(dòng)和放下。Qt窗口部件可以作為拖動(dòng)點(diǎn)(darg site)、放下點(diǎn)(drop site)或者同時(shí)作為拖動(dòng)點(diǎn)和放下點(diǎn)。

Qt程序接受其他程序的拖拽

我們經(jīng)常將文本文件推拽到notepate++等類(lèi)型文本編輯器軟件中。那么如何讓Qt程序也能夠支持這種操作呢?

我們需要在主窗口重新實(shí)現(xiàn)了來(lái)自父類(lèi)的dragEnterEvent()和 dropEvent()函數(shù)。

protected:
    virtual void dragEnterEvent(QDragEnterEvent* event) override;
    virtual void dropEvent(QDropEvent* event) override;

在構(gòu)造函數(shù)中,創(chuàng)建了一個(gè)QTextEdit并且把它設(shè)置為中央窗口部件。默認(rèn)情況下,QTextEdit可以接受來(lái)自其他應(yīng)用程序文本的拖動(dòng),并且如果用戶(hù)在它上面放下一個(gè)文件,它將會(huì)把這個(gè)文件的內(nèi)容填充到QTextEdit部件中。

由于拖放事件是從子窗口部件傳遞給父窗口部件的,所以通過(guò)禁用QTextEdit上的放下操作以及啟用主窗口上的放下操作,就可以在整個(gè)MainWindow窗口中獲得放下事件。

#include <QMimeData>
#include <QTextStream>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    
 
    textEdit = new QTextEdit(this);
    setCentralWidget(textEdit);

    textEdit->setAcceptDrops(false);
    setAcceptDrops(true);

    setWindowTitle("Text Editor");
}

當(dāng)用戶(hù)把一個(gè)對(duì)象拖動(dòng)到這個(gè)窗口部件上時(shí),就會(huì)調(diào)用dragEnterEvent()。如果對(duì)這個(gè)事件調(diào)用acceptProposedAction(),就表明用戶(hù)可以在這個(gè)窗口部件上拖放對(duì)象。默認(rèn)情況下,窗口部件是不接受拖動(dòng)的。Qt會(huì)自動(dòng)改變光標(biāo)來(lái)向用戶(hù)說(shuō)明這個(gè)窗口部件是不是有效的放下點(diǎn)。

這里,我們希望用戶(hù)拖動(dòng)的只能是文件,而非其他類(lèi)型的東西。為了實(shí)現(xiàn)這一點(diǎn),我們可以檢查拖動(dòng)的MIME類(lèi)型。

MIME類(lèi)型中的 text/uri-list 用于存儲(chǔ)一系列的統(tǒng)一資源標(biāo)識(shí)符(Universal Re-source Identifier ,URI),它們可以是文件名、統(tǒng)―資源定位器(Uniform Resource Locator , URL,如 HTTP或者FTP路徑),或者其他全局資源標(biāo)識(shí)符。標(biāo)準(zhǔn)的MIME類(lèi)型是由國(guó)際因特網(wǎng)地址分配委員會(huì)(Internet Assigned Numbers Authority , IANA)定義的,它們由類(lèi)型、子類(lèi)型信息以及分隔兩者的斜線(xiàn)組·成。MME類(lèi)通常由剪貼板和拖放系統(tǒng)使用,以識(shí)別不同類(lèi)型的數(shù)據(jù)。可以從下面的網(wǎng)站得到正式的 MIME類(lèi)型列表: http://www.iana.org/assignments/media-types/

void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
    if(event->mimeData()->hasFormat("text/uri-list"))
    {
        event->acceptProposedAction();
    }
}

當(dāng)用戶(hù)在窗口部件上放下一個(gè)對(duì)象時(shí),就會(huì)調(diào)用dropEvent()。.我們調(diào)用函數(shù)QMimeData::urls()來(lái)獲得QUrl列表。通常,用戶(hù)一次只拖動(dòng)一個(gè)文件,但是通過(guò)拖動(dòng)一個(gè)選擇區(qū)域來(lái)同時(shí)拖動(dòng)多個(gè)文件也是可能的。如果要拖放的URL不止一個(gè),或者要拖放的URL,不是一個(gè)本地文件名,則會(huì)立即返回到原調(diào)用處。
QWidget也提供 dragMoveEvent()和 dragLeaveEvent()函數(shù),但是在絕大多數(shù)應(yīng)用程序中并不需要重新實(shí)現(xiàn)它們。

void MainWindow::dropEvent(QDropEvent *event)
{
    QList<QUrl> urls = event->mimeData()->urls();
    if(urls.empty())
        return;

    QString fileName = urls.first().toLocalFile();
    if(fileName.isEmpty())
        return;

    if(ReadFile(fileName))
    {
        setWindowTitle(QString("%1-%2").arg(fileName).arg("Drag File"));
    }
}
bool MainWindow::ReadFile(const QString &filename)
{
    QFile file(filename);
    file.open(QIODevice::ReadOnly | QIODevice::Text | QIODevice::Truncate);
    if(false == file.isOpen())
    {
        return false;
    }
    QTextStream stream(&file);
    textEdit->insertPlainText(stream.readAll());
    file.flush();
    file.close();
    return true;
}

看看效果吧

部件/控件之間相互拖放

我們將實(shí)現(xiàn)類(lèi)似于一個(gè)下圖的效果,但不需要向左向右的按鍵,通過(guò)拖拽目標(biāo)實(shí)現(xiàn)移動(dòng)。

思路:創(chuàng)建一個(gè)支持拖拽的QListWidget子類(lèi)ProjectListWidget,并且作為該界面的一個(gè)部件。

在ProjectListWidget類(lèi)中需要重寫(xiě)父類(lèi)的五個(gè)事件,和一個(gè)私有方法以及一個(gè)坐標(biāo)記錄

protected:
    virtual void mousePressEvent(QMouseEvent* event) override;
    virtual void mouseMoveEvent(QMouseEvent* event) override;
    virtual void dragEnterEvent(QDragEnterEvent* event) override;
    virtual void dragMoveEvent(QDragMoveEvent* event) override;
    virtual void dropEvent(QDropEvent* event) override;
private:
    void performDrag();

private:
    QPoint startPos;

在構(gòu)造函數(shù)中,我們使列表框上的放下生效。

#include <QApplication>
#include <QDrag>
#include <QMimeData>
ProjectListWidget::ProjectListWidget(QWidget* parent)
    :QListWidget{parent}
{
    setAcceptDrops(true);
}

當(dāng)用戶(hù)按下鼠標(biāo)左鍵,就把鼠標(biāo)位置保存到statPos私有變量中。然后我們正常調(diào)用QListWidget 中mousePressEvent()。

void ProjectListWidget::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        startPos = event->pos();
    }
    QListWidget::mousePressEvent(event);
}

當(dāng)用戶(hù)按住鼠標(biāo)左鍵并移動(dòng)鼠標(biāo)光標(biāo)時(shí),就認(rèn)為這是一個(gè)拖動(dòng)的開(kāi)始。我們計(jì)算當(dāng)前鼠標(biāo)位置和原來(lái)鼠標(biāo)左鍵按下的點(diǎn)之間的距離-—這個(gè)“曼哈頓長(zhǎng)度”(Manhattan Length)其實(shí)是從坐標(biāo)原點(diǎn)到該矢量長(zhǎng)度快速計(jì)算的近似值。如果這個(gè)距離大于或等于QApplication推薦的拖動(dòng)起始距離值(通常是4個(gè)像素),那么就調(diào)用私有函數(shù)performDrag()以啟動(dòng)拖動(dòng)操作。這可以避免用戶(hù)因?yàn)槭治帐髽?biāo)抖動(dòng)而產(chǎn)生拖動(dòng)。

void ProjectListWidget::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton)
    {
        if(int distance = (event->pos() - startPos).manhattanLength();
            distance >= QApplication::startDragDistance())
        {
            performDrag();
        }
    }
    QListWidget::mouseMoveEvent(event);
}

perfomDrag()中,創(chuàng)建了一個(gè)類(lèi)型為QDrag的對(duì)象,并且把this作為它的父對(duì)象。這個(gè)QDrag對(duì)象將數(shù)據(jù)存儲(chǔ)在QMimeData對(duì)象中。在這個(gè)實(shí)例中,我們利用QMineData::setText()提供了作為text/plain字符串的數(shù)據(jù)。QMimeData 提供了一些可用于處理最常用拖放類(lèi)型(諸如圖像、URL、顏色,等等)的函數(shù),同時(shí)也可以處理任意由QByteArrays表宗的MiME類(lèi)型。QDrag::setPiximap()調(diào)用則可以在拖放發(fā)生時(shí)使圖標(biāo)隨光標(biāo)移動(dòng)。

QDrag::exec()調(diào)用啟動(dòng)并執(zhí)行拖動(dòng)操作;直到用戶(hù)放下或取消此次拖動(dòng)操作才會(huì)停止。它把所有支持的“拖放動(dòng)作"(如 Qi: : CopyAction, Qt : : MoveAction和 Qt: : LinkAction)的組合作為其參數(shù),并且返回被執(zhí)行的拖放動(dòng)作(如果沒(méi)有執(zhí)行任何動(dòng)作,則返回Qt: IgnoreAction)。至于執(zhí)行的是哪`個(gè)動(dòng)作,取決于放下發(fā)生時(shí)源窗口部件是否允許、目標(biāo)是否支持及按下了哪些組合鍵。在 exec()調(diào)用后,Qt擁有拖動(dòng)對(duì)象的所有權(quán)并且可以在不需要它的時(shí)候刪除它。

void ProjectListWidget::performDrag()
{
    if(QListWidgetItem* item = currentItem();
        nullptr != item)
    {
        QMimeData* mineData = new QMimeData();
        mineData->setText(item->text());

        QDrag* drag = new QDrag(this);
        drag->setMimeData(mineData);
        drag->setPixmap(QPixmap(":/icon.jpg"));

        if(drag->exec(Qt::MoveAction) == Qt::MoveAction)
        {
            delete item;
            item = nullptr;
        }
    }
}	

ProjectListWidget窗口部件不僅能發(fā)起拖動(dòng),還可以接收同一個(gè)應(yīng)用程序中來(lái)自另外一個(gè)ProjectListWidget部件的拖動(dòng)。如果窗口部件是同個(gè)應(yīng)用程序的一部分,QDragEnterEvent::source()返回一個(gè)啟動(dòng)這個(gè)拖動(dòng)的窗口部件的指針;否則,返回一個(gè)空指針值。

void ProjectListWidget::dragEnterEvent(QDragEnterEvent *event)
{
    ProjectListWidget* source = reinterpret_cast<ProjectListWidget*>(event->source());
    if(nullptr != source && source != this)
    {
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}

dragMoveEvent()中的代碼與dragEnterEvent()中編寫(xiě)的代碼基本相同。因?yàn)樾枰貙?xiě)QListWidget的函數(shù)實(shí)現(xiàn)(實(shí)際上是 QAbstractItemView的函數(shù)實(shí)現(xiàn))。

void ProjectListWidget::dragMoveEvent(QDragMoveEvent *event)
{
    ProjectListWidget* source = reinterpret_cast<ProjectListWidget*>(event->source());
    if(nullptr != source && source != this)
    {
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}

在dropEvent()中,我們使用QMimeData::text()重新找回拖動(dòng)的文本并隨文本創(chuàng)建一個(gè)拖動(dòng)項(xiàng)。還需要將事件作為“移動(dòng)動(dòng)作”來(lái)接受,從而告訴源窗口部件現(xiàn)在可以刪除原來(lái)的拖動(dòng)項(xiàng)了。

void ProjectListWidget::dropEvent(QDropEvent *event)
{
    ProjectListWidget* source = reinterpret_cast<ProjectListWidget*>(event->source());
    if(nullptr != source && source != this)
    {
        addItem(event->mimeData()->text());
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}

效果如下

總結(jié)

拖放是在應(yīng)用程序之間傳遞數(shù)據(jù)的有力機(jī)制。但是在某些情況下;,有可能在執(zhí)行拖放時(shí)并未使用Qt的拖放工具。如果只是想在一個(gè)應(yīng)用程序的窗口部件中移動(dòng)數(shù)據(jù),通常只要重新實(shí)現(xiàn)mousePressEvent()和 mouseReleaseEvent()函數(shù)就可以了。

到此這篇關(guān)于Qt實(shí)現(xiàn)拖拽功能(支持拖放文件、拖放操作)的文章就介紹到這了,更多相關(guān)Qt實(shí)現(xiàn)拖拽功能內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論