Delphi programozás - Szoftverfejlesztés fórum

üzenetek

hozzászólások


vz12
(tag)

Hello!

> a függvény visszatérése a nevével nem fejezi be a ciklust is?

NEM, az "csak" egy értékadó utasítás, és nem return. Ebből következik, hogy a függvény belül akárhányszor kaphat értéket, az utolsó értékadás a visszatérő érték. A példád szerinti kódban tehát az "utkitt" függvényed visszatérési értéke MINDIG false (!!!)
Egyébként úgy lenne "szép". ha a függvényben egy lokális változót definiálnál a visszatérő érték számára, a függvény értékek menet közben ebbe kerülnének bele. Sokszor érdemes egy kezdeti értéket is adni neki, hogy ne érjen később meglepetés. A függvény legutolsó utasítása pedig az lenne, hogy ennek a lokális változónak a tatalma átkerülne a függvény nevére egy új értékadó utasítással, tehát pl. utkitt := bRet, ahol bRet egy boolean típusú (a függvény visszatérési típusa) lokális változó. Ezt persze nem kötelező így csinálni, működik enélkül is, csak úgy szerintem "szebb", ha a függvény ténylegesen EGYSZER kap értéket.

> Variable identifier expected

Ez pedig azért hibás a te esetedben mert "var" típusúak a függvényed paraméterei (mind a kettő), azaz CÍM szerinti paraméter átadást írtál elő, címe pedig NINCS a híváskor átadott második paraméterednek (starty-magassag*szorzo), csak értéke. A startx oké (mert a változóknak van címe), a starty-magassag*szorzo pedig nem oké. Ha leszeded a "var"-okat a függvény definíciód paramétereiről (amúgy jelen esetben nincs is rá szükség, úgy látom), akkor jó lesz.
A "var" kulcsszót a paramétereknél csak indokolt esetben célszerű használni, vigyázni kell velük.

[ Szerkesztve ]


Tomi_78
(tag)

Szia!
Köszönöm szépen a kifejtést; most már jó lett a program is.
Amúgy úgy tudom, létezik egy "result" utasítás is Pascalban; nem ez lenne a függvényben az értékvisszaadás?


vz12
(tag)

> úgy tudom, létezik egy "result" utasítás is Pascalban

NEM UTASÍTÁS, hanem változó.
Van amelyikben létezik, van amelyikben nem ... A "sima" pascalban tudtommal NEM létezik, a Delphiben létezik.
Ha minél hordozhatóbb ("kompatibilis") kódot szeretnél írni, akkor NE használd a "result" változót, szerintem. Ha Delphin belül maradsz, akkor oké, de érdemes tudni a fenti információt.
Amúgy a "result" egy olyan (lokális) változó, amit a fordító a függvény számára automatikusan deklarál, típusa a függvény visszatérési típusa, lokális változót a függvényekben ezzel a névvel (újra) deklarálni nem lehet, és "össze van drótozva" a függvénnyel, ha az egyik értéket kap, akkor azt a másik is megkapja, oda-vissza.
Mivel változó, ezért értéket akárhányszor kaphat (ez is) a függvényben, ettől még a függvény működése NEM ér véget. Használatával akár "érthetetlen" kódot is lehet íni, nekem nem tetszik.
Azt csinálsz amit gondolsz, de szerintem sokkal tisztább, érthetőbb és hordozhatóbb a kód, ha az általam javasolt SAJÁT lokális változót használod a "result" változó helyett.


Tomi_78
(tag)

Felmerült még pár hiba a programomban:
1. miért ad az alábbi kód a NEM gombra kattintva SIGSEGV osztályú kivételt? Nem a Free-vel kell megsemmisíteni futásidőben a gombokat, paneleket és egyéb dolgokat?
2. a felirathatter-en miért nem látszik a kilépéses felirat?
3. miért van az, hogy az ESCAPE gombra nem reagál a program, mióta beillesztettem ezt a paneles-gombos kilépést? Pedig csak az van az ESCAPE-hez rendelve, hogy Close;.

