Różne typy pól w treeView z GTK sharp

0

Piszę aplikację do reprezentacji danych xml, ich modyfikacji i zapisu. Mam problem z budową niektórych funkcjonalności interfejsu w GTK.

Tak wygląda aplikacja: http://i.imgur.com/c1gnc70.jpg
Lewa kolumna stanowi etykiety informujące jakie pole chcemy edytować natomiast prawe pola będą edytowane. Problem w tym że muszę z góry ustalić dla całej kolumny jakiego typu będzie, np textfield, checkbox bądź progress bar. Ja natomiast potrzebuję rożnych pól w różnych wierszach, na przykład: pola takie jak ID muszą być text fieldem bo przyjmują dowolny ciąg znaków, pole Race z kolei powinno mieć Combo boxa aby wybrać jedną z kilku dostępnych ras. Dla pola flying powinien być checkbox bo to pole typu bool.
Jak to zrobić korzystając z TreeView? Tak właściwie czy to w ogóle jest możliwe przy użyciu treeView?

0

W C jest to możliwe, nie określa się typu komórki tylko korzysta się z obiektu GtkCellRenderer. Kiedy GtkCellRenderer otrzyma daną na jej podstawie decyduje co wyświetlać tekst, combobox, pixbuf, itp.
Nie wiem jak to jest w GTK Sharp, ale uważam że jest do zrobienia :)

0

Tylko że użycie cellrenderera ustala co wyświetla dla całej kolumny.

0

Tak ale ona jest ogolnego przeznaczenia z niej sie wywodza nastepne do wyswietlania konkretnych danych.
Zobac na http://developer.gnome.org/gtk2/2.24/GtkCellRenderer.html
Ustalasz co prawda dla calej kolumny, przeciaz odpowiednie sygnaly i na podstawie jakie dane otrzymasz rysujesz odpowiednie kontrolki.

0

Tylko jak ustalam jaki jest renderer w gtk sharp to podaje cellrenderertext albo albo cellrenderertoggle co narzuca jeden typ dla całej kolumny.

1

Pisałem, że musisz skorzystać z obiektu ogólnego przeznaczanie jakim jest GtkCellRenderer, GtkCellRendererText jest pochodną GtkCellRenderer i wyspecjalizowaną do wyświetlania tektu.
GtkCellRenderer jest obiektem "niższego poziomu", w którym masz dostęp do rozmiarów wyświetlanej komórki, miejsca na ekranie, itp. GtkCellRenderer sama nie wyświetli tekstu, combobox'a, itd., to Ty musisz na podstawie danych w kodzie programu podjąc decyzję co będzie wyświetlane...
Pewnie piszesz w Mono, jak będę miał czas sprawdzę, czy można uzyć GtkCellRenderer. Może się okazać, że niedopuszczalne jest użycie GtkCellRenderer, a wymuszone jest skonkretyzowanie typu - wtedy kicha, musiałbyś pisać swój moduł...

0

Sprawdziłem CellRenderer. Jego użycie jest nie możliwe ze względu na poziom ochrony :P
EDIT: aczkolwiek znalazłem rozwiązanie ^^ setCellDataFunc ustawia odpowiedni Renderer ze względu na otrzymane dane. Jest tylko jedne problem, nie wiem jak identyfikować wiersze. Tzn w pierwszym wierszu mam inta, w drugim stringa, w trzecim boola. Oczywiście to tylko przykłąd, model wygląda innaczej :P
Cały problem rozbija się o to że kliknięcie w dowolny wiersz wywołuje ten sam handler, stąd też problem jak wywołać właściwy getter z modelu aby odwołać się do odpowiedniej wartości?

1

Podaj źródło gdzie znalazłeś setCellDataFunc.
Bo mi się wydaje, że to działa jeśli masz skonkretyzowany typ komórki, a chcesz żeby dane były w niej wyświetlane w sposób inny niż domyślny.

0

http://www.mono-project.com/GtkSharp_TreeView_Tutorial
w rozdziale Controlling how the model is used. Tylko rzeczywiście jest problem z tym że komórka jest typu string. Zasadniczo to definicja modelu który odpowiada za treeView nie pozwala na wpisanie czegoś innego niż string. Wygląda ona tak:
private Gtk.TreeStore itemsList = new Gtk.TreeStore (typeof (string), typeof (string));
(...)
tree.Model = itemsList;

dodanie elementu:
itemsList.AppendValues ("ID", "true");

Jeżeli stringa true zastąpię boolem true to wywala błąd konwersji: Gtk-WARNING **: gtktreestore.c:765: Unable to convert from gboolean to gchararray
Przy czym aplikacja i tak się kompiluje i uruchamia.

