Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
]semo[

Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 22. únor 2012, 18:52:40 Předmět: QT model/view trable |
|
|
Nevíte někdo, jak v Model/View architektuře v QT "invalidovat" QModelIndex? :-)
Dělám herní editor, mám LayerManager a SceneTree. Oboje je QTreeView/vlastní implementace QAbstractItemModel. Ale když v SceneTree smažu objekty, potřebuju změnu reflektovat i v LayerManageru - ale nic na to neexistuje. Kromě brutální metody reset(). removeRows se použít nedá. Počítá totiž s tím, že budu objekty odstraňovat, ne že už jsou odstraněny...
Je to dost peklo. Jedno řešení mám, ale je dost nebezepčný a nepřehledný. Přitom by stačilo něco jako removeIndex, nebo invalidateIndex.
Nic o tom nemůžu najít, ani na jejich fóru. A ptát se tam nechci, už jednou mi neodpověděli. _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory |
|
Návrat nahoru |
|
 |
nou

Založen: 28. 07. 2007 Příspěvky: 1050
|
Zaslal: 22. únor 2012, 20:18:43 Předmět: |
|
|
chapem tomu dobre ze z jedneho modelu chces zobrazovat data do dvoch view? _________________ Najjednoduchšie chyby sa najtažšie hľadajú. |
|
Návrat nahoru |
|
 |
nou

Založen: 28. 07. 2007 Příspěvky: 1050
|
Zaslal: 22. únor 2012, 20:57:40 Předmět: |
|
|
pokial viem tak pred zacatim odstranovania dat treba zavolat beginRemoveRows() a po skonceni zase endRemoveRows() myslim ze toto je proste nutne. _________________ Najjednoduchšie chyby sa najtažšie hľadajú. |
|
Návrat nahoru |
|
 |
]semo[

Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 23. únor 2012, 10:15:44 Předmět: |
|
|
Naopak, mám jedny "data" (herní objekty), ale chci je mít ve dvou modelech - jeden je LayerManager, druhej SceneTree. A s tím se v QNávrhu nějak nepočítalo, myslím.
Jedniný, se mi povedlo je toto:
- např. SceneTree vyvolá odstranění objektu
- přes signály se oznámí LayerManageru, že se bude odstraňovat objekt
- LayerManager zavolá svoji privátní metodu beginRemoveRows()
- pak se objekty fyzicky odstraní (uplně mimo LayerManager!)
- poté se opět přes signál oznámí LayerManageru, že objekt byl odstraněn
- LayerManager zavolá privátní metodu endRemoveRows()
...to mi připadá krkolomný. Navíc těžko říct, co by se stalo, kdyby to selhlalo a endRemoveRows by se nezavolalo. Hodilo by se prostě ruční odstranění indexů...Z Model/View jsem často dost smutný. _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory |
|
Návrat nahoru |
|
 |
kerekes
Založen: 29. 07. 2007 Příspěvky: 57
|
Zaslal: 23. únor 2012, 10:33:55 Předmět: |
|
|
Co ak by si viac oddelil GUI a logiku .. tj mazanie objektu od mazania jeho UI reprezentacie? Napr ak by si mal funkciu/metodu removeObject(<jedinecny identifikator>) a ona by vnutri odstranila najprv zo vsetkych zoznamov GUI reprezentaciu a nezavisle na tom potom odstranila samotny herny objekt? |
|
Návrat nahoru |
|
 |
]semo[

Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 23. únor 2012, 10:45:30 Předmět: |
|
|
No tak to právě mám, ale návrh Qtčka počítá (jak jsem to pochopil) s tím, že ta logika bude v nějakém gui prvku - uvnitř removeRows/Columns v QAbstractItemModel...
Já mám "JádroEditoru", který odstraňuje objekty a oznamuje to signálama tomu GUI. Jenže tam se to komplikuje, jak jsem psal. Ono je to možná dost nesrozumitelný, potřebuje to hlubší znalost Qt.
No nejspíš budu muset ještě na každý herní objekt v každým GUI prvku udělat wrapper, jehož odstranění se bude řídit jinak. _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory |
|
Návrat nahoru |
|
 |
Mnemonic

Založen: 28. 07. 2007 Příspěvky: 93
|
Zaslal: 24. únor 2012, 08:07:06 Předmět: |
|
|
A je nutný mít dva modely nad stejnejma datama? Myslím, že jejich původní idea byla taková, že bude jeden model a nad ním X views. Pokud ta data chceš ukazovat radikálně jiným způsobem, nestačil by nějakej proxy model na zafiltrování, pověšenej na ten původní model?
Jinak model/view architektura je poměrně zevrubně popsaná v téhle knížce. |
|
Návrat nahoru |
|
 |
]semo[

Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 24. únor 2012, 09:25:40 Předmět: |
|
|
No vpodstatě by to tak asi nešlo (ten proxy model) - proxy model používám na filtrování, ale nenapadá mě, jak to naroubovat, podle toho co píšeš.
Více pohledu na data je prostě potřeba a neni to prasečina: Prostě objekty v LayerManageru chci vidět navěšené pod vrstvama, ale zároveň ty samé objekty pořebuju vidět ve SceneTree, bez vrstev... Prostě klasický herní editor.
NICMÉNĚ, včera jsem si dopomohl sklenkou trnkového vína a celý to nějak rozseknul.. pomohly ty interní wrapovací objekty v ItemModelech. Najednou to do sebe začalo pěkně zapadat :-) _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory |
|
Návrat nahoru |
|
 |
mkcz
Založen: 24. 02. 2012 Příspěvky: 7
|
Zaslal: 24. únor 2012, 16:09:06 Předmět: |
|
|
Vytvoř si jeden TreeModel kde budou vrstvy a objekty. Pak si můžeš vytvořit pohled, který ti zobrazí jen vrstvi nebo jen objekty. Když se budeš v pohledu odkazovat na indexi v modelu přes QPersistentModelIndex tak při emitování rowsRemoved můžeš jen projít položky v pohledu a když nebude mít validní index tak jí vymazat. |
|
Návrat nahoru |
|
 |
]semo[

Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 26. únor 2012, 19:41:08 Předmět: |
|
|
Už mi to funguje...ale jen pro zajímavost,
mkcz: Jak by to šlo udělat, když "vlastníkem" objektu je v LayerManageru vrstva a ve SceneTree jiný objekt? Nevím přesně jak to myslíš. Možná je to ale mojí neznalostí QPersistentModelIndex. Rychle se točící kola kapitalismu mi nedávají příliš času studovat každou věc z QT... _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory |
|
Návrat nahoru |
|
 |
mkcz
Založen: 24. 02. 2012 Příspěvky: 7
|
Zaslal: 26. únor 2012, 22:18:08 Předmět: |
|
|
Tak přece když má model stromovou strukturu, tak vrstva může mít potomky objekty a objekty zase potomky další objekty. V pohledu pak zobrazíš jen typ dat, který chceš vidět.
Ale z toho co je tady napsaný nějak nechápu jestli je potřeba, aby objekt měl předka z jiný vrstvy než je on sám, pokud by to bylo potřeba, tak bych si udělal nějaké společné pole dat pro oba modely a řešil bych to na úrovní funkcí data, index, parent atd. u jednotlivých modelů.
Ten QPersistentModelIndex je jen odkaz na QModelIndex, tak že pokud vymažeš model index, na který ukazuje tak není validní (isValid vrací false).
Tady sem napsal příklad jak by mohla vypadat funkce parent u layer modelu:
kód: |
QModelIndex LayerModel::parent(const QModelIndex &aIndex) const
{
Q_D(const LayerModel);
if (!aIndex.isValid())
return QModelIndex();
Node *childItem = static_cast<Node*>(aIndex.internalPointer());
if (childItem->type == OBJECT)
Node *parentItem = (Object*)childItem->parentLayer(); //pro scenetree model by to mohl být třeba parentObject()
else
.
.
.
if (parentItem == d->iHeadItem)
return QModelIndex();
return createIndex(parentItem->getRow(), 0, parentItem);
} |
Node je třída, ze který by mohly vychází třídy Objekt i Layer, měla by asi mít nějakou virtual funkci type která by vracela typ nodu.
Sem jen programátor amatér takže to ber s rezervou, třeba by se našla nějaká komplikace, kvůli který by to nešlo zrealizovat. |
|
Návrat nahoru |
|
 |
]semo[

Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 27. únor 2012, 08:23:54 Předmět: |
|
|
mkcz napsal: |
Ale z toho co je tady napsaný nějak nechápu jestli je potřeba, aby objekt měl předka z jiný vrstvy než je on sám, ... |
To je právě potřeba.
mkcz napsal: |
Ten QPersistentModelIndex je jen odkaz na QModelIndex, tak že pokud vymažeš model index, na který ukazuje tak není validní (isValid vrací false). |
Tak to je nejspíš to, co používám teď, ale je to moje vlastní třída, o Persistent Model Index jsem nevěděl. (Stejně tak jako jsem nevěděl, že v QT mají UndoStack a udělal jsem svůj, který jako by z oka vypadnul tomu z Qt...). Je to prostě už dost velké API, nabírám zkušenosti.
Ten kód, co jsi poslal (a za nějž děkuji) vypadá taky použitelně. Třeba na něj u nějakého dalšího toolu dojde. _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory |
|
Návrat nahoru |
|
 |
]semo[

Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 27. únor 2012, 13:07:00 Předmět: |
|
|
mkcz :
Když už jsme v tom povídání o Qt...nevěděl bys, jak "updatnout" sortování treeview? Mám svůj tree model a ten nacpu do QSortFilterProxyModel, který sortuje objekty (např.) podle jména. To funguje. Ale když vložím do toho svýho tree modelu nový řádek, tak se sice přidá, ale sortování je blbě (uživatel musí znovu 2x kliknout na záhlaví sloupce, aby se změna projevila).
volám:
//layoutAboutToBeChanged()
beginInsertRows()
insertRows()
endInsertRows()
//layoutChanged() - crash
Snažil jsem se i emitovat layoutAboutToBeChanged() a layoutChanged(), ale to vede ke crashi. Nevím proč. Navíc neexistuje žádná funkce "updateSortManualy()". Fakt už nevím, jakej signál mám kde emitovat a co přesně vyemituje endInsertRows()...
EDIT: i když do Qt examplu "EditableTreeModel" přidám QSortFilterProxyModel, tak jim to nefunguje (a celé se to nějak rozsype). Jsem moc náročný? _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory |
|
Návrat nahoru |
|
 |
mkcz
Založen: 24. 02. 2012 Příspěvky: 7
|
Zaslal: 27. únor 2012, 18:35:48 Předmět: |
|
|
Setřídění by mělo proběhnout právě potom layoutChanged, pokud ti to padá na příkazu:
kód: |
emit layoutChanged();
|
tak máš určitě někde chybu, ale asi bych potřeboval vidět zdroják abych jí našel.
Třídění používám skoro u všech modelů a vždy mě to fungovalo bez problému. Nejlepší způsob je napsat si v modelu vlastní funkci pro třídění.
kód: |
void sort ( int column, Qt::SortOrder order = Qt::AscendingOrder )
|
Pokud si v modelu definuješ index z nějakýho vlastního ukazatele (internalPointer) tak ti nemůže fungovat QSortFilterProxyModel v napovědě pro Qt je to vysvětlené http://developer.qt.nokia.com/doc/qt-4.8/qabstractitemmodel.html#createIndex |
|
Návrat nahoru |
|
 |
]semo[

Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 27. únor 2012, 20:52:58 Předmět: |
|
|
Potíž je v tom, že nevím kdy mám layoutChanged(); emitovat. V dokumentaci píšou, že když změním layout. Jenže neni napsaný, jestli to mám dělat při insertRows/removeRows, nebo se o to postarají ty funkce beginInsertRows/endInsertRows/atd...
Takže jsem zkoušel tu sekvenci, která mi přijde logická, ale je nefunkční:
kód: |
emit layoutAboutToBeChanged()
beginInsertRows();
insertRows();
setData(pro nový řádek);
endInsertRows();
emit layoutChanged(); |
Nutno podotknout, že všechny ty funkce se týkají toho originálního modelu. SortFilterProxy by měl fungovat na základě signálů a wrapování funkcí, jestli to chápu dobře. Nebo musím všechno dělat přes něj? Ještě jsem zkoušel modifikovat jejich oficiální příklad "editabletreemodel", kde jsem model obalil jednoduše QSortFilterProxyModelem...ale ani ten příklad nefunguje správně - objeví se tam třeba prázdný item, když zkusím přidat nový..a tak podobně. O automatickým updatu třídění nemůže být řeč. Nechápu, co mi uniká :-/.
Zkusil jsem dát dotaz na jejich diskuzní fórum, ale zatim nikdo nenapsal.
....
Ano, tohle chápu a myslím, že to není ten problém. _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory |
|
Návrat nahoru |
|
 |
|