Wartości w checkbox lub listbox

0

Czy można w Delphi wpisać do listboxa lub checkboxa 2 wartości, tzn pierwsza wyświetlała bys się w listboxie lub checkboxie(służyła by tylko do opisu) a drugia była by wartością dla tego opisu. np.

id-wartość
login-wartośc opisowa

wyświetlane login a id było by wartością.

Drugie pytanie czy można się pozbyć pasków przewijania w DBGrid?

0

Do ListBox.Items.Objects[] możesz wstawić co tylko chcesz ale pamiętaj żeby sobie to samemu zwolnić gdy już będzie niepotrzebne.
W przyp. CheckBox można wykorzystać do tego celu Tag lub Hint.

0
  1. metoda Items.AddObject i właściwość Items.Objects + F1/google
  2. można - jest w google
0

aha, czyli spokojnie mogę załadować "select id,opis from xxx" przy ppomocy Items.AddObjects

0

możesz

0

Tak całkiem prosto się nie da, bo zwykły string nie jest obiektem. Musisz sam zadeklarować obiekt zawierający string.

0
pelsta napisał(a)

Tak całkiem prosto się nie da, bo zwykły string nie jest obiektem. Musisz sam zadeklarować obiekt zawierający string.

A tak dokładnie to masz do dyspozycji 4 bajty; Żeby nie tworzyć obiektu możesz bezpośrednio rzutować na TObject i pakować tam np. liczby typu Word, czy DWORD (Cardinal), a po zakończeniu wystarczy zwykły nil; Natomiast dla łańcuchów trzeba referencji do obiektu zawierającego łańcuch, a na koniec zwolnienie obiektu przez Free, choć zwalnianiem powinien zająć się OwnsObject ustawiony na True (standardowo jest na True ustawiany w konstruktorze);

0
furious programming napisał(a):

A tak dokładnie to masz do dyspozycji 4 bajty

A czy przypadkiem w systemach 64botowych pointer nie ma 8 bajtów? :)

0

Nie trzeba sprawdzać - podstawiasz pod wskaźnik wskazanie na obiekt, kompilator powinien załatwić resztę :)

0

A kłania się, kłania, tylko nie mnie. Nie odnosiłem się do wpisywania/przechowywania liczby a do wypowiedzi, że

Tak całkiem prosto się nie da, bo zwykły string nie jest obiektem. Musisz sam zadeklarować obiekt zawierający string.

0

Sprawdzałem kiedyś czy można do TObjectList wpakować bezpośrednio łańcuch, jednak nic z tego nie wyszło pomimo tego, że SizeOf(StringVariable) zwraca 4, a tyle mamy dostępne; Próbowałem wpakować pointer na łańcuch (z rzutowaniem na TObject) i pomimo tego, że wskaźnik także miał rozmiar 4 bajtów to i tak kompilator nie puścił - niezgodność typów;

Jeśli macie jakiś sposób na ominięcie tego to podzielcie się - tak z czystej ciekawości chciałbym wiedzieć;

0

Bezpośrednio - nie wiem jak...

Ja tworzę taką klasę

type
  TString=class(TObject)
    Str:string;
  public
    constructor Create(const s:string);
  end;
//...
constructor TString.Create(const s:string);
begin
   inherited Create;
   Str:=s;
end;
1
type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormClick(Sender: TObject);
  private
    Fsl: TStringList;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  p: PChar;
  s: string;
begin
  p := 'Dupa dupa';
  s := 'Inna dupa';
  Fsl := TStringList.Create;
  Fsl.AddObject('test', TObject(p));
  Fsl.AddObject('test2', TObject(s)); //jednak podanie zamiast zmiennej tekstu tutaj nie przejdzie
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Fsl.Free;
end;