procedure TForm1.kilepgombkatt(Sender: TObject);
var panelszoveg, igenszoveg, nemszoveg: array [0..1] of string;
begin
panelszoveg[0]:='Biztosan ki akarsz lépni?';
panelszoveg[1]:='Are you sure you want to exit?';
felirathatter:=TPanel.Create(self);
With felirathatter do
begin
Left:=round(Form1.width/2);
top:=round(Form1.height/2);
Caption:=panelszoveg[nyelv];
parent:=self;
end;
igenszoveg[0]:='Igen';
igenszoveg[1]:='Yes';
igengomb:=TButton.Create(self);
With igengomb do
begin
Left:=felirathatter.left+1;
top:=felirathatter.top+TextHeight('I')+1;
Caption:=igenszoveg[nyelv];
parent:=self;
Onclick:=@kilepigenkatt;
end;
nemszoveg[0]:='Nem';
nemszoveg[1]:='No';
nemgomb:=TButton.Create(self);
With nemgomb do
begin
Left:=igengomb.left+igengomb.width+4;
top:=felirathatter.top+TextHeight('I')+1;
Caption:=nemszoveg[nyelv];
parent:=self;
Onclick:=@kilepnemkatt;
end;
felirathatter.width:=igengomb.width+nemgomb.width+10;
felirathatter.height:=igengomb.height+TextHeight('I')+10;
end;

procedure TForm1.kilepigenkatt(Sender: TObject);
begin
close;
end;

procedure TForm1.kilepnemkatt(Sender: TObject);
begin
igengomb.Free;
felirathatter.Free;
nemgomb.Free;
end;


Tomi_78
(tag)

Sziasztok!
Egy Lazarus (FreePascal) programomban úgy kellene méreteznem a főformon lévő két PaintBox méretét, hogy arányosan kövessék a fő form új méretét, akár nagyításról, akár kicsinyítésről van szó.
Amit én csináltam hozzá kód, az hol jól működik, hol eltolja méretileg a PaintBoxokat:
procedure TForm1.FormResize(Sender: TObject);
var ujszel,ujmag: real;
begin
  Kep3d.left:=8;
  Kep3d.top:=8;
  ujszel:=regikep3dszel*(Form1.width/regiform1szel);
  ujmag:=regikep3dmag*(Form1.height/regiform1mag);
  Kep3d.width:=round(ujszel);
Kep3d.height:=round(ujmag);
  //
  Alaprajz.left:=Kep3d.left+Kep3d.width+8;
  Alaprajz.top:=Kep3d.top;
  Alaprajz.width:=Kep3d.width;
  Alaprajz.height:=Kep3d.height;
  //
  regiform1szel:=Form1.width;
  regiform1mag:=Form1.height;
  regikep3dszel:=Kep3d.width;
regikep3dmag:=Kep3d.height;
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
  regiform1szel:=Form1.width;
  regiform1mag:=Form1.height;
  regikep3dszel:=Kep3d.width;
regikep3dmag:=Kep3d.height;
end;

Már napok óta töröm a fejem, hogy mi lehet a baj az arányszámításommal a méretezőkódban, de nem tudok rájönni. Valaki tud segíteni?


Fire/SOUL/CD
(félisten)
Blog

Nem Lazarus, hanem RAD Studio (Delphi), de a lényeg ugyanaz.

unit Unit1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;

