Prosty program nie działa

0

Witam, mam prosty program mający wykonać prostą animację zmniejszenia rozmiaru tak dla picu, tylko dlaczego ten program się nawet nie uruchamia? Proces jest, ok 1000K tylko zajmuje ale nic poza tym, nie wyświetla się.

Unit Tetrys;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
	
  private
    { Private declarations }
  public
      procedure Start;
	  procedure FPS;
  end;

var
  Form1: TForm1;

implementation


{$R *.dfm}


procedure TForm1.Start;
begin
	sleep(1000);
	FPS;
end;

procedure TForm1.FPS;
begin
	
	if (Width <> 1280) and (Width>2) then
		Width := Width-1;




	Start;
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
  Start;
end;

end.
0

Spróbuj dodać Application.ProcessMessages do FPS bądź Start
(btw, ale wiesz, że ten kod to nieskończona pętla, tak?).

0

Spróbuj dodać Application.ProcessMessages do FPS bądź Start

Oczywiście to co kolega napisał jest bez sensu bo podczas Create forma nie jest wyświetlana. Trzeba przenieść cały proces do timera albo innego zdarzenia oraz zmienić rekurencję na metodę iteracyjną (w czasie wszystkiego wywoływać paint).

0

Sorka nie specjalnie rozumiem. Wiem że to pętla nieskończona, o to chodzi, żeby mi się generowały FPSy, jak w przykładowych grach. W konsoli wystarczyłoby samo while i delay/sleep. Dodanie Application.ProcessMessages; na początku Startu / FPS nic nie dało)

0

Uruchom proces w innym zdarzeniu np po kliknięciu przycisku, a nie w Form Create. Bo to co jest w tym zdarzeniu robi się jeszcze przed "ukazaniem się" okienka czyli nigdy nic nie zobaczysz.

0

Hmm no ok, mam buttonem. Ale teraz mam taki problem że program się zapętla niekontrolowanie, tzn po prostu nie mogę na nim operować. Jest jakiś inny sposób generowania FPS?. Drugim problemem jest brak możliwości uruchamiania programu exekiem, nie reaguje, natomiast jak dam w Borlandzie Run, to uruchamia. Byćmoże 2 problem wynika z pierwszego ale jak rozwiązać pierwszy?

0

Ale teraz mam taki problem że program się zapętla niekontrolowanie, tzn po prostu nie mogę na nim operować.

Skoro cały czas działa jedna pętla to program ją wykonuje a wszystkie komunikaty o wciskanych klawiszach czy ruchu myszy wpierdziela do kolejki, która zostanie wykonana dopiero po skończeniu ww pętli; No ale Twoja się nie kończy więc nie zostaną wykonane; Jeżeli kilka rzeczy musisz zrobić w jednym czasie (tzn. aby działały równorzędnie) skorzystaj z wątków bo po to je wymyślili; Albo pobaw się z wątkami, albo kombinuj z Application.ProcessMessages, który nie zawiesi okna aplikacji, choć nie wiem czy to pomoże; Lepiej skorzystać z wątków; Chyba, że nie ma możliwości sprzężenia go z pętlą to już inna sprawa...

0

To już chyba advanced delphi. Ja potrzebuję jakiegoś prostego rozwiązania, to tylko projekt na informatykę, zwykły wąż. Można to chyba rozwiązać w sposób podobny jak w konsoli.

0

Można to chyba rozwiązać w sposób podobny jak w konsoli.

Zależy co robisz w tej konsoli; Wątki nie są wcale takie trudne jak to się wydaje; A możliwości mają większe niż wstrzymywanie pracy programu;

