.[ ČeskéHry.cz ].
QT model/view trable
Jdi na stránku 1, 2  Další
 
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> Obecné
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č

PříspěvekZaslal: 22. únor 2012, 18:52:40    Předmět: QT model/view trable Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
nou



Založen: 28. 07. 2007
Příspěvky: 1050

PříspěvekZaslal: 22. únor 2012, 20:18:43    Předmět: Odpovědět s citátem

chapem tomu dobre ze z jedneho modelu chces zobrazovat data do dvoch view?
_________________
Najjednoduchšie chyby sa najtažšie hľadajú.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
nou



Založen: 28. 07. 2007
Příspěvky: 1050

PříspěvekZaslal: 22. únor 2012, 20:57:40    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
]semo[



Založen: 29. 07. 2007
Příspěvky: 1526
Bydliště: Telč

PříspěvekZaslal: 23. únor 2012, 10:15:44    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
kerekes



Založen: 29. 07. 2007
Příspěvky: 57

PříspěvekZaslal: 23. únor 2012, 10:33:55    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
]semo[



Založen: 29. 07. 2007
Příspěvky: 1526
Bydliště: Telč

PříspěvekZaslal: 23. únor 2012, 10:45:30    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
Mnemonic



Založen: 28. 07. 2007
Příspěvky: 93

PříspěvekZaslal: 24. únor 2012, 08:07:06    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
]semo[



Založen: 29. 07. 2007
Příspěvky: 1526
Bydliště: Telč

PříspěvekZaslal: 24. únor 2012, 09:25:40    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
mkcz



Založen: 24. 02. 2012
Příspěvky: 7

PříspěvekZaslal: 24. únor 2012, 16:09:06    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
]semo[



Založen: 29. 07. 2007
Příspěvky: 1526
Bydliště: Telč

PříspěvekZaslal: 26. únor 2012, 19:41:08    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
mkcz



Založen: 24. 02. 2012
Příspěvky: 7

PříspěvekZaslal: 26. únor 2012, 22:18:08    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
]semo[



Založen: 29. 07. 2007
Příspěvky: 1526
Bydliště: Telč

PříspěvekZaslal: 27. únor 2012, 08:23:54    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
]semo[



Založen: 29. 07. 2007
Příspěvky: 1526
Bydliště: Telč

PříspěvekZaslal: 27. únor 2012, 13:07:00    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
mkcz



Založen: 24. 02. 2012
Příspěvky: 7

PříspěvekZaslal: 27. únor 2012, 18:35:48    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
]semo[



Založen: 29. 07. 2007
Příspěvky: 1526
Bydliště: Telč

PříspěvekZaslal: 27. únor 2012, 20:52:58    Předmět: Odpovědět s citátem

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.
....

citace:
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

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
Zobrazit příspěvky z předchozích:   
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> Obecné Časy uváděny v GMT + 1 hodina
Jdi na stránku 1, 2  Další
Strana 1 z 2

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra
Nemůžete odpovídat na témata v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete hlasovat v tomto fóru


Powered by phpBB © 2001, 2005 phpBB Group


Vzhled udelal powermac
Styl "vykraden" z phpBB stylu MonkiDream - upraveno by rezna