type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
procedure FormResize(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormResize(Sender: TObject);

Const
Panel1TopGap = 8;
Panel1BottomGap = 8;
Panel1LeftGap = 8;
Panel2RightGap = 8;
//Panel1 és Panel2 közti távolság
Panel1Panel2Gap = 8;

begin
Panel1.Top:=Panel1TopGap;
Panel2.Top:=Panel1TopGap;
Panel1.Left:=Panel1LeftGap;
Panel1.Width:=(Form1.ClientWidth-(Panel1LeftGap + Panel1Panel2Gap + Panel2RightGap)) div 2;
Panel2.Width:=Panel1.Width;
Panel2.Left:=Panel1LeftGap+Panel1.Width+Panel1Panel2Gap;
Panel1.Height:=Form1.ClientHeight-(Panel1TopGap + Panel1BottomGap);
Panel2.Height:=Panel1.Height;
end;

end.

kép_01 | kép_02 | kép_03


Tomi_78
(tag)

Köszönöm szépen, ilyenre gondoltam, ami a csatolt képeiden látszik is (bár nekem nem pont a főablak felényiek a PaintBoxok).
Most mindjárt átnézem és értelmezem is a kódodat. Még egyszer köszönet érte! :K


Fire/SOUL/CD
(félisten)
Blog

"...(bár nekem nem pont a főablak felényiek a PaintBoxok)..."
Akkor ezt a sort
Panel1.Height:=Form1.ClientHeight-(Panel1TopGap + Panel1BottomGap);

cseréld erre
Panel1.Height:=(Form1.ClientHeight-(Panel1TopGap + Panel1BottomGap)) div 2;


Fire/SOUL/CD
(félisten)
Blog

"...(bár nekem nem pont a főablak felényiek a PaintBoxok)..."
Ahhh, benéztem, vedd tárgytalannak az előző hozzászólást... :W


Tomi_78
(tag)

Próbálom univerzálisabbá tenni a kódodat, hogy bármilyen kiindulási PaintBox méretnél megfelelő legyen a méretezés, de még nem akar összejönni a megoldás. A div 2-nél a 2-t próbáltam lecserélni, de akkor össze-vissza méreteződött.
Nekem egyelőre jó így is, ahogy pont a fele, de azért még gondolkodom.


Fire/SOUL/CD
(félisten)
Blog

1. A div 2 azért van, hogy a 2 objektum (esetedben PaintBox-ok (továbbiakban PB)) egyforma méretűek legyenek, szóval ezt nem kell módosítani.
2. Ha azt szeretnéd, hogy ne pont a Form1.ClientWidth fele legyen a PB-k szélessége (vízszintesen), akkor a Panel2RightGap értékét kell megnövelni, Én most 200-ra tettem (majd alább a képeken látszani fog)
3. A Form1.OnCreate eseményére nincs szükség, mert az OnResize is lefut a progi indításakor, az meg elintézi egyből a méretezést (ez is majd képen látszódik).
4. A 2. pontban leírtaknak akkor van értelme, ha a 2 PB mellett még van(nak) objektum(ok) és azok méretét fixen akarjuk tartani, csak a PB-k méreteződjenek át.
(Itt a példában egy balra igazítot Panel-n elhelyezett 8 gomb marad fix méreten)

IDE-ben így néz ki, a PB-k össze-vissza, méretük sem egyforma
OnResize automatikusan elrendezi a PB-k helyzetét, méretét progi futtatásakor
Vízszintesen méretezve | Függőlegesen méretezve | Mindkét irányban méretezve

Szóval ha esetleg dobnál egy képet a progidról, ahol látom, hogy milyen a Form felépítése (milyen objektumok vannak, hogy néz ki), akkor talán könnyebb lenne segíteni.

[ Szerkesztve ]


Tomi_78
(tag)

Várj csak, kezdem érteni: a Panel2RightGap ugye nálad a jobb oldali panel jobb szélének távolsága a főablak jobb szélétől?
Ez alapján:
procedure TForm1.FormCreate(Sender: TObject);
begin
  oldalsotav:=Form1.ClientWidth-(Alaprajz.left+Alaprajz.width); //Az Alaprajz jobb szegélyének távolsága a főablak jobb szegélyétől.
alsotav:=Form1.ClientHeight-(Kep3d.height+Kep3d.top);
end;  

procedure TForm1.FormResize(Sender: TObject);
begin
  Kep3d.left:=8;
  Kep3d.top:=8;
  Kep3d.width:=(Form1.ClientWidth-(8+8+oldalsotav)) div 2;
  Kep3d.height:=Form1.ClientHeight-(8+alsotav);
  //
  Alaprajz.left:=Kep3d.left+Kep3d.width+8;
  Alaprajz.top:=Kep3d.top;
  Alaprajz.width:=Kep3d.width;
Alaprajz.height:=Kep3d.height;
end;

És akkor így jó is lett az egész, mert ha az oldalsotav változóban az Alaprajz.width-et kisebbre állítom vagy kivonást írok a végéhez, akkor kisebb méretnél is megfelelő arányú lesz az átméretezés.
Nagyszerű; ezt akartam! :DD Még egyszer, ezer köszönet érte neked! :K


Tomi_78
(tag)

Sziasztok!
Azt hiszem, valami nem jól működik ezekkel a ciklusokkal vagy én értelmezem rosszul. Tehát, van egy 2-dimenziós tömböm:
terkep: array [0..7,0..7] of byte=(
  (0,0,0,1,0,0,0,0),
  (0,0,0,1,0,0,0,0),
  (0,0,0,1,0,0,0,0),
  (0,0,1,1,0,0,0,0),
  (0,0,1,0,0,0,0,0),
  (0,0,1,0,0,0,0,0),
  (0,0,1,1,0,0,0,0),
  (0,0,0,1,0,0,0,0)
  );

egy így átméretezett TBitmap-em:
palyakep.SetSize(Form1.width*2,Form1.height*2);
és egy talajképem, ami eredetileg 256*256-os méretű volt, de most:
talajkep.SetSize(palyakep.width div 8,palyakep.height div 8);
Ebből a 2d-s tömbből rajzolnám ki a 0-s helyekre a talajképet, az 1-esekre pedig egy kék négyzetet (mert az egy folyó lenne mondjuk):
for psz:=0 to 7 do
                   for pm:=0 to 7 do
                   begin
                   case terkep[pm,psz] of
                        0: begin
        palyakep.canvas.draw(psz*talajkep.width,pm*talajkep.height,talajkep);

end;
                          1: begin
                                  palyakep.Canvas.Brush.Color:=clBlue;
                                  palyakep.canvas.fillrect(psz*talajkep.width,pm*talajkep.height,psz*talajkep.width+talajkep.width,pm*talajkep.height+talajkep.height);
                                  //palyakep.canvas.textout(iderakx,ideraky,'Sz.: '+inttostr(psz*talajkep.width+talajkep.width)+' M.: '+inttostr(pm*talajkep.height+talajkep.height));
                             end;
                   end;
                   end;
Egyrészt nem értem, hogy a case terkep[pm,psz] of kifejezésben miért kell megcserélnem a pm-et a psz-szel, hogy ne fektetve rajzolja ki a dolgokat, másrészt miért vannak fekete helyközök a talajképek között? Mert ha jól számolom, akkor minden talajképnek szorosan egymás mellett kellene lennie: ha pl. 400 a szélessége, akkor psz=0 esetén 0 X helyre rakódik ki és 400 a szélessége, psz=1 esetén 400*1=400-zal arrébb, és 800-nál van a vége (+400), stb. tehát elvileg mindig egymás mellett. De ha futtatom, akkor az a helyzet, mint a képen:

Miért vannak ezek a fekete foghíjak? Rossz a ciklus? Vagy a mérete rossz a talajképnek?


vz12
(tag)

Hello!

(1) pm-psz csere ("m" a magasság, "sz" a szélesség szeretne lenni (?))
A tömbben az ELSŐ index az a SOR, a grafikán az ELSŐ koordináta az X pozíció, tehát az OSZLOP.
A tömbben a MÁSODIK index az OSZLOP, a grafikán az MÁSODIK koordináta az Y pozíció, tehát az SOR.
Ezért kell felcserélni.
Továbbá, ha "pm"-et és "psz"-t jól értelmeztem fentebb, akkor a 2 db FOR ciklust szerintem fordítva értelmezted, bár a végeredmény szempontjából az mindegy, hogy balról jobbra + felülről lefelé haladva a SORokkal rajzolod ki, vagy felülről lefelé + balról jobbra haladva az OSZLOPokkal rajzolod ki.
>psz=1 esetén 400*1=400-zal arrébb, és 800-nál van a vége (+400), stb. tehát elvileg mindig egymás mellett
Mivel "psz" NÁLAD valójában NEM a "szélesség", hanem a "magasság", ezért a megfogalmazásodban a "mellett"-nek valójában "alatt"-nak kellene hogy legyen.

(2) fekete csík
Úgy látom, hogy a képernyő szélessége NEM egyezik meg a magassággal (szélesebb, mint amilyen magas), de a rajz elvileg mind a kettőt arányosítja (nagyon helyesen). A kiinduló képed 256*256-os ("NÉGYZET" alakú). A SetSize az eredetinél kisebb méretet minden probléma nélkül ki tudja venni a képből (eredeti tartalommal), de mit kezdjen a "hozzátoldással"? Úgy tűnik, hogy a Delphi fekete színnel (=0) bővíti a képet, amennyiben a SetSize paramétere nagyobb az eredeti méretnél. Te pedig VÍZSZINTES irányban bővítetted a képet 256-ról 400-ra, ezért lett a "toldás" fekete színű. Úgy tűnik hogy FÜGGŐLEGESEN belefértél a 256-ba, a képernyő arány miatt, ezért "folytonos" a kép függőlegesen, nem kellett fekete színnel kiegészíteni.
A "SetSize" NEM nyújt, hanem kivág, legalábbis jelen esetben.
ENNYI. :)
Ja, és vettem a fáradságot, arányítottam a "zöld" sáv pixelben vett szélességét a "zöld+fekete" szélességhez, és kerekítéstől eltekintve egészen pontosan kijött a 256/400 arány.