Ja kiedyś jak jeszcze do TI chodziłem napisałem taki programik do oczekiwania na wciśnięty klawisz; Odliczanie z paskiem postępu (wszystko w konsoli); Podobnie do odliczania po zainstalowaniu windozy; Oczekuje np. 15 sekund - jeżeli się wciśnie klawisz to zostaje coś wykonane, w przeciwnym razie program sam po odliczanym czasie coś tam wykonywał, sam już nie wiem co (ale to tylko test był); Wszystko było oparte na procedurze KeyPressed i pętli oraz Delay na sekundę; Tak samo można to wykorzystać w programowaniu węża, tyle że należałoby sprawdzić jaki klawisz został wciśnięty (także z tym, który wstrzymuję grę i pokazuje menu gry); No ale to był Turbo Pascal w wersji 7, a nie delphi...

Nie wiem co chcesz osiągnąć w delphi, ale można także skorzystać z timera, który będzie odpowiednio rozpoznawał wciśnięty klawisz i na niego reagował; Nie zawiesi Ci programu, a będzie można odpowiednio ustawić interwał timera tak, by podczas wciskania klawisza nie opóźniał jego rozpoznania i reakcji; Chyba prostsze rozwiązanie dla Ciebie skoro chcesz tylko zakuć, zdać, zapomnieć...

0

Nie nie, ja jestem na infie na studiach, nic nie chcę zapominać ;] Tylko mam raptem tydzień czasu wolnego na napisanie tego. Myślałem że w Delphi mogę tak samo zrobić jak napisałeś ale widzę że to tak nie działa nie wiedzieć czemu. Czyli mogę tymi wątkami zrobić ten timer tak?

1

Tylko mam raptem tydzień czasu wolnego na napisanie tego.

No to czas najwyższy spiąć pośladki i napierdzielać kod i czytać różne różności; Po to ludzie wymyślili Internet żeby z niego korzystać;

Myślałem że w Delphi mogę tak samo zrobić jak napisałeś ale widzę że to tak nie działa nie wiedzieć czemu.

A czy stoi coś na przeszkodzie żebyś ten program zrobił w konsoli? Czy musi być w aplikacji okienkowej?

Jeżeli to musi być program z okienkiem to skorzystaj z TTimer, bo możesz to szybko załapać (masz mało czasu więc sprężaj się); Klasa ta nie jest trudna do opanowania i wystarczy napisać dobry jeden programik testowy żeby poznać jego możliwości i wykorzystać w swoim programie;

Czyli mogę tymi wątkami zrobić ten timer tak?

Widzę, że dalej nie zajżałeś ani do dokumentacji klasy TTimer, ani nie poczytałeś o wątkach... Jeżeli chcesz to oprzeć na wątku, to nie musisz sprawy komplikować jeszcze dodając TTimer; Albo rybki, albo akwarium - wątki albo TTimer;

Opanowanie TTimer zajmie o wiele mniej czasu niż wątki, więc z nich skorzystaj; Ustaw Interval na tyle milisekund, co ile potrzebujesz sprawdzić stan wciśniętych klawiszy, a w zdarzeniu OnTimer oprogramuj wciśnięte przyciski na klawiaturze;

Jak jesteś ambitny to w zdarzeniu formularza OnKeyDown możesz tworzyć mini stos przechowujący kolejkę wciskanych klawiszy, a w OnTimer będziesz odczytywał klawisze z tego stosu i je usuwał po ich obsłudze; Może wystąpić problem ze synchwonizacją tych zdarzeń, ale spróbuj to najpierw oprogramować a później wyciąg wniski czy się opłaca czy nie; Jak nie spróbujesz to się nie dowiesz;

0

Zamiast to do wątku wrzucić, to nie, bo po co?

0

Zamiast to do wątku wrzucić, to nie, bo po co?

Jeżeli tobie się wydaje że taki sobie autor wątku w dziale Newbie umie napisać sobie Threada to jesteś conajmniej w błędzie ;-]

0

Sorka nie miałem wczoraj czasu, wigilia, sprzątanie, choinka itd. więc faktycznie nie zajrzałem, ale dziś obadam TTimer. Dzięki bardzo, dam znać jak coś.

