[解決済み] QStandardItemModelとカスタムオブジェクトへのバインディング
質問
Qtのexampleにあるcities-standarditemを自分のexampleに適応させようとしたのですが、どうすればいいですか?おかしな結果になっています。
以下は私のUserクラスです。
class User{
public:
User();
QString getFirstname() const;
void setFirstname(const QString &value);
QString getLastname() const;
void setLastname(const QString &value);
int getAge() const;
void setAge(int value);
private:
QString firstname;
QString lastname;
int age;
};
で、usermodel.hを宣言しています。
class UserModel: public QStandardItemModel
{
Q_OBJECT
public:
UserModel(QList<User> users, QObject *parent = Q_NULLPTR);
QHash<int, QByteArray> roleNames() const;
};
そして、コンストラクタとroleNames関数の実装は以下の通りです。
enum ItemRoles {
FirstnameRole,
LastnameRole,
AgeRole,
};
UserModel::UserModel(QList<User> users, QObject *parent) : QStandardItemModel(parent)
{
//this->setItemRoleNames(roleNames());
this->setColumnCount(3);
for (auto user: users) {
QStandardItem *item = new QStandardItem();
item->setData(user.getFirstname(), FirstnameRole);
item->setData(user.getLastname(), LastnameRole);
item->setData(user.getAge(), AgeRole);
appendRow(item);
}
setSortRole(FirstnameRole);
}
QHash<int, QByteArray> UserModel::roleNames() const
{
QHash<int, QByteArray> mapping = QStandardItemModel::roleNames();
mapping[FirstnameRole] = "firstname";
mapping[LastnameRole] = "lastname";
mapping[AgeRole] = "age";
return mapping;
}
私のテーブルビューには、関数で追加された最後のRoleだけが表示されます。
item->setData(user.getFirstname(), FirstnameRole);
最後に追加された年齢が表示されている場合、その年齢が表示されます。 何か手がかりはありますか?
解決方法は?
例えば、次のような場合です。
<強い
本当に
はカスタムモデルが必要で、既存のモデルを拡張したい。あなたのデータは表形式なので、私は
QAbstractTableModel
を基本クラスとします。
では、このクラスを用意しましょう。
class UserModel: public QAbstractTableModel
{
Q_OBJECT
QList<User> _users;
public:
UserModel(QList<User> users, QObject *parent = Q_NULLPTR) : QAbstractTableModel(parent), _users(users){}
見ての通り、このクラスは構築時に指定されたユーザーのリストを保存します。コンストラクタ自体は、リストをコピーして初期化する以外には何もしません。
そうすると、少なくともこれらの実装を用意する必要があります。
int rowCount(const QModelIndex &) const override
{
return _users.size();
}
int columnCount(const QModelIndex &) const override
{
return 3;
}
QVariant data(const QModelIndex &index, int role) const override
{
if(role == Qt::DisplayRole)
{
User user = _users.at(index.row());
QVariant data[] = { user.getFirstname(), user.getLastname() , user.getAge() };
return data[index.column()];
}
return {};
}
一方
columnCount
は一定で常に3を返します。
rowCount
は、ユーザーのリストに含まれる項目の数を返します。
で
data
の実装では、渡されたインデックスが検査され、そのインデックスに応じた値が返されます。
行
と
列
と、渡された
役割
.
ここで重要なのは、ビューが
data
を渡すと
role
と等しい
Qt::DisplayRole
のセルに表示されるデータそのものを返す必要があります。
(index.row(), index.column())
この例では、3つの
User
のデータメンバです。
を再実装すると、かなり便利です。
sort
関数も同様に、すなわち
void sort(int column, Qt::SortOrder order) override
{
auto fnSort = [](const User & u1, const User & u2){ return u1.getFirstname() < u2.getFirstname(); };
auto lnSort = [](const User & u1, const User & u2){ return u1.getLastname() < u2.getLastname(); };
auto agSort = [](const User & u1, const User & u2){ return u1.getAge() < u2.getAge(); };
std::function<bool (const User &, const User &)> sortFn[] = {fnSort, lnSort, agSort};
std::sort(_users.begin(), _users.end(), sortFn[column]);
if(order == Qt::DescendingOrder)
{
std::reverse(_users.begin(), _users.end());
}
}
こうすることで、期待通り、ユーザーに列でソートさせることができます。
myTableView->setModel(new UserModel(list));
myTableView->model()->sort(2, Qt::DescendingOrder); //sort by first age, in descending order
もし、何らかの理由で カスタム のロールは、このようなenumにしてください。
enum ItemRoles {
FirstnameRole = Qt::UserRole,
LastnameRole,
AgeRole,
};
からスタートします。
Qt::UserRole
(これはまさにこの目的のためにあるのですが) あなたのロールが組み込みのロールと衝突しないようにするためです。
上記のコードは、次のような意味であることに注意してください。 提案 可能な解決策であり、それは その の解決策そのものです(境界チェックやメモリ管理など、多くの重要な機能が欠けています)。
関連
-
[解決済み】C++エラー。アーキテクチャ x86_64 に対して未定義のシンボル
-
[解決済み】コンストラクターでのエラー:識別子を期待されますか?
-
[解決済み】C-stringを使用すると警告が表示される。"ローカル変数に関連するスタックメモリのアドレスが返される"
-
[解決済み] 非常に基本的なC++プログラムの問題 - バイナリ式への無効なオペランド
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】リンカーエラーです。"リンカ入力ファイルはリンクが行われていないため未使用"、そのファイル内の関数への未定義参照
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された
-
[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】'cout'は型名ではない
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる