2016-05-13 27 views
2

這是我在這裏的第一篇文章,但我從你們所有人那裏得到了很多幫助,因爲我開始編程。如何完全改變QAbstractTableModel的底層數據?

我是Qt新手,現在嘗試做我的第一個項目。我的問題是關於模型,基礎數據和視圖之間的溝通。

我首先將背景事物(數據存儲等)與GUI分開。 現在我有一個模板類Matrix,我寫了一個模板類MatrixModel,它繼承自QAbstractTableModel。這工作正常,意味着我可以編輯表格並在視圖和模型數據中刷新值。

現在我的問題:如何在不編寫新方法的情況下更改模型中的數據?

mainwindow.cpp:

matrix<int> m = {{1,2,3},{4,5,6},{7,8,9}}; 
MatrixModel<int>* model = new MatrixModel<int>(m); 
QTableView* tableView = new QTableView; 
tableView->setModel(model); 

有沒有什麼方法來調用m.transpose()到模型的基礎數據?如果我更改m,會發生什麼情況?它會影響模型的數據嗎?我嘗試了很多東西,但都沒有成功。一個「問題」是我無法使用標準信號/插槽語法,因爲我正在處理模板類。

我的最後一次嘗試是使更新類模型:

template<typename T> 
void MatrixModel<T>::updateAll() { 
    QModelIndex topLeft = index(0,0); 
    QModelIndex bottomRight = index(rowCount()-1, columnCount()-1); 
    emit dataChanged(topLeft, bottomRight); 
} 

,我試圖把它與一個按鈕和一個lambda函數連接:

connect(transposeButton, &QPushButton::clicked, [=,&m,&model]() { 
m.transpose(); model->updateAll(); 
}); 

,但似乎崩潰我的程序,如果我按下按鈕。我真的絕望xD希望你能幫助我。如果您需要了解更多信息,請只問^^

問候

丹尼斯

編輯1:好的到目前爲止,我想通了(在您的幫助:)),我有寫的功能矩陣再次在模型中(例如,轉置()),並從那裏發出數據更改(發出dataChanged或beginResetModel()...),但我無法修改模型的基礎數據。如果我寫

這在主窗口:

connect(transposeButton, &QPushButton::clicked, [&model]() { 
    model->transpose(); 
}); 

這在型號:如果我按下按鈕轉

template<typename T> 
void MatrixModel<T>::transpose() { 
    m(0,0) = 5; 
} 

我的程序只是崩潰。如果我評論該行

m(0,0) = 5; 

出來,一切正常。

編輯2: 也許有與數據存儲的問題,所以這裏是我的拷貝構造函數和我的矩陣類的私有變量:

private: 
std::vector <T> data; 
size_t rows, columns; 

//Copy constructor 
template<typename T> 
matrix<T>::matrix(const matrix<T>& other) 
    : rows(other.rows), columns(other.columns) { 
    data = other.data; 
} 
+0

如果你的模型的尺寸變化,'dataChanged() '信號是不夠的。在更改數據之前,應該調用'beginResetModel()',然後在完成時調用'endResetModel()'。 。 。 – Mike

+0

所以如果你的矩陣不是一個正方形,調用'transpose()'然後發射'dataChanged()'信號可能會導致崩潰並訪問矩陣中的無效索引 – Mike

+0

好吧,我明白了,但我可以打電話來自我的模型。但是我從mainwindow.cpp中調用函數m.transpose(),我無法調用beginResetModel(因爲它受保護)。而且我不想在我的矩陣模型中再次編寫所有函數。 – syc

回答

0

我知道了......

connect(transposeButton, &QPushButton::clicked, [model]() { 
    beginResetModel(); 
    m(0,0)=50; 
    endResetModel(); 
}); 

作品...模型已經是一個指針,所以我給出相同的指針lambda函數。現在我只需要弄清楚,因爲這仍然沒有工作什麼是不正確的我轉功能,但崩潰都消失了:P感謝您的建議:)

1

你應該有你的matrix變量作爲私有成員在您的模型中,以便所有對matrix的編輯都應通過模型中的函數完成。這意味着您的型號將有一個公共transpose函數,該函數在您的matrix數據上調用transpose,然後發出dataChanged()信號。你不應該有任何直接訪問你的matrix,因爲改變它沒有模型的知識不會給你想要的。這樣,在您的模型進行更改並相應更新自己之後,每次更改matrix變量後,您都無需致電updateAll。 。 。

+0

好吧,只是這麼想:P,所以我必須重寫我的模型的功能。但我讀過,我們不應該使用resetmodel,因爲它再次繪製。從左上角向右下角發射不是更好嗎?除此之外,如果我嘗試調用模型函數(即使是簡單的函數,如新的轉置函數,我開始重置模型轉置endResetModel。Thx對您的幫助:) – syc

+0

我想通了,刪除beginResetModel()和endResetModel()的作品。所以編輯模型裏面的m就行了。 – syc

+0

如果你的模型的尺寸沒有改變,它足以發射'dataChanged()',但是如果你的尺寸在變化,你應該調用像'beginRemoveRow'或'beginResetModel'或者..然後'endRemoveRow'或'endRemoveRow '...在改變數據結構後 – Mike

相關問題