Az nagyon jó, hogy elegendő adatot írtál a problémához, kellett a megoldáshoz. :)

Egyébként miért kellett megszorozni 2-vel a "Form1.width" és a "Form1.height" értékét? Hogy "lelógjon" a képed a képernyőről, vagyis a form-ról?

[ Szerkesztve ]


Tomi_78
(tag)

Szia!

Igen, az m magasságot, az sz szélességet jelent (pályamagasság és pályaszélesség).
Akkor a SetSize csak kisebbíteni tud képet? Ez érdekes...

"arányítottam a "zöld" sáv pixelben vett szélességét a "zöld+fekete" szélességhez, és kerekítéstől eltekintve egészen pontosan kijött a 256/400 arány."

Ezt hogyan csináltad? Azért kérdezem, mert változó pályamérethez kellene majd mindig igazítanom a zöld és kék sáv kiterjedését.

"Egyébként miért kellett megszorozni 2-vel a "Form1.width" és a "Form1.height" értékét? Hogy "lelógjon" a képed a képernyőről, vagyis a form-ról?"

Pontosan. A kép görgethető a nyíl gombokkal a képernyőn. A pályaméretnek ugyanis nagyobbnak kell lennie a felhasználó aktuális képernyőméreténél. Ehhez a pályamérethez kellene igazítanom a zöld és kék sávok értékeit, hogy mindig pontosan kitöltsék.
A mátrix tkp. egy kistérkép, amely nagyban vetül ki a palyakep képre.