0
krwq napisał(a)

a po co kod wykonujący raz na sekundę kilka operacji wrzucać do wątku?

Racja, wątki odpadają ale głównie dlatego, że to wyższa szkoła jazdy i trzeba trochę czasu na nie poświęcić; Raczej więcej niż kilka dni;

krwq napisał(a)

kod wykonujący raz na sekundę

Ja bym tego co sekundę nie robił; Nawet, gdyby ilość klatek na sekundę wynosiła 1 to i tak pasowało by Timer.Interval ustawić na np. 250 ms i sprawdzać stan klawiszy, a co np. 1 s wykonywać określony kod;

Można to tak zrobić, można inaczej; Zależy wszystko od tego w jaki sposób autor to sobie zaplanował; W każdym razie to co napisałem wyżej zdało by egzamin przy kodowaniu klawiszy w grze Tetris, gdzie co jakiś czas opuszczany jest klocek, ale klawisze sprawdzane są częściej; Inaczej na każdy ruch klocka o jedną jednostkę można by tylko o jeden przesunąć klocek;

Trzeba więcej informacji na temat tej gry żeby można było dokładniej powiedzieć co i jak będzie wyglądać;

0

Już sobie poradziłem, bawię się timerami, kluczowy okazał się event onTimer w którym muszę zawrzeć cały program. I tu pojawia się problem. Jak w tej procedurze obsłużyć klawisze? Wiem że jest procedura OnKeyPress, OnKeyDown itd. ale wtedy w nich muszę zawierać kod który się wykona po wciśnięciu klawisza. Nie wiem czy np taki readkey to dobre rozwiązanie. Ale nic innego mi nie przychodzi do głowy... chyba że dałoby sie zrobić coś takiego

procedure onTimerblah(Sender: TObject);
begin
    if onKeyPressed(tu jakis przycisk) then instrukcja;
end;
1

Wiem że jest procedura OnKeyPress, OnKeyDown itd. ale wtedy w nich muszę zawierać kod który się wykona po wciśnięciu klawisza.

To nie jest procedura, tylko zdarzenie. I możesz w niej zawrzeć kod który zapisze gdzieś że ostatni klawisz to jest taki, a potem w timerze sobie sprawdzisz jaki był ostatni klawisz.

chyba że dałoby sie zrobić coś takiego

Tak się bezpośrednio nie da, ale z tą dodatką warstwą co wspomniałem da się.

1
Oho napisał(a)

To nie jest procedura, tylko zdarzenie.

Zdarzenie to jak najbardziej procedura; A czy na samochód nie mówisz "auto"? Na pewno tak, bo to to samo;

MateuszS napisał(a)

kluczowy okazał się event onTimer

To jedyne zdarzenie, jakie posiada ta klasa... :P

MateuszS napisał(a)

Jak w tej procedurze obsłużyć klawisze?

Napisałem Ci wcześniej jak to musisz zrobić; W zdarzeniu ((OnKeyDown and OnKeyUp) or OnKeyPress) musisz zapisać kod klawisza np. do prywatnej zmiennej w klasie okna, a w zdarzeniu OnTimer sprawdzić, czy zmienna przechowuje jakiś kod klawisza czy np. 0; Jak posiada wartość klawisza to rozpoznajesz go i odpowiednio reagujesz, po czym zmienną zerujesz (czyli potocznie usuwasz zapisany klawisz); Jeżeli nie wciśnięto przycisku (czyli zmienna ustawiona jest na 0) wykonujesz to, co ma się dziać jeżeli się nic nie wcisnęło;

Poniżej poglądowy kod (może zawierać błędy bo piszę z pamięci - można powiedzieć, że na pałę...):

TMainForm = class(TForm)
private
  {...}
  wKey: Word;
  {...}
public
  {...}
end;

{...}

procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key in [{obsługiwane klawisze}] then
    wKey := Key;
