Pagina1 van 1
Forum

Welkom bij de Tweaking4All gemeenschapsforums!
Voor je gaat deelnemen, bekijk de Forum Regels!

Specifieke onderwerpen: Start het onderwerp met de naam van het programma of systeem.
Bijvoorbeeld “MacOS X – Jouw vraag“, of bijvoorbeeld “MS Word – Jouw Tip of Truc“.

Merk op: Omschakelen naar een andere taal zal niet werken als je een post aan het lezen bent aangezien er waarschijnlijk geen vertaling beschikbaar is.



Deel:
Meldingen
Alles wissen

[Opgelost] Vraag door oude Pascaller

137 Berichten
2 Gebruikers
0 Reactions
17.5 K Bekeken
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 12 jaar geleden
Berichten: 2864
 

Voor wat betreft de vele units and forms heb ik geloof ik boven al een goede oplossing gegeven.
In dat geval heb je slecht 1 unit ... en 1 form. 

De Application.Run procedure zul je in Lazarus (of Delphi) nooit gebruiken.

In principe start jouw applicatie met een venster met de eerste vragen of een welkomst bericht (dit kan dus ook een tabblad zijn!).
De gebruiker krijgt vervolgens op ieder tabblad een "verder" knop te zien die dan de volgen tab zichtbaar maakt, en een "begin opnieuw" knop die meteen terug springt naar de eerste tab.

Ik snap de verwarring helemaal! 
Haha, ik zal eerlijk toegeven dat ik tegenwoordig nog weleens een andere programmeer taal wil proberen, maar binnen enkele minuten ben ik het al zat omdat het soms best wel moeite kost om "om te schakelen", terwijl ik daar vroeger helemaal geen moeite mee had.

In principe moet je Turbo Pascal methoden enzo los laten en alleen maar onthouden hoe basis Pascal werkt, oh en natuurlijk wennen aan de automatische code die gegenereerd wordt. Maar daar was ik zelf al snel aan gewend. Initieel was het wel lastig om te ontdekken hoe het e.e.a. nu door het programma loopt. Waar je bij Turbo Pascal sequentieel werkt, werk je bij Delphi en Lazarus alleen binnen een procedure sequentieel en de rest object georiënteerd.

Als verwarrend voorbeeld: stel je hebt twee knoppen op een form, en stel dat het mogelijk zou zijn om alle twee de knoppen op precies hetzelfde moment aan te klikken, dan draaien er in jouw programma twee procedures tegelijk! Dit heeft met object georiënteerd werken en events te maken.
Maar daar zou ik me nog niet zo druk over maken, ... 2 knoppen tegelijk aan klikken is best een kunst ...

Later, als je zeer complexere programma's begint te maken, dan kan het wel van belang zijn dat je dit weet. Maar zo te horen is jouw programma niet zo complex. De programma's die ik hier op Tweaking4All aanbiedt zijn overigens allemaal met Lazarus geschreven, en slechts 1 daarvan is behoorlijk complex waarbij dat soort zaken wel voorkomen.


   
BeantwoordenCiteren
(@hengst)
Trusted Member
Deelgenomen: 10 jaar geleden
Berichten: 83
Topic starter  

Hoi Hans,

Toch weer een paar vraagjes.

Wat zou jij gebruiken om de op de ene plaats opgehaalde info op een ander tabblad weer te geven.
Tot nu toe lukt me dat alleen op op de andere plaats erop geclikt wordt. Ik wil het eigenlijk middels:

in Edit2.Text ophalen
VARX:=Edit2.txt

op ander tabbad VARX weergeven.

Daarnaast worden er vele lege procedures aangemaakt. Toen ik er een paar weghaalde kreeg ik fout meldingen.
Wat doe ik fout?

Dank 


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 12 jaar geleden
Berichten: 2864
 

De waarde van Edit.Text op tabsheet1 kan gewoon worden gelezen als je tabsheet2 zichtbaar hebt.
Dus je zou ze niet over te hoeven zetten ... 