EDIT: Zapoznałem się z tym jeszcze raz i na stronie zrobili model typu Song (klasa z odpowiednimi polami). Ja mam natomiast plik .cs wygenerowany na bazie schemy xsd. Składa się z masy partial class, każda ma swoje pola, settery i gettery. Stąd też czy powinienem właśnie tego użyć do stworzenia modelu i na podstawie tego wyświetlać odpowiednie informacje?

PS: Problem jest taki że każde kolejne pole to kolejny wiersz.

0

Nie znam C#, w ogóle jakoś obiektowe języki nie przemawiają do mnie :)
Analizując treść linka, który podałeś uważam, że jest możliwość dodania danych np. integer, sprawdź:

Gtk.ListStore dane = new Gtk.ListStore (typeof(string),typeof (int));
dane.AppendValues ("ID", 1);

W C jest możliwość dodania do modelu "nadmiarowych" danych, które nie są interpreterowane bezpośrednio przez GtkTreeView:

enum
{
  TEKST = 0,
  LICZBA,
  COMBO,
  CHECK
};

  GtkTreeStore * magazyn_drzewa;
  GtkTreeIter rodzic, potomek;

  magazyn_drzewa = gtk_tree_store_new( ILOSC_KOLUMN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT ); /* ILOSC_KOLUMN = 3 (ilosc kolum w modelu, nie w GTkTreeView) */

   /* Tworzy pusty węzeł bez potomka */
   gtk_tree_store_append( magazyn_drzewa, & rodzic, NULL );
    /* Wypełnia danymi stworzony węzeł */
    gtk_tree_store_set( magazyn_drzewa, & rodzic, 0, "1_Dana_w_kolumnie_1", 1, "1_Dana_w_kolumnie_2", 2, TEKST, - 1 );
   /* Tworzy pusty węzeł bez potomka */
    gtk_tree_store_append( magazyn_drzewa, & rodzic, NULL );
    /* Wypełnia danymi stworzony węzeł */
    gtk_tree_store_set( magazyn_drzewa, & rodzic, 0, "2_Dana_w_kolumnie_1", 1, "2_Dana_w_kolumnie_2", 2, COMBO, - 1 );
     /* Tworzy pusty węzeł bez potomka */
   gtk_tree_store_append( magazyn_drzewa, & rodzic, NULL );
    /* Wypełnia danymi stworzony węzeł */
    gtk_tree_store_set( magazyn_drzewa, & rodzic, 0, "3_Dana_w_kolumnie_1", 1, "3_Dana_w_kolumnie_2", 2, CHECK, - 1 );

Trzecią kolumne nie wiąże się z wyświetlaniem w GtkTreeView, można ją później wykorzystać w setCellDataFunc do odpowiedniego wyświetlania zawartości.

Tutaj http://cpp0x.pl/kursy/Kurs-GTK+-C++/GtkTreeView/447 masz moje wypociny na temat GtkTreeView i magazynie danych w C, być może Ci się przyda.

0

Tylko w takiej sytuacji
Gtk.ListStore dane = new Gtk.ListStore (typeof(string),typeof (int));
dane.AppendValues ("ID", 1);

wszystkie dane muszą być int, jak potrzebuje przechować stringa to nic z tego.

Myślałem żeby zrobić tak:
Gtk.ListStore dane = new Gtk.ListStore (typeof(string),typeof (Object));

Dzięki temu będę mógł przechować dowolny typ a potem w funkcji sprawdzać jaki typ jest przechowane w tym parametrze typu Object i na podstawie tego odpalać odpowiedni renderer. Tylko jeszcze nie wiem jak sprawdzić typ object to wszystko się sypie:P GTK# tam gdzie jest typeof(Object) towrzy gtkSharpValue, dziwne to już się robi xD

EDIT: Właśnie przez to GtkSharpValue się sypie ponieważ to w modelu było podane jako typeof(Object) i gdy chce w to pole wstawić int to pisze: unable to convert gInt to GtkSharpValue ;/

0

Ja miałem na myśli coś takiego (pdeudokod):

enum
{
TEKST = 0,
LICZBA,
COMBO,
CHECK
};

Gtk.ListStore dane = new Gtk.ListStore (typeof(string),typeof (int));
dane.AppendValues ("Dana1", TEKST);
dane.AppendValues ("TRUE", CHECK);
dane.AppendValues ("123", LICZBA);

na podstawie tego "nadmiarowego" pola wiesz z czym masz do czynienia.

1 użytkowników online, w tym zalogowanych: 0, gości: 1