end;

{...}

procedure TMainForm.tmGameTimer(Sender: TObject);
begin
  if wKey <> 0 ten
    begin
      case wKey of
        {rozpoznanie wciśniętego klawisza i jego obsługa}
      end;

      wKey := 0;
    end
  else
    {kod, który ma się wykonać jak nic nie wciśnięto};
end;

I to cała filozofia; Może czegoś brakować, ale piszę z głowy więc...

EDIT: Cholera, znowu się spóźniłem... :P

0

Dokładnie tak samo zrobiłem ;]

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
    LastPressedButton := Key;
end;

I potem to obrabiałem sobie tzn. próbowałem.

A nawet chciałem dać ShowMessage(Key) w powyższej procedurze jednak... nic się nie dzieje w obu przypadkach, tak jakby ta procedura nic nie robiła, nie przechwytuje klawiszy. Trzeba załączyć jakieś biblioteki dodatkowe?

1

Właściwość formy: KeyPreview na True.

0

Zdarzenie to jak najbardziej procedura; A czy na samochód nie mówisz "auto"? Na pewno tak, bo to to samo;

Nie, zdarzenie to nie procedura. Nie każda procedura jest zdarzeniem, każde zdarzenie to procedura. A ja lubię być dokładnym :-] . Więc każde auto to samochód i vice versa ale tak samo z procedurą i zdarzeniem nie jest :-] . A jakby się uprzeć to zdarzenie jest pointerem na procedurę, a nie procedurą. Tutaj już jak kto lubi. W każdym razie poprawniej jest to nazwać zdarzeniem.

To jedyne zdarzenie, jakie posiada ta klasa...

Nie zgodzę się. Są jeszcze OnStartTimer i OnStopTimer... (Przynajmniej pod Lazarusem) Wiem, czepiam się :-]

EDIT: Cholera, znowu się spóźniłem...

Chociaż nie byłeś tak zdawkowy jak ja to zazwyczaj bywam ;) .

A żeby nie było że mój post jest o niczym, to opowiem po co KeyPreview - powoduje on że klawisze zamiast lądować w akurat wybranej kontrolce (TEdit itd) będą najpierw filtrowane przez zdarzenia TForm. Często się przydaje.

0

@oho, Ty to cholera jesteś :P

Napisałem, że zdarzenie jest procedurą i tak jest w każdym przypadku, także nie napisałem, że każda procedura jest zdarzeniem; Celowo to napisałem, bo nie ma zdarzenia, które jest funkcją;

Oho napisał(a)

Nie zgodzę się. Są jeszcze OnStartTimer i OnStopTimer...

Racja, ale zakładam, że autor ma Windows, a pod nim jest tylko OnTimer;

Zbyt się zakręciliśmy, coraz mniej sensu jest w kolejnych postach...

Oho napisał(a)

KeyPreview - powoduje on że klawisze zamiast lądować w akurat wybranej kontrolce (TEdit itd) będą najpierw filtrowane przez zdarzenia TForm.

Racja, jeżeli filtruje się klawisze w zdarzeniu ( :P ) OnKeyDown, to bez znaczenia jest wartość tej właściwości; Ważne jest to, który obiekt sprawdzamy pod kątem wciskanych klawiszy;

0

Racja, ale zakładam, że autor ma Windows

Też mam windows i mam jakoś OnTimerStart itd. ; czuję się wyalienowany :P
No chyba że Lazarus to nowy OS. ;-]

Zbyt się zakręciliśmy, coraz mniej sensu jest w kolejnych postach...

eheh

Szarp napisał(a)

"zdarzenie to nie procedura", "każde zdarzenie to procedura" - to jak to w końcu jest? :P

Zdarzenie=class(procedura); Tłumacząc na obiektowość...

Racja, jeżeli filtruje się klawisze w zdarzeniu OnKeyDown, to bez znaczenia jest wartość tej właściwości; Ważne jest to, który obiekt sprawdzamy pod kątem wciskanych klawiszy;

