CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - StringGrid - częściowa edycja komórek

StringGrid - częściowa edycja komórek

dział ogólny

StringGrid - częściowa edycja komórek

Nowy postprzez oneiro » wtorek, 5 lutego 2013, 16:33

Witam,

Urodził się kolejny problem. Potrzebowałem w StringGridzie elementy typu CheckBox i skorzystałem z poniższego kodu:

http://www.borlandtalk.com/checkbox-in- ... 17770.html

Działa świetnie do momentu włącznie edycji w komórkach (goEditing). Przy włączonej edycji komórek praca z CheckBoxem jest dziwna, wskakuje mi kursor, jak się "odklikam" z komórki to CheckBox jest zaznaczony, ale funkcjonalność nie ta (po prostu jest to mało intuicyjne rozwiązanie).

Czy wobec tego, dla części komórek w StringGridzie można WYłączyć edycję komórek (dla zawierających CheckBox'a), a dla pozostałych edycję WŁączyć?

Ogólnie problem wyrasta poza CheckBoxa, gdyż zależnie od parametrów będę chciał mieć część komórek edytowalnych, a część nie (i będzie to zmieniane w trakcie programu). Oczywiście mogę to rozwiązać za pomocą elementów Edit ułożonych w macierz, ale nie jest to eleganckie rozwiązanie.
Dodam, że wymiar StringGrida będzie stały (ilość wierszy i kolumn).
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: StringGrid - częściowa edycja komórek

Nowy postprzez Mironas » wtorek, 5 lutego 2013, 17:15

oneiro napisał(a):Czy wobec tego, dla części komórek w StringGridzie można WYłączyć edycję komórek (dla zawierających CheckBox'a), a dla pozostałych edycję WŁączyć?

KOD cpp:     UKRYJ  
void __fastcall TForm1::StringGrid1SelectCell(TObject *Sender, int ACol, int ARow, bool &CanSelect)
{
  TStringGrid *pGrid = static_cast<TStringGrid*>(Sender);
  bool IsCheckBox = HIWORD(reinterpret_cast<int>(pGrid->Objects[ACol][ARow]));

  if ( IsCheckBox )
    StringGrid1->Options = StringGrid1->Options >> goEditing;
  else
    StringGrid1->Options = StringGrid1->Options << goEditing;
}
 
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: StringGrid - częściowa edycja komórek

Nowy postprzez oneiro » wtorek, 5 lutego 2013, 17:33

@Mironas dzięki działa :)
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: StringGrid - częściowa edycja komórek

Nowy postprzez oneiro » wtorek, 5 lutego 2013, 19:39

He, poległem na jeszcze jednej rzeczy - jak dodać opis (tj pole Caption) do tak utworzonego CheckBoxa?
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: StringGrid - częściowa edycja komórek

Nowy postprzez Cyfrowy Baron » środa, 6 lutego 2013, 00:14

oneiro napisał(a):ak dodać opis (tj pole Caption) do tak utworzonego CheckBoxa?


Tego nie rozumiem, przecież CheckBox prócz kwadracika zawiera pole Caption, więc niczego nie trzeba dodawać, wystarczy ustawić odpowiednią długość całego CheckBox'a gdyż automatycznie się nie zmienia.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: StringGrid - częściowa edycja komórek

Nowy postprzez oneiro » środa, 6 lutego 2013, 12:17

No właśnie, obiekt tworzy się dynamicznie i nie wiem w którym miejscu dodać (tj przypisać) wartość do Caption. Normalnie nie ma problemu, a w tym kodzie trochę się zgubiłem :/
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: StringGrid - częściowa edycja komórek

Nowy postprzez Mironas » środa, 6 lutego 2013, 12:24

Po prostu wpisz tekst do właściwych komórek:
KOD cpp:     UKRYJ  
StringGrid1->Cells[kolumna][wiersz] = "Ala ma kota";
 
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: StringGrid - częściowa edycja komórek

Nowy postprzez Cyfrowy Baron » środa, 6 lutego 2013, 12:48

oneiro napisał(a):obiekt tworzy się dynamicznie i nie wiem w którym miejscu dodać (tj przypisać) wartość do Caption.


No jak nie wiesz? W momencie gdy obiekt jest rysowany (umieszczany w komórce), czyli np:

KOD cpp:     UKRYJ  
void __fastcall TForm1::StringGrid1SelectCell(TObject *Sender, int ACol, int ARow, bool &CanSelect)
{
  TStringGrid *pGrid = static_cast<TStringGrid*>(Sender);
  bool IsCheckBox = HIWORD(reinterpret_cast<int>(pGrid->Objects[ACol][ARow]));

  if ( IsCheckBox )
  {
    StringGrid1->Options = StringGrid1->Options >> goEditing;
    CheckBox1->Caption = "Caption";
  }
  else
    StringGrid1->Options = StringGrid1->Options << goEditing;
}


Lub w każdym innym momencie, gdy zachodzi konieczność zmiany właściwości Caption obiektu typu TCheckBox.

Stworzyłem kiedyś podobną poradę na umieszczani obiektu typu TComboBox w komórkach tabeli http://programowanie.cal.pl/cyfbar/stringgrid.html#grid10.

Ja naprawdę nie rozumiem jak możesz mieć problem ze zmianą właściwości Caption obiektu CheckBox. Przecież kiedy byś temu obiektowi nie przypisał Caption to po wyświetleniu tego obiektu będzie on posiadał dokładnie taki tekst w tej właściwości?!?
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: StringGrid - częściowa edycja komórek

Nowy postprzez oneiro » środa, 6 lutego 2013, 13:05

@Mironas :shock: dzięki, nawet o tym nie pomyślałem


@Cyfrowy Baron

KOD cpp:     UKRYJ  
CheckBox1->Caption = "Caption";
 


Hehe, wydawało mi się, że muszę odwoływać się poprzez pGrid->Objects[ ACol ][ ARow ] ... i tak dalej i kombinowałem w tą stronę.

No dobrze, a co jeśli mam już jakieś CheckBox'y na formularzu, skąd mam wiedzieć, czy będzie to CheckBox4 czy też ChecBox10?

Nie mniej dzięki za pomoc.
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: StringGrid - częściowa edycja komórek

Nowy postprzez Cyfrowy Baron » środa, 6 lutego 2013, 13:51

Ty tworzysz ten program, więc skoro program wie, który jest który to i Ty - jako, że zaprogramowałeś ten program - powinieneś to wiedzieć. Zadajesz dziwne pytania. Czy na pewno masz pełną kontrolę nad tym programem?
Przypuszczam, że problem nie leży w tam, gdzie go przedstawiasz. Nie ważne czy obiekt jest tworzony dynamicznie czy nie, istotne jest to, że każdy obiekt musi mieć inną nazwę, więc odwołuj się do tej nazwy.

KOD cpp:     UKRYJ  
reinterpret_cast<TCheckBox *>( pGrid->Objects[ACol][ARow] )


To ci zwróci wskaźnik na właściwy obiekt. Poczytaj sobie o rzutowaniu i przypisaniu polimorficznym: Rzutowanie typów, przypisanie polimorficzne.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: StringGrid - częściowa edycja komórek

Nowy postprzez oneiro » środa, 6 lutego 2013, 15:01

Obiekty tworzone dynamiczne to nie najsilniejsza moja strona, dzięki za artykuł, na pewno przeczytam

EDIT.

Przeczytałem, ciekawy artykuł, ale nie rozumiem, jak tworzą się CheckBox w linkowanej metodzie, tam nawet słowo "CheckBox" w kodzie nie występuje (poza komentarzami), na razie nie mam czasu na zrozumienie tego (działa i tyle mi wystarcza - wiem wiem, że tak nie ładnie ale co pocznę, mało czasu, a program tworzę "po godzinach" :/).
Skorzystam z metody @Mironas, na moje potrzeby wystarcza.

Ale jak to zwykle bywa, urodził się kolejny problem, wycinek mojego formularza wygląda tak (z wypełnionymi losowymi danymi, nie wnikamy w sens).
Obrazek

O ile z CheckBox'ami sobie poradziłem, o tyle z ComboBox'ami nie (skorzystałem z metody Barona dotyczącej ComboBox'ów).A problem dotyczy zapisu i odczytu wartości z ComboBox'ów.

Na ustawienie wymyślałem takie coś w "Form1::StringGrid3DrawCell"

KOD cpp:     UKRYJ  
for (unsigned i=1; i<9; i++)
 StringGrid3->Cells[1][i] = myEditor->Items->Strings[1];
 


Ale nie działa tak jak chcę - działa ale, raz, po wybraniu pozycji, ale dwa, po wybraniu pozycji w kółko wywołuje się samo siebie, także jest to zły kod.
Ale odczyt wartości, coś w podobny deseń, ale gdzie to wsadzić?
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: StringGrid - częściowa edycja komórek

Nowy postprzez Cyfrowy Baron » czwartek, 7 lutego 2013, 00:41

Po co ci ta pętla w zdarzeniu OnDrawCell, przecież to zdarzenie ma wskaźniki na kolumny i wiersze, więc wystarczy odpowiednio skonstruować warunek:

KOD cpp:     UKRYJ  
void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect, TGridDrawState State)
{
 if( ACol == 1 )
 {
   if( ARow >= 1 && ARow < 9 )
   {
      StringGrid3->Cells[1][ARow] = myEditor->Items->Strings[1];
   }
 }
}
Czy na pewno chcesz umieszczać ten kod w zdarzeniu odpowiedzialnym za odrysowywanie komórek?
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: StringGrid - częściowa edycja komórek

Nowy postprzez oneiro » czwartek, 7 lutego 2013, 01:22

Właśnie nie wiedziałem, w którym miejscu go umieścić, w końcu zdecydowałem się na FormCreate

KOD cpp:     UKRYJ  
for (unsigned i=1; i<=9; i++)
  {
    StringGrid3->Cells[1][i] = myEditor->Items->Strings[1];
    MoveEditor();
  }
for (unsigned i=1; i<=9; i++)
  {
    StringGrid3->Cells[3][i] = myEditor->Items->Strings[2];
    MoveEditor();
  }
 


i takie coś działa (tj wstępnie ustawia mi wybrane combboxy), ale w komórce [0,0] pojawia mi się ComboBox, które o dziwo mogę wybrać. Po wybraniu Combo opcja ta znika. I nie wiem skąd ona jest (tj na pewno z kodu powyżej, ale nie widzę związku).

PS. Baron, chyba podróżujesz w czasie, u mnie jest 0.18, a posta napisałeś 0.41 :) (pewnie czas letni/zimowy)

PS2. Twojej metody nie sprawdziłem jeszcze wydaje się dobra na pierwszy rzut oka, a możesz wytłumaczyć obawy związane z OnDrawCell..... kod sprawdzę jutro...e tzn. później dziś
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: StringGrid - częściowa edycja komórek

Nowy postprzez Cyfrowy Baron » czwartek, 7 lutego 2013, 09:33

oneiro napisał(a):a możesz wytłumaczyć obawy związane z OnDrawCell....


Nie mam obaw, ale OnDrawCell jest wywoływane każdorazowo gdy trzeba odrysować tabelę, a wraz z wywołaniem tego zdarzenia wywoływany jest cały zawarty w nim kod. Dla przykładu przesłonięcie czymś tabeli spowoduje jej odrysowanie, przesunięcie okna też, czyli zawsze gdy system musi odrysować okno programu.

oneiro napisał(a):ale w komórce [0,0] pojawia mi się ComboBox,


Dzieje się tak dlatego, że panel na którym masz ComboBox zostaje przypisany pierwotnie do obiektu StringGrid:

KOD cpp:     UKRYJ  
 myPanel->Parent = StringGrid3;


Ale nie określasz w której komórce ma się pojawić, więc pojawia się w pierwszej. Jeżeli jednak w konstruktorze klasy przy tworzeniu tego panelu ustawiasz jego właściwość Visible na false, to nie powinien być widoczny.

