CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - TListView gpogubienie zmiana koloru w komórkach

TListView gpogubienie zmiana koloru w komórkach

dział ogólny

TListView gpogubienie zmiana koloru w komórkach

Nowy postprzez Darek_C++ » poniedziałek, 13 grudnia 2010, 17:28

Czy można ustawić wygląd czcionki / tekstu w poszczególnych komórkach w komponencie TListView np:.
KOD cpp:     UKRYJ  
TListItem * ElementListy = ListView1->Items->Add();
ElementListy->Caption = "Pierwszy";

ElementListy->SubItems->Add("---");

ElementListy->SubItems->Add("Kolor czerwony pogrubiona czcionka");

ElementListy->SubItems->Add("Kolor zielony normalna czcionka");
Jeśli tak to jak to zrobić ?



W zasadzie to chodzi o zmianę koloru już wyplecionych komórek w zależności od statusu. Akcja wykonywana w wątku:

KOD cpp:     UKRYJ  
if(ststusOK)
{
        ListView1->Items->Item[this->nrNaListViev]->SubItems->Strings[1] = "Prawidłowy"; // Kolor zielony
}
else
{
        ListView1->Items->Item[this->nrNaListViev]->SubItems->Strings[1] = "Błędny";  // Kolor czerwony
}
Mam kod który w zdarzeniu OnCustomDrawSubItem podczas wypełniania komórek ustawia kolor ich tekstu:

KOD cpp:     UKRYJ  
void __fastcall TForm1::ListView1CustomDrawSubItem(TCustomListView *Sender,
          TListItem *Item, int SubItem, TCustomDrawState State, bool &DefaultDraw)
{
        if(SubItem == 3)
        {
                randomize();
                if( RandomRange(1, 10) >= 5)
                {
                        Sender->Canvas->Font->Color = clRed;
                }
                else
                {
                        Sender->Canvas->Font->Color = clGreen;
                }
        }
}


Ale mi chodzi o zmianę koloru w komórkach już wypełnionych :(
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: TListView gpogubienie zmiana koloru w komórkach

Nowy postprzez Cyfrowy Baron » poniedziałek, 13 grudnia 2010, 19:40

Trzeba posłużyć się zdarzeniem OnCustomDrawSubItem dla SubItem a dla kolumny pierwszej OnCustomDrawItem. W przykładzie posłużę się jednak SubItem. Poza tym do określania kolorów posłużę się tablicą asocjacyjną, by nie tworzyć pętli w połączeniu z dwiema tablicami do określenia wielu kolorów:
W pliku nagłówkowym dodajemy nagłówek #include <map> a w sekcji private deklarujemy tablicę:

KOD cpp:     UKRYJ  
#include <map>

private:
        std:: map<AnsiString, TColor>  tabColor;


Resztę robimy w pliku źródłowym. Tablicę trzeba wypełnić kolorami a w zdarzeniu OnCustomDrawSubItem trzeba te kolory przypisać poszczególnym SubItem w zależności od tego jaki wpis zawierają. Tobie chodziło o stany prawda-fałsz, ja jednak nieco to rozwinąłem, byś przedstawić to szerzej.
KOD cpp:     UKRYJ  
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 tabColor["Czerwony"] = clRed;
 tabColor["Niebieski"] = clBlue;
 tabColor["Zielony"] = clGreen;
 tabColor["Żółty"] = clYellow;
 tabColor["Brązowy"] = clMaroon;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListView1CustomDrawSubItem(TCustomListView *Sender,
        TListItem *Item, int SubItem, TCustomDrawState State, bool &DefaultDraw)
{
 AnsiString aColor = Item->SubItems->Strings[ SubItem - 1];

 if(tabColor.find( aColor ) != tabColor.end())
 {
   ListView1->Canvas->Font->Color = tabColor[aColor];
 }
 else
 {
   ListView1->Canvas->Font->Color = clBlack;
 }
}
//---------------------------------------------------------------------------


Dla Twoich potrzeb, będzie to oczywiście prostsze i nie potrzebna jest żadna tablica:

tego kodu nie testowałem, pisałem z pamięci, więc może zawierać błędy.
KOD cpp:     UKRYJ  
void __fastcall TForm1::ListView1CustomDrawSubItem(TCustomListView *Sender,
        TListItem *Item, int SubItem, TCustomDrawState State, bool &DefaultDraw)
{
 AnsiString boolValue = Item->SubItems->Strings[ SubItem - 1];

 if(boolValue == "Prawidłowy")
 {
   ListView1->Canvas->Font->Color = clGreen;
 }
 else if(boolValue == "Błędny")
 {
   ListView1->Canvas->Font->Color = clRed;
 }
 else
 {
     ListView1->Canvas->Font->Color = clBlack;
 }
}
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
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: TListView gpogubienie zmiana koloru w komórkach

Nowy postprzez Darek_C++ » poniedziałek, 13 grudnia 2010, 20:14

OK, ale TListViev ma już wczytane dane np listę adresów www. Wyjściowo jest wypełniony np:
[Adres] [ Status]
http://www.adres1.pl - Status nie sprawdzony
http://www.adres2.pl - Status nie sprawdzony
http://www.adres3.pl - Status nie sprawdzony
http://www.adres3.pl - Status nie sprawdzony

W wątku pobieram kod HTML danej strony i w zależności od wyniku operacji tekst w komórce powinien zmienić status na np "Jest" kolor zielony "Nie ma" kolor czerwony .
Innymi słowy jak zmienić kolor tekstu np dla kolumny [Nagłówek 4] -> tekst "czerwony" który jest koloru czerwonego w kodzie jest to:
ListView1->Items->Item[2]->SubItems->Strings[2] = "Czerwony";

Czyli zmienić kolory dla już istniejących danych w komórkach ?
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: TListView gpogubienie zmiana koloru w komórkach

Nowy postprzez Cyfrowy Baron » poniedziałek, 13 grudnia 2010, 20:38

No przecież testowy program zmienia kolor tekstu już znajdującego się w tabeli. Zdarzenie OnCustomDrawSubItem działa dynamicznie, reaguje na zmianę zawartości komórek. Podałem Tobie gotowe rozwiązanie. Numer kolumny określa zmienna SubItem, więc jeżeli to ma być kolumna 4, to wystarczy dodać warunek if(SubItem == 3) a potem w tym warunku kolejne sprawdzające zawartość wierszy. Zdarzenie sprawdza zawartość każdego wiersza.
Nie rozumiem z czym masz jeszcze problem. :roll:
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: TListView gpogubienie zmiana koloru w komórkach

Nowy postprzez Darek_C++ » poniedziałek, 13 grudnia 2010, 20:42

Zaraz to przetestuje na działającym programie...
Niestety, ale nie działa zgodnie z oczekiwaniem :(
Użycie w kodzie wątku [nieistotne fragmenty pominąłem]:
KOD cpp:     UKRYJ  
void __fastcall WatekSprawdz::Execute()
{
        Synchronize(&PobierzStart);
        this->WykonajZadanieGet();
        Synchronize(&PobierzStop);
}
void __fastcall WatekSprawdz::MyListView1CustomDrawSubItem(TCustomListView *Sender,
                TListItem *Item, int SubItem, TCustomDrawState State, bool &DefaultDraw)
{
        if(Item->Index == this->nrNaListViev)
        {
                if(SubItem == 2)
                {
                        if(this->kodOdpInt == 200)
                        {
                           Sender->Canvas->Font->Color = clGreen ;
                        }
                        else
                        {
                           Sender->Canvas->Font->Color = clRed;
                        }
                }
        }
}

void __fastcall WatekSprawdz::PobierzStop()
{
        this->End = GetTickCount();

        String czasZadania =  FloatToStr((this->End - this->Start) / 1000) + " s.";
        ListView1->Items->Item[this->nrNaListViev]->SubItems->Strings[0] = (String) this->kodOdpInt;
        ListView1->Items->Item[this->nrNaListViev]->SubItems->Strings[2] = czasZadania;
        this->ListView1->OnCustomDrawSubItem = MyListView1CustomDrawSubItem;
}
 

Wątki wywołuje w timerze wiec nieraz działa kilka jednocześnie.
Na początku się kolorują, ale jak przesunę suwakiem TListView zmieniają się na czarne :(

W polu klasy wątka nrNaListViev jest nr lini z ListView z jakiej został pobrany adres do sprawdzenia.
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: TListView gpogubienie zmiana koloru w komórkach

Nowy postprzez Darek_C++ » niedziela, 19 grudnia 2010, 01:19

Jakiego innego działającego sposobu nie ma na to kolorowanie w TListViev ?
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: TListView gpogubienie zmiana koloru w komórkach

Nowy postprzez Cyfrowy Baron » niedziela, 19 grudnia 2010, 11:38

Człowieku! To nigdy nie będzie Tobie działać, bo Ty nie rozumiesz zasady działania zdarzeń OnDraw, a tutaj OnCustomDraw. To jest wewnętrzne zdarzenie obiektu ListView i wszystkie warunki odnoszące się do zawartości ListView muszą być uzależnione od tego obiektu lub argumentów zdarzenia. To oznacza, że ten warunek if(this->kodOdpInt == 200) nie ma racji bytu w tym zdarzeniu, gdyż wogóle nie jest w żadne sposób związany z obiektem ListView. Zwóć uwagę na ten fragment użytego przez Ciebie kodu if(Item->Index == this->nrNaListViev) lub tego if(SubItem == 2). Warunki są uzależnione od argumentów zdarzenia, więc są prawidłowe działają.
Kod: Zaznacz cały
                        if(this->kodOdpInt == 200)
                        {
                           Sender->Canvas->Font->Color = clGreen ;
                        }
                        else
                        {
                           Sen


To oznacza tyle, że jeżeli kodOdpInt ma wartość 200 to wszystkie teksty w SubItem2 będą zielone w przeciwnym razie będą czerwone.



Mój kod:

KOD cpp:     UKRYJ  
void __fastcall TForm1::ListView1CustomDrawSubItem(TCustomListView *Sender,
        TListItem *Item, int SubItem, TCustomDrawState State, bool &DefaultDraw)
{
 AnsiString aColor = Item->SubItems->Strings[ SubItem - 1];

 if(tabColor.find( aColor ) != tabColor.end())
 {
   ListView1->Canvas->Font->Color = tabColor[aColor];
 }
 else
 {
   ListView1->Canvas->Font->Color = clBlack;
 }
}


bez tablicy asocjacyjnej można by go zapisać tak:

KOD cpp:     UKRYJ  
void __fastcall TForm1::ListView1CustomDrawSubItem(TCustomListView *Sender,
        TListItem *Item, int SubItem, TCustomDrawState State, bool &DefaultDraw)
{
 if(Item->SubItems->Strings[ SubItem - 1] == "czerwony")
 {
   ListView1->Canvas->Font->Color = clRed;
 }
 else
 {
   ListView1->Canvas->Font->Color = clGreen;
 }
}


Widzisz, że warunek jest uzależniony od argumentów zdarzenia.



W Twoim przypadku by kod zadział i kolor całej kolumny kolumny SubItem zmienił kolor po zmianie wartości zmiennej kodOdpInt, musisz wymusić przerysowanie obiektu. Jest to konieczne, gdyż uzależniasz zmianę zawartości obiektu ListView od zmiennej w żaden sposób z tym obiektem nie związanej.
KOD cpp:     UKRYJ  
  this->kodOdpInt = 100;
  ListView1->Repaint();


Kolor zostanie zmieniony nie tylko w kolumnie SubItem, ale również we wszystkich po niej następujących. Jeżeli chcesz ograniczyć warunek tylko do jednej kolumny SubItem to musisz wprowadzić kontr-warunek określający kolor domyślny:

KOD cpp:     UKRYJ  
 if(SubItem == 2)
 {
  if(this->kodOdpInt == 200)
  {
   Sender->Canvas->Font->Color = clGreen ;
  }
  else
  {
   Sender->Canvas->Font->Color = clRed;
  }
 }
 else Sender->Canvas->Font->Color = clBlack;


Przemyśl zasadę działania tego zdarzenia bo kombinując po swojemu do niczego nie dojdziesz.
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: TListView gpogubienie zmiana koloru w komórkach

Nowy postprzez Darek_C++ » niedziela, 19 grudnia 2010, 12:25

Problem jest taki, że podany przez Ciebie kod:
Kod: Zaznacz cały
void __fastcall TForm1::ListView1CustomDrawSubItem(TCustomListView *Sender,
        TListItem *Item, int SubItem, TCustomDrawState State, bool &DefaultDraw)
{
if(Item->SubItems->Strings[ SubItem - 1] == "czerwony")
{
   ListView1->Canvas->Font->Color = clRed;
}
else
{
   ListView1->Canvas->Font->Color = clGreen;
}
}
Uruchamiany w wielu wątkach powoduje, że przez jakiś czas cele są kolorowane prawidłowo, a po pewnym czasie wszystkie teksty robią się czarne.
Sprawdź samemu...
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: TListView gpogubienie zmiana koloru w komórkach

Nowy postprzez Cyfrowy Baron » niedziela, 19 grudnia 2010, 13:24

Sprawdź samemu...


Sprawdziłem. To o czym piszesz jest niemożliwe. Opisana przez Ciebie sytuacja może się zdarzyć tylko wtedy, gdy warunki nie zostaną spełnione lub gdy gdy ListView nie zostanie podpięty pod zdarzenie. Nie jest możliwe by kod najpierw działał, by za chwilę zupełnie bez powodu przestać działać.
Problemem nie jest samo zdarzenie i kod w nim się znajdujący lecz wątki. Podczas wykonywania kodu w wątkach, coś gdzieś się gubi, co jest o tyle prawdopodobne, że podpinasz zdarzenie dynamicznie (Sender->...). Przejrzyj dokładnie kod i sprawdź kiedy i w którym wątku obiekt ListView gubi zdarzenie.

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
Darek_C++
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: TListView gpogubienie zmiana koloru w komórkach

Nowy postprzez Darek_C++ » niedziela, 19 grudnia 2010, 14:28

CB Super : 8-)
Masz rację, że działa tylko nie tak jak ja pierwotnie dałem w wątku, ale dla zdarzenia głównym oknie tam gdzie jest ListViev.

Jeszcze raz dziękuję.
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

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 14 gości

cron