首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Qt 學習之路(54):自定義拖放數據對象——TableMimeData 實戰

     編輯:關於C語言

為什麼需要自定義 MIME 數據?

前文使用 QMimeData::setText() 等預置方法存儲標準類型(text/plain、text/html 等)。但若需拖放自定義類對象,或希望延遲數據生成(僅在目標真正需要時轉換),則需繼承 QMimeData 重寫 retrieveData()。

方案對比

  • 方案一:直接用 QMimeData::setData() 存多種預轉換好的 QByteArray。簡單但可能導致類爆炸、大數據時性能差。
  • 方案二(本文重點):繼承 QMimeData,存儲源對象指針與選區信息,按需轉換。靈活、高效、控制力強。
  • 方案三:實現 QMimeData 接口的完整自定義類。最通用但工作量大。

實戰:表格組件多格式拖放

場景:QTableWidget 支持拖放導出 plain/text、text/html、text/csv 三種格式。

自定義 MIME 數據類


class TableMimeData : public QMimeData {
    Q_OBJECT
public:
    TableMimeData(const QTableWidget *tableWidget,
                  const QTableWidgetSelectionRange &range);

    const QTableWidget *tableWidget() const { return myTableWidget; }
    QTableWidgetSelectionRange range() const { return myRange; }
    QStringList formats() const override; // 支持的 MIME 類型列表

protected:
    QVariant retrieveData(const QString &format,
                          QVariant::Type preferredType) const override;

private:
    static QString toHtml(const QString &plainText);
    static QString toCsv(const QString &plainText);
    QString text(int row, int column) const;
    QString rangeAsPlainText() const;

    const QTableWidget *myTableWidget;
    QTableWidgetSelectionRange myRange;
    QStringList myFormats;
};

構造函數與 formats()


TableMimeData::TableMimeData(const QTableWidget *tableWidget,
                             const QTableWidgetSelectionRange &range) {
    myTableWidget = tableWidget;
    myRange = range;
    myFormats << "text/csv" << "text/html" << "text/plain"; // 最優格式優先
}

QStringList TableMimeData::formats() const {
    return myFormats;
}

核心:retrieveData() 按需生成數據


QVariant TableMimeData::retrieveData(const QString &format,
                                     QVariant::Type preferredType) const {
    if (format == "text/plain")
        return rangeAsPlainText();
    else if (format == "text/csv")
        return toCsv(rangeAsPlainText());
    else if (format == "text/html")
        return toHtml(rangeAsPlainText());
    else
        return QMimeData::retrieveData(format, preferredType); // 交給基類
}

preferredType 提示期望的 QVariant 類型,這裡簡化處理忽略。

放置端處理:識別自定義類型


void MyTableWidget::dropEvent(QDropEvent *event) {
    const TableMimeData *tableData =
        qobject_cast<const TableMimeData*>(event->mimeData());

    if (tableData) { // 同一應用程序內部拖放
        const QTableWidget *otherTable = tableData->tableWidget();
        QTableWidgetSelectionRange otherRange = tableData->range();
        // 直接訪問源表格模型數據,無需解析文本
        event->acceptProposedAction();
    }
    else if (event->mimeData()->hasFormat("text/csv")) { // 外部 CSV
        QByteArray csvData = event->mimeData()->data("text/csv");
        // 解析 csvData...
        event->acceptProposedAction();
    }
    else if (event->mimeData()->hasFormat("text/plain")) { // 外部純文本
        QString plainText = event->mimeData()->text();
        // 解析 plainText...
        event->acceptProposedAction();
    }
}

關鍵優勢

  1. 零拷貝/延遲計算:數據僅在目標調用 data()/text() 時才通過 retrieveData() 生成。
  2. 類型安全:內部拖放可直接傳遞源對象指針與選區,避免文本解析開銷與精度損失。
  3. 兼容性:仍通過標準 MIME 類型與外部應用交互。

本文出自 “豆子空間” 博客,原文地址:https://devbean.blog.51cto.com/448512/288742

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved