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

Qt 學習之路 (45):自訂 Model 實戰 (一) —— 貨幣匯率表模型

     編輯:關於C語言

Qt 內建的 QStringListModel 等預定義模型雖方便,但無法滿足複雜業務需求(如資料壓縮、運算衍生、效能優化)。本篇透過「貨幣匯率表」實例,示範繼承 QAbstractTableModel 實作高效能、低記憶體佔用的自訂表格模型。

業務場景與設計動機

假設需顯示 100 種貨幣兩兩匯率的 100×100 表格(含自對自 1.0000),共 10,000 儲存格。若全量儲存極其浪費。觀察發現:**僅需儲存各貨幣對美元匯率(100 筆),任意兩貨幣匯率可由「幣值A/幣值B」即時運算得出**。

模型類別設計

class CurrencyModel : public QAbstractTableModel
{
public:
    CurrencyModel(QObject *parent = 0);
    void setCurrencyMap(const QMap<QString, double> &map);

    int rowCount(const QModelIndex &parent) const override;
    int columnCount(const QModelIndex &parent) const override;
    QVariant data(const QModelIndex &index, int role) const override;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const override;

private:
    QString currencyAt(int offset) const;
    QMap<QString, double> currencyMap;   // 底層資料:貨幣名稱 -> 對美元匯率
};

核心虛函數實作

int CurrencyModel::rowCount(const QModelIndex &) const
{ return currencyMap.count(); }

int CurrencyModel::columnCount(const QModelIndex &) const
{ return currencyMap.count(); }
QVariant CurrencyModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid()) return QVariant();

    // 文字靠右垂直置中
    if (role == Qt::TextAlignmentRole)
        return int(Qt::AlignRight | Qt::AlignVCenter);

    // 顯示角色:動態計算匯率
    if (role == Qt::DisplayRole) {
        QString rowCur   = currencyAt(index.row());
        QString colCur   = currencyAt(index.column());
        double rateRow   = currencyMap.value(rowCur);
        double rateCol   = currencyMap.value(colCur);

        if (rateRow == 0.0) return "####";           // 避免除零
        double amount = rateCol / rateRow;           // 幣值B / 幣值A
        return QString("%1").arg(amount, 0, 'f', 4); // 格式化 4 位小數
    }
    return QVariant();
}
QVariant CurrencyModel::headerData(int section, Qt::Orientation, int role) const
{
    if (role != Qt::DisplayRole) return QVariant();
    return currencyAt(section);   // 行/列標題皆為貨幣名稱
}
void CurrencyModel::setCurrencyMap(const QMap<QString, double> &map)
{
    currencyMap = map;
    reset();                      // 通知視圖資料全量變更
}

QString CurrencyModel::currencyAt(int offset) const
{
    return (currencyMap.begin() + offset).key();
}

QVariant:型別擦除的萬能容器

data() 回傳 QVariant,相當於 Java 的 Object,可封裝 int、QString、QColor 等任意型別。使用時需對應型別取出(如 toInt()、toString()),不可自動轉型。Qt 將此功能從 QObject 分離,避免基底類別膨脹,體現 C++ 非單一繼承體系下的務實設計。

視圖端使用範例

QMap<QString, double> data;
data["NOK"] = 1.0000;
data["NZD"] = 0.2254;
data["SEK"] = 1.1991;
data["SGD"] = 0.2592;
data["USD"] = 0.1534;

CurrencyModel *model = new CurrencyModel;
model->setCurrencyMap(data);

QTableView *view = new QTableView(this);
view->setModel(model);
view->resize(400, 300);

執行結果

貨幣匯率表執行畫面

抽象模型繼承體系速查

  • QAbstractListModel:一維列表模型基類。
  • QAbstractTableModel:二維表格模型基類(本例使用)。
  • QAbstractItemModel:樹狀/多維模型基類,功能最完整但需實作更多虛函數。

三者關係:QAbstractItemModel 為根,QAbstractListModel 與 QAbstractTableModel 分別針對一維/二維優化。

本文出自 “豆子空間” 博客,請務必保留此出處:https://devbean.blog.51cto.com/448512/267435

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