vz12
(tag)

Hello!

> Akkor a SetSize csak kisebbíteni tud képet?
Ahogyan írtam is, a "SetSize" nem nyújt sem össze, sem szét, nem vetít, nem projektál. Tehát NEM kicsinyíti/kisebbíti és NEM nagyítja/nagyobbítja a TELJES képet. Tegnap este nem volt és most sincs előttem Delphi, de az általad írtakból + a Google találatokból is azt látom, hogy a "SetSize" a képből VÁG, kimetszi a kép egy RÉSZÉT az eredeti méretben, ha tudja, de működik az eredeti képméretnél nagyobb értékekkel is (nem akad ki a program), csak ilyenkor információ hiányában alapértelmezetten fekete színnel tölti ki a plusz helyet. De működik. Biztosan van valami "stretch" lehetőség, csak be kell állítani, de ezt rád bízom. Egyszínű képeknél ez a nyújtás még nem is okoz problémát, "rendes" képeknél viszont akár nagyon csúnya is lehet az eredmény. Kísérletezgetni, "játszani" kell a dolgokkal, és rá fogsz jönni.

>Ezt hogyan csináltad?
Semmi extra, a képet megnyitottam Paint-ben, ahol az egérmutató (X,Y) pozíciója látszódott a státusz sorban, ebből könnyen kiszámítható volt, itt csak az X érték kellett. Ha jól emlékszem, a zöld sáv szélessége 86 pixel volt, a zöld+fekete sáv szélessége 135, az arányuk 86/135=0.637 (kb.), ami nagyon hasonlít a 256/400=0.64-re, csak a "durvább felbontás" miatt mondjuk kerekítési eltérés tapasztalható.