Nie rozumiem ale chyba o to chodzi :D

Dobra, starczy tych rozważań chyba :P

0

Hey hey to znowu ja ;] Dzięki wszystkim za dotychczasową pomoc. Mam teraz małą zagwozdkę. Jak wiecie, dodając np. buttony do forma, mamy coś takiego Button1, Button2 itd. Ja chcę to jakoś sobie uprościć żeby potem jakbym chciał np. każdemu buttonowi nadać ten sam Caption móc to zrobić w pętli, czyli śmierdzi tu tablicą. Tylko nie wiem jaki to typ tablicy, tablica obiektów? Jak takie coś utworzyć w Delphi i czy w ogóle się da? Interesuje mnie taki zapis

tab[1] := Button1;
tab[2] := Button2;

{i potem}
tab[1].Caption := 'sratata';

Da się tak?

1

Da się tak?

Tak

var tab:array[1..2] of TButton; Kod co dałeś powinien z tym działać. Ew. daj errory to wyperswadujemy to kompilatorowi.

1

A próbowałeś? Możesz sobie w macierzy przechowywać obiekty czy nazwy tych obiektów; Tworzysz sobie tablicę:

var
  aComponents: array of TComponent;

i korzystać z niej w ten sposób:

SetLength(aComponents, 2);

aComponents[0] := Button1;
aComponents[1] := Memo1;

Nie ma żadnego problemu; Jak z niej skorzystać? A no np. tak:

TButton(aComponents[0]).Hide();
TMemo(aComponents[1]).Clear();

EDIT: Znowu się spóźniłem... :P

0

@up, masz jeszcze jedną szansę być 1 ;D

Super o to mi chodziło, w sumie to logiczne skoro Button1 jest typu TButton to mogę taką tablicę utworzyć ;P. I już chyba taka ostatnia rzecz trudniejsza którą nie wiem jak rozwiązać. Mianowicie mam coś typu stos klocków, na który dodaje kolejne klocki i który się powiększa. Planszę mam podzieloną na tablicę 2 wymiarową, jeśli np. tab[1][4] == 1 to tam będzie ten klocek (obrazek klocka). Wiem jak wczytać taki obrazek ale trzeba go wcześniej zdefiniować, ImageN : TImage, gdzie N to numer klocka. No i teraz pytanie jak to zrobić w trakcie działania programu. Czy mam po prostu na wyrost zdefiniować tysiąc klocków a potem ewentualnie wypełniać je obrazkiem?

1

Zrobić tablicę

Obrazki : array of TImage

a potem tak

procedure ZrobKlocka;
begin
  SetLength(Obrazki, High(Obrazki) + 2);
  Obrazki[High(Obrazki)] := TImage.Create;
  with Obrazki[High(Obrazki)) do
    begin
      Width := 40;
      Height := 40;
      Top := //ileś tam
      Left := //Ileś tam
      Name := 'Image' + IntToStr(High(Obrazki));
    end;
end;
 
0

Super, dzięki bardzo, trochę przerobie, przekażę all przez parametry i będzie ładniej stylistycznie i nie zawalę może tak pamięci. Dzięki

0

Trochę kod przerobiłem na własny użytek ale wyświetla error "Not enough actual parameters". Wiem co on oznacza po PL ale jak się go pozbyć?

{musze dac na sztywno tablice Images 1..80 bo kazdy klocek o konkretnym nrze ma konkretny indeks w tablicy }

procedure TForm1.CreateBlock(dTop : integer; dLeft : integer; Number : integer);
begin
    Images[Number] := TImage.Create; { w tej linijce blad }
    with Images[Number] do
    begin
        Width := 50;
        Height := 50;
        Top := dTop;
        Left := dLeft;
        Name := 'Block' + IntToStr(Number);
    end;
end;

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