oneiro napisał(a):Baron, chyba podróżujesz w czasie, u mnie jest 0.18, a posta napisałeś 0.41 :) (pewnie czas letni/zimowy)


Forum pokazuje źle czas, próbowałem to przestawiać z uwzględnieniem czasu zimowy/letni, ale nic się nie zmieniało.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: StringGrid - częściowa edycja komórek

Nowy postprzez Mironas » czwartek, 7 lutego 2013, 12:10

Inny sposób na CheckBox-a w komórce StringGrid-a.
Zamiast tworzyć dynamicznie CheckBox można narysować 'coś podobnego'. Checked/unchecked można powiązać z zawartością komórki - u mnie to wartość 1/0. Takie rozwiązanie wydaje się być prostsze do ogarnięcia przez początkującego programistę:
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------
void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol, int ARow,
          TRect &Rect, TGridDrawState State)
{
  // Rysuje pole CheckBox
  // --------------------
  if ( ACol==1 && ARow>0 )
  {
    // tlo
    StringGrid1->Canvas->Pen->Color = StringGrid1->Canvas->Brush->Color;
    StringGrid1->Canvas->Rectangle(Rect);
    // rysowanie pustego kwadratu
    int x = Rect.left + Rect.Width()/2 - 5;
    int y = Rect.top + Rect.Height()/2 - 5;
    TRect rect = TRect(x, y, x+11, y+11);
    StringGrid1->Canvas->Pen->Color = clBlack;
    StringGrid1->Canvas->Pen->Width = 2;
    StringGrid1->Canvas->Rectangle(rect);
    // rysowanie znaku 'x'
    if ( StringGrid1->Cells[ACol][ARow] == "1" )
    {
      rect = TRect(x+2, y+2, x+8, y+8);
      StringGrid1->Canvas->Brush->Color = clBlack;
      StringGrid1->Canvas->FillRect(rect);
    }
    StringGrid1->Canvas->Pen->Width = 1;
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StringGrid1Click(TObject *Sender)
{
  // Zmiana select-a komorki
  // -----------------------
  int k = StringGrid1->Col;
  int w = StringGrid1->Row;
  if ( k==1 && w>0 )
  {
    String s = StringGrid1->Cells[k][w];
    StringGrid1->Cells[k][w] = (s=="1") ? "0" : "1";
  }
}
//---------------------------------------------------------------------------
 


Podobnie można rozwiązać problem z 'ComboBox-em' - tzn narysować w komórce przycisk a po jego kliknięciu wyświetlić PopupMenu z właściwymi opcjami.

Za ten post autor Mironas otrzymał podziękowanie od:
Yari27
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Następna strona

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 9 gości

cron