Плъзнете и пуснете между различни изгледи на разнородна йерархия на данни

Имам йерархична структура от данни, която трябва да се визуализира в няколко Qt изгледа (или джаджи). Йерархията на данните се състои от разнородни типове елементи, като:

House
 |- Floor
 |   |- Room
 |   |   |- Window
 |   |   |- ...
 |   |- Room
 |   |   |- ...
 |- ...

Всички елементи (Къща, Етаж, Стая, ...) имат атрибути, които могат да бъдат показани. Имайте предвид, че това е опростен пример. Йерархията е съставена от различни възгледи. напр. само идентификатора на стая в списък за шаблони (QListView/Widget), персонализиран изглед (йерархия от подкласове на QWidget за всеки елемент), подробен изглед за редактиране на свойствата на напр. етаж (подклас QWidget или QWizard).

Възможно е също така да плъзгате и пускате елементи между няколко екземпляра. напр. преместване на стаи на различни етажи. Възможно е да декларирате конкретен етаж като шаблон и да плъзнете етаж от списъка с шаблони напр. персонализираният изглед (където е съставена къща).

Qt използва модел/изглед архитектура за разделяне на данните , модел и изглед. Тъй като имам напълно различни видове изгледи, предполагам, че за всеки изглед е необходим съответен модел. В случая на моя персонализиран йерархичен изглед, всеки елемент има своя собствена визуализация и следователно йерархията съществува (но не трябва да съществува) три пъти: йерархията на данните, йерархията на модела и йерархията на изгледа. Това става наистина объркващо, защото всяка йерархия трябва да се актуализира, ако даден елемент се плъзга и пуска, премахва или копира. По-добър подход би бил Presentation-Abstraction-Control модел. PAC обаче не е приложим, тъй като родителят на QWidget трябва да бъде зададен, за да се вградят деца в техния родителски изглед. Следователно QWidget не може да препраща към агент, който отговаря за моделирането на йерархията.

Струва ми се, че Qt е много добър в представянето на списъци, таблици и дървета от хомогенни типове данни (като низове). В моя случай всеки елемент има индивидуален набор от атрибути, които не могат просто да бъдат изразени под формата на таблица. В тази дискусия не се препоръчва поставянето на квадратно колче в кръгла дупка. Което означава, да не налагате никакъв дизайн в представяне на таблица.

Ядрото на моя проблем е да обединя следните характеристики в една концепция за дизайн: Визуализация на йерархични данни с различни нива на детайлност. Поддържа плъзгане и пускане между изгледи, което копира данните и генерира подходящи компоненти за модел/изглед. Поддържане на плъзгане и пускане в изглед, което засяга йерархията на данните, модела и изгледа (което бих искал да избегна прилагането три пъти). Не мога да осигуря един модел за къща с всички нейни подкомпоненти, тъй като подовете и стаите са твърде сложни. Намирам за тромаво да управлявам три (или повече) йерархии за едно действие с плъзгане и пускане, изтриване или копиране.

Има ли най-добра практика, шаблон за проектиране или може би различен подход към моя проблем? Този проблем разрешим ли е с Qt?

Благодарен съм за всяко предложение.


person Marian    schedule 16.04.2013    source източник


Отговори (1)


Имах подобен проблем за известно време с моята йерархична структура. Всичко в архитектурата модел-изглед-делегиране на Qt зависи от това как организирате данните си и колко сложни сте готови да направите. За много прости приложения има смисъл да се прилагат неща от подход, базиран на елементи, редактиране на показването на елементи на ниво изглед. Това става много объркано много бързо.

Звучи сякаш сте готови да станете доста сложни, така че бих препоръчал подход, базиран на модел. Можете да контролирате почти всичко на ниво модел, включително някои основни елементи на дисплея, организация на данните и (най-важното) иерархии.

Намерих за полезно, когато започвам, обектите ми да наследяват QStandardItem и подкласове QStandardItemModel, тъй като QStandardItem вече има настроена йерархия родител-дете и индексиране за мен. Харесва ми да увеличавам Qt::UserRole и да присвоявам enum стойност на всеки от моите потребителски типове данни. Например:

enum FloorProperties
{
    DAT_CARPETING = Qt::UserRole +100,
    DAT_AREA = Qt::UserRole +101,
    DAT_FLOORNUM = Qt::UserRole +102
}

Дори и да не искате да свързвате съхранена стойност с всяка роля на данни (като използвате удобния QStandardItem::setData()), можете да персонализирате QStandardItemModel::data() за връщане на изчислена стойност, съхранена стойност, каквото и да е. Персонализирането на модела ви позволява да мислите за всеки елемент като за обект, а не като отделна клетка в таблицата/списъка.

Стандартните изгледи трябва да ви дадат повечето от това, от което се нуждаете като цяло. Персонализирайте дисплея за определени типове данни (Етажи, Windows, цели числа, низове и т.н.) с помощта на делегати. Надявам се, че има някакъв смисъл.

person Phlucious    schedule 16.04.2013
comment

Ако използвате onClickListner в customAdapter, onitemClickListner няма да работи. Отговорих на въпроса, защото не мога да коментирам поради отвращение

public class CustomListAdapter extends BaseAdapter {

private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;


public CustomListAdapter (Activity a, ArrayList<HashMap<String, String>> d) {
    activity = a;
    data=d;
    inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

}

public int getCount() {
    return data.size();
}

public Object getItem(int position) {
    return position;
}

public long getItemId(int position) {
    return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
    View vi=convertView;
    if(convertView==null)
        vi = inflater.inflate(R.layout.layout1, null);

    Checkbox Checkeditem= (Checkbox )vi.findViewById(R.id.checkitem); 


    HashMap<String, String> listitem = new HashMap<String, String>();
    listitem = data.get(position);

    // Setting all values in listview
    Checkeditem.setText(listitem .get(MainActivity.strTagDate));

    return vi;
}}    

Във вашата основна дейност
CustomListAdapter adapter = new CustomListAdapter (Mainactivity.this, aaSubCategory); lvUserInterest.setAdapter(adapter);

- person Marian; 17.04.2013