procedure TForm1.FormClick(Sender: TObject);
begin
  ShowMessage(Fsl[0] + #13#10 + PChar(Fsl.Objects[0]));
  ShowMessage(Fsl[1] + #13#10 + string(Fsl.Objects[1]));
end;
0
abrakadaber napisał(a)

ślepy? Przecież string też jest...

Furious Programming napisał(a)

Sprawdzałem kiedyś czy można do TObjectList wpakować bezpośrednio łańcuch, jednak nic z tego nie wyszło pomimo tego, że SizeOf(StringVariable) zwraca 4, a tyle mamy dostępne; Próbowałem wpakować pointer na łańcuch (z rzutowaniem na TObject) i pomimo tego, że wskaźnik także miał rozmiar 4 bajtów to i tak kompilator nie puścił - niezgodność typów;

Ja jestem ślepy...? Czy nie wyraźnie napisałem, że chodzi o włożenie String do TObjectList...?!

0
furious programming napisał(a):

Ja jestem ślepy...? Czy nie wyraźnie napisałem, że chodzi o włożenie String do TObjectList...?!
To sobie zamień TStringList na TObjectList, AddObject na Add a Objects[x] na [x] - takie to trudne?

0

Faktycznie działa, a wcześniej testowałem i w ogóle nie chciało mi skompilować - wspomniana wcześniej niezgodność typów... Gdybym wcześniej nie miał takiego problemu to nie pytałbym o to w ogóle; Zanim zadałem pytanie sprawdziłem i dostałem błąd, teraz o dziwo działa;

Ze zwalnianiem w ten sposób wypełnionej listy jest problem - AV dostaję przy zwalnianiu obiektu; Dopiero OwnsObject na False wyklucza błąd ze zwalnianiem, jednak samemu ręcznie trzeba posprzątać po sobie;

0

ale co ty tam chcesz zwalniać???? Przecież nie tworzysz ŻADNYCH obiektów! Trochę pomyślunku

0
abrakadaber napisał(a)

ale co ty tam chcesz zwalniać????

No dobra, a jeśli wpakuję łańcuch o sporej długości (w każdym razie większej niż 4 bajty) to nie trzeba go wykasować? Jeśli pozostawię OwnsObject na True to dostaję AV (bo pewnie przy Free lista w pętli próbuje wywołać destruktor obiektów na liscie, a łańcuch go nie posiada), jeśli jednak ustawię OwnsObject na False to lista nie zostanie automatycznie zwolniona, stąd pytam; Nie gniewaj się tylko wytłumacz mi to, czego nie wiem/nie jestem pewny;

Ogólnie to chodzi mi o to, czy jak dodam np. jeden element do listy - łańcuch o wadze np. 1kB - i po usunięciu obiektu (bez OwnsObject) czy pamięć po łańcuchu (ten 1kB) zostanie zwolniona; Nie mam narzędzi do MemLeak'ów więc pytam;

0

string (tak jak i tablica dynamiczna) w delphi jest typem specyficznym, który niejako "sam się zwalnia". Nie trzeba go zwalniać.

0

Ale pakuję do listy dane o rozmiarze większym niż wskaźnik, stąd pytam;

ansistring to wskaźnik na tablicę dynamiczną. Więc to ma taki sam rozmiar jak pointer. z kolei shortstring nie przeszedłby, bo to jest sama tablica.

No dobra, a jeśli wpakuję łańcuch o sporej długości (w każdym razie większej niż 4 bajty) to nie trzeba go wykasować?

Trzeba, tylko że zajmie się tym Delphi które po wykryciu że twój łańcuch jest nieużywany zwolni jego pamięć.

lista w pętli próbuje wywołać destruktor obiektów na liscie, a łańcuch go nie posiada

Ściślej, TObjectList usiłuje potraktować tablicę dynamiczną jako TObject.

jeśli jednak ustawię OwnsObject na False to lista nie zostanie automatycznie zwolniona, stąd pytam

Lista zostanie automatycznie zwolniona, jednak nie będzie wywoływany destruktor obiektów które podałeś (bo to nawet nie muszą być obiekty tak jak słusznie zauważył i zrobił @abrakadaber ).

Ogólnie to chodzi mi o to, czy jak dodam np. jeden element do listy - łańcuch o wadze np. 1kB - i po usunięciu obiektu (bez OwnsObject) czy pamięć po łańcuchu (ten 1kB) zostanie zwolniona; Nie mam narzędzi do MemLeak'ów więc pytam;

Nie, nie zostanie zwolnione po usunięciu obiektu (TObjectList?) tylko po tym, gdy referencje stringa spadną do zera, więc najprawdopodobniej po przypisaniu do s pustego stringa. Wobec tego mechanizm ten jest niebezpieczny.

string (tak jak i tablica dynamiczna) w delphi jest typem specyficznym, który niejako "sam się zwalnia". Nie trzeba go zwalniać.

Tak samo jak i obiekt (nie klasa). Nie widzę w tym nic 'specyficznego', po prostu niektórzy nie wiedzą czym się ich język różni od takiego C. Niewiedza szkodzi, co widać dobitnie.

Typ PChar oczywiście przejdzie, ale mi chodziło o wpakowanie zmiennej typu String; To jednak nie zmienia faktu, że rzutowaniem załatwi się sprawę;

Każdy ansistring jest rozszerzonym PCharem.

@furious programming, http://www.freepascal.org/docs-html/ref/refsu10.html coś dla ciebie (to domyślne stringi od Delphi4 bodaj).

Należy jednak zauważyć że takie rozwiązanie wymaga dużego castowania i generalnie bezpieczniej i czytelniej jest zrobić klasę na string. Takie niebezpieczne castowanie zostawmy dla osób które wiedzą jak działa Delphi/FPC, bo widać tutaj to mniejszość.

0

Myślę, że sporo można się dowiedzieć z artykułu http://delphi.clockwork-bits.pl/string.htm. Na przykład o tym co to i gdzie jest licznik referencji :)

Narzędzie do raportowania memleaków jest w Delphi, niestety nie pamiętam od której wersji (2010? Kiedy włączono FastMem do środowiska?)
W kodzie projektu trzeba dać

ReportMemoryLeaksOnExit := True;

0

przecież wystarczy jeżeli zrobisz:

TStr = class TObject
  public
  Str:String;
  constructor Create(const AStr:String);
end;

constructor TStr.Create(const AStr:String);
begin
  inherited;
  Str:=AStr;
end;

Da się dorzucić jeszcze parę dodatkowych metod dla wygody używania.

0
-321oho napisał(a):

Ogólnie to chodzi mi o to, czy jak dodam np. jeden element do listy - łańcuch o wadze np. 1kB - i po usunięciu obiektu (bez OwnsObject) czy pamięć po łańcuchu (ten 1kB) zostanie zwolniona; Nie mam narzędzi do MemLeak'ów więc pytam;

Nie, nie zostanie zwolnione po usunięciu obiektu (TObjectList?) tylko po tym, gdy referencje stringa spadną do zera, więc najprawdopodobniej po przypisaniu do s pustego stringa. Wobec tego mechanizm ten jest niebezpieczny.

string (tak jak i tablica dynamiczna) w delphi jest typem specyficznym, który niejako "sam się zwalnia". Nie trzeba go zwalniać.

Tak samo jak i obiekt (nie klasa). Nie widzę w tym nic 'specyficznego', po prostu niektórzy nie wiedzą czym się ich język różni od takiego C. Niewiedza szkodzi, co widać dobitnie.

string to taka tablica dynamiczna tylko, że możesz np. go porównywać czy kopiować przez przypisanie (przy tablicy przepiszesz jedynie wskaźnik) i co najważniejsze sprząta po nim samo delphi (jak zauważyłeś). I nie ważne czy zmienna ma 2 znaki tekstu czy 2kB tekstu - delphi to sprzątnie.
Natomiast porównanie stringa do obiektu to jest nieporozumienie. Obiekt nie jest specyficznym typem - on jest po prostu obiektem. Typy proste (integer, double, char, ...) to typy proste, wskaźniki to wskaźniki, obiekty to obiekty natomiast string i tablica dynamiczna to specyficzne wymysły delphi i nie ma tego w takiej postaci nigdzie indziej.

@_13th_Dragon tylko, że jak masz 1mln stringów a jak masz 1mln obiektów, które trzymają ten 1mln stringów to jest trochę więcej i pamięci i szybkości w dostępie do danych

0

string to taka tablica dynamiczna tylko, że możesz np. go porównywać czy kopiować przez przypisanie (przy tablicy przepiszesz jedynie wskaźnik)

Operator overloading...

i co najważniejsze sprząta po nim samo delphi (jak zauważyłeś). I nie ważne czy zmienna ma 2 znaki tekstu czy 2kB tekstu - delphi to sprzątnie.

Tak samo jak w tablicy dynamicznej

Natomiast porównanie stringa do obiektu to jest nieporozumienie. Obiekt nie jest specyficznym typem - on jest po prostu obiektem.

A gdzie ja porównuję string do obiektu? Czytanie ze zrozumieniem. Stwierdziłem jedynie że jest referencjowany tak jak obiekt.

@_13th_Dragon tylko, że jak masz 1mln stringów a jak masz 1mln obiektów, które trzymają ten 1mln stringów to jest trochę więcej i pamięci i szybkości w dostępie do danych

Jedna warstwa pośredniczenia + ~10bajtów? Nie przesadzaj, szukasz dziury w całym, tak się tego nie rozwiązuje.

0
abrakadaber napisał(a):

... tylko, że jak masz 1mln stringów a jak masz 1mln obiektów, które trzymają ten 1mln stringów to jest trochę więcej i pamięci i szybkości w dostępie do danych
Nie unikniesz tego przynajmniej w Delphi. Nawet jak zamiast stringa zapodasz PChar zrobisz konstruktor, destruktor, assign, to nadal będziesz mieć 1mln obiektów trzymających wskaźniki do 1mln C-stringów czy jakkolwiek to załatwisz.
Można podpinać wynik GetMem pod Objects[]; ale zwalniać trzeba "ręcznie", zresztą o tym już mówiłem w tym temacie.
To była tylko propozycja jak podpiąć stringa ale zachować automagiczne zwolnienie.

0

Nie unikniesz tego przynajmniej w Delphi. Nawet jak zamiast stringa zapodasz PChar zrobisz konstruktor, destruktor, assign, to nadal będziesz mieć 1mln obiektów trzymających wskaźniki do 1mln C-stringów czy jakkolwiek to załatwisz.

Blablabla. TFPGMap<String,String>;. Rozwiązanie lepsze niż wasze prześmieszne listy używane niezgodnie z przeznaczeniem... No ale cóż, widzę że przebijacie jedno słabe rozwiązanie drugim słabym rozwiązaniem.

właśnie tu: "string (tak jak i tablica dynamiczna) w delphi jest typem specyficznym" ... "Tak samo jak i obiekt"

Cytowałem dokładnie to: "string (tak jak i tablica dynamiczna) w delphi jest typem specyficznym, który niejako "sam się zwalnia". Nie trzeba go zwalniać." - i do tej 'specyficzności' poprzez brak potrzeby zwalniania odnosiło się "tak samo jak i obiekt". No cóż, widać że czytać ze zrozumieniem nie umiesz.

  1. Zapomniałeś napisać ~10bajtów (dokładnie "czysty" TObject to 8 bajtów) na KAŻDY obiekt

Nie zapomniałem, wydawało mi się że to oczywiste w dziale nie-newbie. Ale widzę że to jednak piaskownica?

@abrakadaber , twoje rozwiązanie ma malutki problem.

var
  l:TStringList;
  s:ansistring;

procedure AddSth(l:TStringList);
var
  s:ansistring;
begin
  s:='static';
  l.AddObject('sth',TObject(s));//Oh i'm so smart!
end;

begin
  l:=TStringList.create();
  AddSth(l);
  s:=ansistring(l.Objects[0]);
  writeln(s,#32,length(s));//WTF?
  l.Free;
end.

Proponuję ustawić lokalną zmienną s na coś innego niż const i zobaczyć co się stanie. Gratulujemy, właśnie użyłeś dzikiego wskaźnika. I tak kończy się używanie mechanizmów do których programista w normalnych warunkach dostępu nie ma.

0
-321oho napisał(a):

Nie unikniesz tego przynajmniej w Delphi. Nawet jak zamiast stringa zapodasz PChar zrobisz konstruktor, destruktor, assign, to nadal będziesz mieć 1mln obiektów trzymających wskaźniki do 1mln C-stringów czy jakkolwiek to załatwisz.

Blablabla. TFPGMap<String,String>;.
Fajnie więc do 1 mln wierszy w TStrings dodajesz 1 mln rekordów w których w sumie masz 2 mln stringów plus dodatkowe nakłady. Czytanie ze zrozumieniem się kłania. Przeczytaj jeszcze raz czego dotyczyło - "Nie unikniesz tego przynajmniej w Delphi".

0

Przeczytaj jeszcze raz czego dotyczyło - "Nie unikniesz tego przynajmniej w Delphi".

Bo w Delphi nie ma generyków. Zamień TFPGMap na odpowiednik Delphi i o boshe masz rozwiązanie dla Delphi.

Fajnie więc do 1 mln wierszy w TStrings dodajesz 1 mln rekordów w których w sumie masz 2 mln stringów plus dodatkowe nakłady.

Gdzie ty tu widzisz rekord? Tutaj nie ma żadnego rekordu.
Chcecie zrobić mapę co widać w tym waszym dodawaniu klas które są kontenerami na stringa. Nakłady pamięciowe będą mniejsze. Tak samo jak ilość instrukcji potrzebna do wyłuskania elementu.
Nie wiem jak tobie, ale mi to wygląda na mapę string-string: Fsl.AddObject('test2', TObject(s)); - na dodatek taką która nie działa. Więc ja zyskuję na pamięci, prędkości (względem twoich klas) jak i bezpieczeństwie (bez groźnego rzutowania).

Czytanie ze zrozumieniem się kłania.

Powiedział ten co nie wie czym się różni string od rekordu. Brawo.
Proponuję ogarnąć temat generyków zamiast mi zarzucać mi brak czytania ze zrozumieniem.

0
-321oho napisał(a):

ble ble ble

//WTF?

ble ble

no i gdzie ten WTF?? bo u mnie wyświetla static 6. Powiedzmy sobie może coś żeby to było jasne - ja używam Delphi a nie FP. I czy tam będzie AnsiString czy string czy PChar to po prostu działa. A co do TFPGMap<String,String> Rozwiązanie lepsze niż wasze prześmieszne listy używane niezgodnie z przeznaczeniem... to oczywiście czytałeś pytanie ("Czy można w Delphi wpisać do listboxa lub checkboxa 2 wartości") i oczywiście to jest twoja odpowiedź...

BTW ale oczywiście z tobą nie ma się co kłócić bo ty i tak wiesz lepiej...
dla mnie EOT jak chcesz to możesz dalej przedstawiać swoje teorie na temat zbawienia świata

0
-321oho napisał(a):

Przeczytaj jeszcze raz czego dotyczyło - "Nie unikniesz tego przynajmniej w Delphi".

Bo w Delphi nie ma generyków. Zamień TFPGMap na odpowiednik Delphi i o boshe masz rozwiązanie dla Delphi.

Fajnie więc do 1 mln wierszy w TStrings dodajesz 1 mln rekordów w których w sumie masz 2 mln stringów plus dodatkowe nakłady.

Gdzie ty tu widzisz rekord? Tutaj nie ma żadnego rekordu.

A generyk to wg ciebie magiczny twór nie zajmujący żadnego miejsca w pamięci nie mający wewnątrz siebie żadnego rekordu opisującego parę string => string? Musisz się przespać lub zacząć czytać podstawy programowania.

-321oho napisał(a):

Chcecie zrobić mapę co widać w tym waszym dodawaniu klas które są kontenerami na stringa. Nakłady pamięciowe będą mniejsze. Tak samo jak ilość instrukcji potrzebna do wyłuskania elementu.
Nie wiem jak tobie, ale mi to wygląda na mapę string-string: Fsl.AddObject('test2', TObject(s)); - na dodatek taką która nie działa. Więc ja zyskuję na pamięci, prędkości (względem twoich klas) jak i bezpieczeństwie (bez groźnego rzutowania).

Niby jakim cudem te nakłady będą mniejsze? W generyku musisz co najmniej zdublować oryginalny string z listbox'a. No chyba że nawet nie przeczytałeś tytułu tematu lub nie zrozumiałeś (czytanie ze zrozumieniem się kłania) i myślisz że do listbox'a dodaje się dodatkowy string aby mieć mapę string -> string. Nie wspominając już o tym że w listbox'ie może być "a"->"b", "a"->"c", "a"->"b" zaś w proponowanej mapie nie może być. Owszem widziałem próby stworzenia obiektu TStringList aby mieć mapę string->coś, w takich przypadkach to co napisałeś o mapie generycznej (nakłady pamięciowe i dostępowe) jest jak najbardziej słuszne. Ale ten temat dotyczy czegoś innego.

-321oho napisał(a):

Czytanie ze zrozumieniem się kłania.

Powiedział ten co nie wie czym się różni string od rekordu. Brawo.
Proponuję ogarnąć temat generyków zamiast mi zarzucać mi brak czytania ze zrozumieniem.
Nie ja muszę ogarnąć temat generyków tylko ty musisz ogarnąć jak te generyki się robi. W mapie para string -> string tworzy rekord w którym oprócz tych dwóch stringów w zależności od rozwiązania może być nawet kilka dodatkowych pól, bez tego nie da się stworzyć mapy.

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