Megoldás1: a "stretch" lehetőség megtalálása (vagy van, vagy nincs, fejből nem tudom, nekem még nem kellett)
Megoldás2: 256*256-nál (lényegesen) nagyobb kép alkalmazása, hogy nagyobb form-on se jelenjenek meg a fekete sávok (egyébként "alul" is megjelenhetnek, ha olyanok a számok ...)


Tomi_78
(tag)

Huhhh, sikerült megcsinálnom; a StretchDraw utasítás volt hozzá a megfelelő.
Nagyon szépen köszönöm, hogy felvilágosítottál ezekről a dolgokról :K ! Sajnos a leírások nem voltak túl informatívak, amiket a világhálón találtam, úgyhogy hála neked, megint tanultam valamit.
A kód egyébként most így néz ki:
var psz,pm: byte;
  iderakx,ideraky: word;
  talajteglalap: TRect;
terkep: array [0..7,0..7] of byte=(
  (0,0,0,1,0,0,0,0),
  (0,0,0,1,0,0,0,0),
  (0,0,0,1,0,0,0,0),
  (0,0,1,1,0,0,0,0),
  (0,0,1,0,0,0,0,0),
  (0,0,1,0,0,0,0,0),
  (0,0,1,1,0,0,0,0),
  (0,0,0,1,0,0,0,0)
  );
begin
     iderakx:=0;
     ideraky:=0;
     case mostpalya of
          1: begin
               palyakep.SetSize(Form1.width*2,Form1.height*2);
               for psz:=0 to 7 do
                   for pm:=0 to 7 do
                   begin
                   case terkep[pm,psz] of
                          0: begin
                                  talajteglalap:=rect(iderakx,ideraky,iderakx+palyakep.width div 8,ideraky+palyakep.height div 8);
                                  palyakep.canvas.StretchDraw(talajteglalap,talajkep);
                             end;
                          1: begin
                                  palyakep.Canvas.Brush.Color:=clBlue;
                                  palyakep.canvas.fillrect(psz*palyakep.width div 8,pm*palyakep.height div 8,psz*palyakep.width div 8+palyakep.width div 8,pm*palyakep.height div 8+palyakep.height div 8);
                             end;
                     end;
                     if pm<7 then
                        ideraky:=ideraky+palyakep.height div 8
                     else
                     begin
                          ideraky:=0;
                          iderakx:=iderakx+palyakep.width div 8;
                     end;
                   end;


vz12
(tag)

Örülök, hogy hasznát vetted az észrevételeimnek.
Jó szórakozást, jó játékot! :)


Tomi_78
(tag)

Segítség ismét...! Most meg a képpont színének cseréje nem működik valamiért!
Egy cikluson belül szeretném váltogatni a fehér és kék színeket. Ez a kódom hozzá Lazarusban:
if (random(100)=1) and (palyakep.canvas.GetPixel(vsz,vm)=TColor($FF0000)) then
                         palyakep.canvas.SetPixel(vsz,vm,TColor($000000))
                       else
                         palyakep.canvas.SetPixel(vsz,vm,TColor($FF0000));

de nem jó, mert ezeket a hibákat írja ki:
unit1.pas(98,64) Error: identifier idents no member "GetPixel"
unit1.pas(99,42) Error: identifier idents no member "SetPixel"
unit1.pas(101,42) Error: identifier idents no member "SetPixel"

üzenetek