Dus stel dat je door Button2 te klikken die op tabsheet2 staat, de waarde van Edit1.Text (die op tabsheet1 staat) wilt gebruiken dan kan dat gewoon.
Dus als een Edit2 op TabSheet2 staat, en die moet dan de dezelfde inhoud krijgen als Edit1 or TabSheet1 dan kun je bij de "OnShow" event van TabSheet2 zoiets zetten als:
Edit2.Text := Edit1.Text;
Als je een procedure weg haalt, dan moet je bovenin ook de declaratie weghalen. Bij het compileren zal Lazarus dan melden dat de declaratie en procedure niet meet bestaan en of hij die dus weg mag halen (omdat ze in sommige properties nog wel vermeld staan).
(Sorry voor het korte antwoord, ik probeer jouw vraag even tussen door te beantwoorden - maar blijf vooral vragen!)

   
BeantwoordenCiteren
(@hengst)
Trusted Member
Deelgenomen: 10 jaar geleden
Berichten: 83
Topic starter  

Hoi Hans,

Wat ik wil is toch iets anders. Over 2 tabs verzamelt het programma informatie en moet dat controleren, aanvullen en wegschrijven.
Voorbeeld BSN. Dat moet voldoen aan een 9-proef, nummer zijn een aangevuld worden met nullen.
Dus na invoer wordt het overgezet in B0203 (wat een array[1..12] of char is. Dus het is anders dan de gebruiker heeft ingetikt.

Op de derde tab wordt alle essentiële informatie getoond en bestaat de knop verzenden. Dan worden de var, zoals B0203, in verzend file geschreven. (Hiertoe wordt een EDI bestand gemaakt, een word doc, een bijschrijving in een DB en een gedeelte in de starters file). Al deze data in vooraf bepaald en strak gedefineerd qua lengte soort en grote.

Dus als ik op tab1 in de procedure heb bepaald B0203:=bewerk(Edit1.Text).
Op tab3 wil ik B0203 weergeven direct als de gebruiker naar tab3 gaat. Dus zonder dat de gebruiker ergens anders op behoeft te klikken. Dan kan ik standaard een tekst laten verschijnen "nog in te vullen".

Maakt dit mijn vraag wat duidelijker?

Dank Gerard


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 12 jaar geleden
Berichten: 2864
 

Misschien is het handiger om een string type te gebruiken ipv een array of char. Maar dat is maar een gedachte, maakt misschien niet al te veel uit ... 

Dus als ik het goed begrijp wordt BSN in B0203 opgeslagen in een ander formaat als wat we in Edit1.Text vinden.
Die berekening kun je dus doen als de knop geklikt wordt om naar de volgende tabsheet te gaan, met B0203 als globale variable.

Vervolgens, als ik het goed begrijp, willen we BSN zoals ingevoerd op TabSheet3 tonen, maar B0203 naar het bestand schrijven.

Ik weet niet of je labels gebruikt, maar je zou dan op de overzicht tabsheet kunnen zeggen:

Label1.Caption := Edit1.Text;

Je zou ook met een globale boolean er bij kunnen werken:

BSN9proef := TRUE;

Of je zou kunnen voorkomen dat naar een ander tabsheet gesprongen wordt als bepaalde condities niet gehaald worden:

OnClick (vd knop om naar de volgende tabsheet te gaan):

// condities o.a. de 9-proef?
if <condities> then
  begin
    ....
    PageControl1.ActivePage := TabSheet1;
  end;

Dus alleen tabsheet wisselen als de condities waar zijn ...

Of heb ik het net goed begrepen? 


   
BeantwoordenCiteren
(@hengst)
Trusted Member
Deelgenomen: 10 jaar geleden
Berichten: 83
Topic starter  

Nog niet helemaal Hans,

De wisseling van tabs gaat goed. De vullen van de variabele gaat ook goed. En de verzamelde data gaat eveneens goed. Array of char verplicht voor overheidsfile, strings te gevaarlijk voor overschrijding lengte. Dat gaat ook goed.

Het enige dat ik niet voor elkaar krijg is dat data op tab1 op tab3 getoond wordt zonder dat de gebruik iets hoeft te doen.

Nog steeds het voorbeeld BSN in B0203 op tab1 gevuld en gecontroleerd. Dit wil ik vanuit B0203 weergeven op tab3 zodra op tab1 de data correct is bevonden en anders moet op tab3 komen te staan "nog in te vullen". In oude pascal zou ik gewoon een writeln(B0203) doen.

Hopelijk begrijp je me nu.

Gerard


   
BeantwoordenCiteren
(@hengst)
Trusted Member
Deelgenomen: 10 jaar geleden
Berichten: 83
Topic starter  

Hoi hans,

Dank voor de hulp. Het is me gelukt. Nu nog alle veldjes verder maken e.d., maar de structuur werkt.

Zie bijgaande exe voor hetgeen ik nu ben gekomen.

Moet nog wel schonen en kleiner maken.

Groetjes Gerard


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 12 jaar geleden
Berichten: 2864
 

Nou dat ziet er goed uit - al behoorlijk wat werk! 

Resize Window

Nu is het misschien tijd om je wat te vertellen over het resizen van een window.

Je zult gemerkt hebben dat het venster groter en kleiner gemaakt kan worden en dat is soms ongewenst.
Je kunt het uitzetten door de property "BorderStyle" van Form1 op "bsSingle" te zetten.

Een andere methode, als een beetje resizen wel wilt toestaan, is door van Form1 de properties onder "Constraints" in te vullen (Min/Max hoogte en breedte). Hierdoor voorkom je, als een beetje resizen toegestaan is, dat het venster te groot of the klein wordt.

Bij het resize komt natuurlijk een potentieel probleem. Soms wil je een component "vast" zetten zodat het meebeweegt en/of van omvang veranderd als je een form resized. Zo kan het wenselijk zijn dat de TPageControl netjes mee gaat met het verkleinen of vergroten.

Hiervoor gebruiken we de property (van visuele componenten) "Anchors".

Bij een anchor kun je b.v. alles op true zetten. Als dan een form groter wordt dan zie je de breedte en hoogte mee veranderen.
Als je nu LEFT en TOP of FALSE zet, dan zie je dat een component zich vast zet tegen de rechterkant en de onderkant en niet in grootte veranderd maar mee beweegt.

Overigens heeft Lazarus een zeer geavanceerde Anchor tool die het ook nog eens mogelijk maakt om componenten aan elkaar te koppelen zodat ze van elkaar afhankelijk gaan zijn - maar dat is iets voor veel later.

Ook handig is de zogenaamde "Borderspacing" waarmee je ruimte binnen en buiten bepaalde componenten op een vaste waar kunt zetten - handig bij het plaatsen van componenten in dat component en goed voor een consistent beeld.

Velden met tekst

Als ik naar jouw velden kijk dan zie ik b.v. een datum veld waar als voorbeeld tekst "Eerste" staat.
Uiteraard niet een goede waarde, en slechts een indicatie voor de gebruiker.

Wat je zou kunnen doen, is in het OnChange event (of misschien beter ook nog eens bij het OnKeyUp event) zoiets te plaatsen:

if Edtit.Text='Eerste' then
  Edit.Font.Color := clSilver
else
  Edit.Font.Color := clBlack;

Waardoor de font kleur veranderd als de gebruiker hier iets gaat invoeren.

Uiteraard is het leuker om de tekst "Eerste" meteen te verwijderen als de gebruiker het veld in gaat.
Doe dat door b.v. in het OnEnter event dit te doen:

if Edit.Text='Eerste' then Edit.Text:='';

En weer terug zetten als de gebruiker niets heeft gedaan, door in het onExit event:

if Edit1.Text='' then Edit1.text:='Eerste';

Ik adviseer hier eens mee te spelen, vooral in een nieuw project, zodat als het fout gaat, je niet al je werkt in de knoei helpt ... 


   
BeantwoordenCiteren
(@hengst)
Trusted Member
Deelgenomen: 10 jaar geleden
Berichten: 83
Topic starter  

Leuk Hans,

heb direct ingevoerd en gaat goed.

Bestaat er ook iets om TEdit velden te laten verschijnen en verdwijnen bij het aanklikken van bepaalde keuzes uit TCheckGroup?

Zou het programma iets verbeteren.


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 12 jaar geleden
Berichten: 2864
 

Leuk om te horen dat je er wat aan hebt, ik vind het zelf ook erg leuk om uit te leggen ...   

Een TEdit (of welk visueel component) kun je verbergen door de property "Visible" of FALSE te zetten. Dit kan via de Object Inspector.

Maar het kan ook in code:

Edit1.Visible:=FALSE;  // Edit1.Hide; doet hetzelfde

of natuurlijk

Edit1.Visible:=TRUE;  //  Edit1.Show; doet hetzelfde

Uiteraard kun je het in een OnClick event hangen van een tButton, of OnChange bij een TCheckBox.
B.v. optie aanvinken van een checkbox zorgt ervoor dat de Edit1 zichtbaar wordt:

Edit1.Visible := Checkbox1.Checked;

Je kunt deze properties ook gebruiken om te testen of een component zichtbaar is:

if Edit1.Visible=true then ...


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 12 jaar geleden
Berichten: 2864
 

Las ik even helemaal over de TCheckGroup heen ... ik gebruik die zelden overigens ... maar daar gaat dat natuurlijk ook mee:

procedure TForm1.CheckGroup1ItemClick(Sender: TObject; Index: integer);
begin
  Edit1.Visible:=CheckGroup1.Checked[1]; // je kunt hier natuurlijk ook de waarde "Index" gebruiken
end; 
(Er vanuit gaande dat de tweede [1] checkbox in de checkgroup de gewenste checkbox is natuurlijk)

Omdat we in design time nog weleens lopen te rommelen met de Object Inspector, zet ik soms het e.e.a. in het OnCreate event van de Form, om er zeker van te zijn dat alles goed staat als het programma start.
Nu kun je daarbij de betreffende procedure (zoals die hierboven) vanuit het Form1 OnCreate event gewoon aanroepen, b.v.
procedure TForm1.FormCreate(Sender: TObject);
begin
  CheckGroup1ItemClick(nil,0);
end;    
Merk op dat ik als Sender de waarde nil geef, maar dat mag ook de Sender van dit event zijn natuurlijk.
Ik gebruik altijd expliciet nil, tenzij het belangrijk is voor de procedure dat de juiste Sender bekend wordt gemaakt.
De 0 (nul) die ik hier meestuur is alleen maar om een waarde door te geven, en nul zou altijd moeten bestaan. Hoop ik. 
Mocht je echter de "Index" waarde gebruiken (meer correct) dan moet je de procedure natuurlijk voor elke checkbox aanroepen, dus b.v.
  CheckGroup1ItemClick(nil,0);
  CheckGroup1ItemClick(nil,1);
  CheckGroup1ItemClick(nil,2);

   
BeantwoordenCiteren
(@hengst)
Trusted Member
Deelgenomen: 10 jaar geleden
Berichten: 83
Topic starter  

Dat lukt. Althans zo ziet het er nu uit.

Nog een voor de TCheckGroup, was dat aan het proberen maar lukt ook niet.

Als je één vakje aanklikt dat de andere niet meer klikbaar worden. Zonder dat er nog maar iets anders gebeurt.


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 12 jaar geleden
Berichten: 2864
 

Ik weet niet zeker of ik je goed begrepen heb.

De TCheckGroup staat het toe om geen, 1 of meer van de checkboxen aan te vinden.
Als je slechts 1 keuze wilt toelaten dan heb je een TRadioBox nodig.

Of is dit niet wat je bedoelde?


   
BeantwoordenCiteren
(@hengst)
Trusted Member
Deelgenomen: 10 jaar geleden
Berichten: 83
Topic starter  

He Hans,

Het meeste gaat en het programma verfraaid zich aardig. Dank voor ju hulp.

Weet je ook de methode om een TLabel veld default op grijs te zetten en bij vullen (vanuit ergens anders dus zonder click) het zwart te laten worden.


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 12 jaar geleden
Berichten: 2864
 

Graag gedaan en leuk om te horen!

Het veranderen van de tekst kleur in een TLabel gaat programmatisch als volgt:

Label1.Font.Color := clGray; // voor grijs, of b.v. clBlack voor zwart

De achtergrond veranderen gaat via de Color property, maar ik denk niet dat dit is wat je bedoelt:

Label1.Color := clYellow;

Om dit te veranderen na invoer van iets, dan is het een kwestie van een event gebruiken en dan de label font van kleur te veranderen. B.v. in het onExit even van een Edit box, het OnClick event van een button, of b.v. in een "controle" procedure die je eventueel gebruikt.


   
BeantwoordenCiteren
Pagina 2 / 10
Deel: