[DELPHI] 1. podstawy + kalkulator

Dzia³ po¶wiêcony programowaniu

Moderators: Frost, Luigi, HQTM-Team

User avatar
Maxoff
HQTM-Team
Posts: 3434
Joined: 2004-07-06, 18:28
Location: Poland
Contact:

Post by Maxoff »

Tak i ma tą przewagę, że ifa wystarczy dopisać raz, co ułatwia modyfikacje. Później pokaże jak z 10 procedur zrobić jedną :D
... You only have to know how to prepare query, google will do the rest ...
... My software ...
... Guide to Punctuation ...
User avatar
Luigi
Moderator
Posts: 475
Joined: 2004-07-15, 19:11
Location: z mm.li.pl
Contact:

Post by Luigi »

No przydałoby się bo chyba nie wiem jak to zrobić :D
User avatar
Maxoff
HQTM-Team
Posts: 3434
Joined: 2004-07-06, 18:28
Location: Poland
Contact:

Post by Maxoff »

Jak zapewne zauważyliście przyciski mają dużo właściwości (patrz ObjectInspector). Są tam Name, Caption a także Tag. Ten ostatni nie ma żadnego znaczenia, jest to zwykła liczba całkownita. Możemy tam wprowadzić własne dane a jego interpretacja pozostawiona jest programiście. Jest to pewniego rodzaju schowek na dane i my tego schowka użyjemy. Dla każdego przycisku wpiszemy w Tagu cyfrę mu odpowiadającą, tj dla przycisku 1 wpisujemy w Tag 1, dla przycisku 2 -> wpisujemy 2 itp. Zastanawiacie się po co to zrobiliśmy ?? Niedługo wszystko stanie się jasne.

Kolejna sprawa to zdarzenia. Jak wspominałem cały interfejs bazuje na zdarzeniach a domyślnym zdarzeniem dla przycisku jest Click. Oczywiście przyciski mają dużo więcej zdarzeń, a ich liste można obejrzeć w ObjectInspekotrze (jest tam zakłada Events). Trochę tych On... na liście jest. Nie będziemy wnikać co znacza pozostałe zdarzenia, nie jest to teraz istotne. Ważne jest to, że przy zdarzeniu OnClick wpisana jest nazwa procedury obsługującej zdarzenie (w tym przypadku edtNum1Click). Procedury mają to do siebie, że można je wywoływać z innych miejsc, a więc kilka przycisków może mieć tą samą obsługe zdarzenia OnClick. Aby to przetestowac klikamy na przycisku 2 i przechodzimy do ObjectInspektora. W OnClick będzie wpisane btnNum2Click. Teraz zmienamy to na btnNum1Click (można wybrac z rozwijanej listy) i kompilujemy.

Co się stanie gdy naciśniemy 2?? Zostanie wpisane 1. Nie do końca o to nam chodziło, ale zaraz to poprawimy. A więc przechodzimy do edytora kodu (można wciśnąć F12) i usuwamy wszystkie procedury OnClick z wyjątkiem edtNum1Click, a nastepnie klikając po kolei w każdy przycisk ustawiamy mu zdarzenie OnClick na edtNum1Click. Aby przetestować czy wszytko zostało poprawnie wykonane, uruchamiamy program i klikamy po kolei w przyciski. Każdy bez wyjątku powinien dopisać 1.

Osatnią kwestią na dzisiaj (dość dużo tego się nazbierało) jest napisanie tej uniwersalnej procedury. W tym celu kilkamy dwa razy na którymś przycisku (wszystkie mają tą samą procedurę obsługi zdarzenia) i modyfikujemy ją w następujący sposób:

Code: Select all

procedure TMainForm1.edtNum1Click(Sender: TObject);
var nNum:integer;
begin

  WriteDigit(nNum); 
end;
Modyfikacji dużo nie ma. Dodaliśmy lokalną zmienną nNum oraz zastąpiliśmy 1 zmienną. Pozostała do dopisania ostatnia linijka. Co chcemy zrobić ?? Musimy sprawdzić który przycisk wywołał zdarzenie. A jak to zrobić ?? Jako parametr procedury dostajemy obiekt Sender, czyli sprawcę zdarzenia. Jest on typu TObject, jest to najogolniejszy typ (coś jak samochód), jednak my mamy przycisk (czyli np Golfa), a więc musimy sprawić aby Sender był interpretowany w kontekscie przycisku, co jest bardzo proste. Rozwiązuje to następujący zapis:

Code: Select all

Sender as TButton
Wiemy juz, że to przycisk, ale nie wiemy który. Na szczęscie każdy przycisk różni się m.in. Tagiem, który odpowiada wpisywanej cyfrze. A więc ostatecznie otrzymujemy:

Code: Select all

nNum:=(Sender as TButton).Tag;
prawda, że proste ?? ;)

Cała procedura wygląda teraz następująco:

Code: Select all

procedure TMainForm1.edtNum1Click(Sender: TObject);
var nNum:integer;
begin
  nNum:=(Sender as TButton).Tag;
  WriteDigit(nNum); 
end;
Można by ją nawet uprościć do jednej linijki rezygnując ze zmiennej tymczasowej.

Jak się okazuje, w takiej sytuacji nie potrzebujemy nawet procedury WriteDigit, gdyż możemy wstawić ją do zdarzenia. Zróbmy tak. Usuwamy WriteDigit a naszą procedurę edtNum1Click doprowadzamy do następującej postaci:

Code: Select all

procedure TMainForm1.edtNum1Click(Sender: TObject);
var nNum:integer;
begin
  nNum:=(Sender as TButton).Tag;
  if StrToInt(edtNumber.Text)=0 
    then edtNumber.Text:=IntToStr(nNum) 
    else edtNumber.Text:=edtNumber.Text+IntToStr(nNum); 
end;
Dzieki temu 11 procedur zastąpiliśmy jedną a program nadal nie stracił swojej funkcjonalności a wszystkie modyfikacje są teraz dużo prostrze.

Zapyta ktoś, czy nie można było tak od razu ?? Można było, ale chciałem Wam pokazać rózne metody abyście mogli wybrać tą, która Wam najbardziej odpowiada.

Przeanalizujcie dokładnie powyższy przykład i jeśli macie jakieś pytania to pytajcie, gdyz zrozumienie mechanizmy zdarzeń (idei) jest bardzo ważne.

To wszystko na dzisiaj, czekam na komentarze, uwagi, pytania...

[ Added: 2005-03-04, 20:53 ]
Luigi wrote:No przydałoby się bo chyba nie wiem jak to zrobić
Mam nadzieję, że teraz już będziesz wiedział :D
... You only have to know how to prepare query, google will do the rest ...
... My software ...
... Guide to Punctuation ...
User avatar
Luigi
Moderator
Posts: 475
Joined: 2004-07-15, 19:11
Location: z mm.li.pl
Contact:

Post by Luigi »

Dobre, a nawet bardzo dobre, pożyteczne i znacząco ułatwiające życie :-)

-> Ja już zrobiłem i wszystko działa.

PS: Jak idzie innym :> Poddaliścię się czy działacie dalej :>:D
User avatar
ZNag
HQTM-Team
Posts: 3526
Joined: 2004-07-15, 19:20
Location: W³oc³awek [PL]
Contact:

Post by ZNag »

Zaczynam nadrabiać zalełgości :D Aktualnie jestem przy przypisywaniu funkcji do przycisków :) Niestety mam problem z funkcją if :/ Próbuję wstawić ten kod:

Code: Select all

if StrToInt(edtNumber.Text)=0
  then edtNumber.Text:=IntToStr(1)
  else edtNumber.Text:=edtNumber.Text+IntToStr(1);
Niestety jak go wstawaim i próbuję zobaczyć na podglądzie (F9), to podświetla mi jedną linijkę na czerwoną i pyta się czy debugować :| Co zrobić ??
•ZNag - Strona domowa
•Intel Core 2 Quad Q9400 2,66GHz, 4GB DDR2 800MHz (Dual Channel), ATI Radeon HD 4850 512MB, 500GB HDD + Pendrive 4GB; Samsung SyncMaster T220
User avatar
Luigi
Moderator
Posts: 475
Joined: 2004-07-15, 19:11
Location: z mm.li.pl
Contact:

Post by Luigi »

Wstaw cały kod i pogrub linijkę, którą zaznacza.
User avatar
ZNag
HQTM-Team
Posts: 3526
Joined: 2004-07-15, 19:20
Location: W³oc³awek [PL]
Contact:

Post by ZNag »

Code: Select all

unit Unit1;

interface

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

type
  TMainForm = class(TForm)
    btnNum1: TButton;
    btnNum3: TButton;
    btnNum4: TButton;
    btnNum5: TButton;
    btnNum6: TButton;
    btnNum7: TButton;
    btnNum8: TButton;
    btnNum9: TButton;
    btnNum0: TButton;
    btnNump: TButton;
    btnNumm: TButton;
    edtNumber: TEdit;
    MainMenu: TMainMenu;
    Plik1: TMenuItem;
    Zamknij1: TMenuItem;
    btnNum2: TButton;
    procedure Zamknij1Click(Sender: TObject);
    procedure btnNum1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.Zamknij1Click(Sender: TObject);
begin
close;
end;

procedure TMainForm.btnNum1Click(Sender: TObject);
begin
edtNumber.Text:=edtNumber.Text+IntToStr(1);
end;
[b]if StrToInt(edtNumber.Text)=0[/b]
  then edtNumber.Text:=IntToStr(1)
  else edtNumber.Text:=edtNumber.Text+IntToStr(1);
end.
Jak wstawiam między begin a end; to też nic nie daje :?
•ZNag - Strona domowa
•Intel Core 2 Quad Q9400 2,66GHz, 4GB DDR2 800MHz (Dual Channel), ATI Radeon HD 4850 512MB, 500GB HDD + Pendrive 4GB; Samsung SyncMaster T220
User avatar
Maxoff
HQTM-Team
Posts: 3434
Joined: 2004-07-06, 18:28
Location: Poland
Contact:

Post by Maxoff »

1.

Code: Select all

    edtNumber.Text:=edtNumber.Text+IntToStr(1); 
end; 
if StrToInt(edtNumber.Text)=0
Tam NIE może być enda

2. Jaką wartośc masz w edicie po odpaleniu programu ?? Mam nadzieję, że 0 bo jeśli pusty albo jeśli jest tam tekst to będzie się sypać.
Możesz to ustawić w ObjectInspektorze, pole Text ma być równe 0

3. Dlaczego masz dwa razy edtNumber.Text:=edtNumber.Text+IntToStr(1); ??

4. Przed end. ma byc jeszcze end;
czyli ma to wyglądać tak:

Code: Select all

unit Unit1; 

interface 

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

type 
  TMainForm = class(TForm) 
    btnNum1: TButton; 
    btnNum3: TButton; 
    btnNum4: TButton; 
    btnNum5: TButton; 
    btnNum6: TButton; 
    btnNum7: TButton; 
    btnNum8: TButton; 
    btnNum9: TButton; 
    btnNum0: TButton; 
    btnNump: TButton; 
    btnNumm: TButton; 
    edtNumber: TEdit; 
    MainMenu: TMainMenu; 
    Plik1: TMenuItem; 
    Zamknij1: TMenuItem; 
    btnNum2: TButton; 
    procedure Zamknij1Click(Sender: TObject); 
    procedure btnNum1Click(Sender: TObject); 
  private 
    { Private declarations } 
  public 
    { Public declarations } 
  end; 

var 
  MainForm: TMainForm; 

implementation 

{$R *.dfm} 

procedure TMainForm.Zamknij1Click(Sender: TObject); 
begin 
  close;
end; 

procedure TMainForm.btnNum1Click(Sender: TObject); 
begin 
  if StrToInt(edtNumber.Text)=0
    then edtNumber.Text:=IntToStr(1) 
    else edtNumber.Text:=edtNumber.Text+IntToStr(1); 
end; 

end.
... You only have to know how to prepare query, google will do the rest ...
... My software ...
... Guide to Punctuation ...
User avatar
[*CzApLa*]
Fantastic Order Of Lords
Posts: 1169
Joined: 2004-07-15, 19:12
Contact:

Post by [*CzApLa*] »

Ja jestem tym zainteresowany ale niestety będe musiał dojść do tego sam bo ani dziś, ani jutro, ani cały tydzień - od poniedziałku do piątku nie mam czasu, a jak zaczną robić sprawdziany i klasówki to chyba depresji dostane i NIE UMIEM PISAÆ "W OGÓLE", NIE UMIEM PISAÆ "W OGÓLE", NIE UMIEM PISAÆ "W OGÓLE" nie wejde do kompa :|
Tylko mam nadzieje że nie będą z każdego przedmiotu pytac dzień w dzień bo chyba dostane takiej deprechy jak 3 miesiące temu (chemia)
Mysle ze dojde do tego jak będe miał sporo czasu bo teraz to albo jestem na kilka min albo robie kilka rzeczy na raz :|
Bleh jak by to były wakacje to inaczej ;)
Nie dyskutuj nigdy z głupcem - najpierw Cię sprowadzi do swojego poziomu, a potem wykończy doświadczeniem.
KCP-Zmieniamy świat na plus.
KCP-(Nie)Umiemy opowiadać bajek.
User avatar
ZNag
HQTM-Team
Posts: 3526
Joined: 2004-07-15, 19:20
Location: W³oc³awek [PL]
Contact:

Post by ZNag »

Dzięki Maxoff, trochę się zaplątałem w kodzie, bo nie dokońca wiedziałem jak to wszystko chodzi, ale teraz już wiem :D mam jeszcze pytanie odnośnie "zdarzeń".

Code: Select all

unit Unit1;

interface

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

type
  TMainForm = class(TForm)
    btnNum1: TButton;
    btnNum3: TButton;
    btnNum4: TButton;
    btnNum5: TButton;
    btnNum6: TButton;
    btnNum7: TButton;
    btnNum8: TButton;
    btnNum9: TButton;
    btnNum0: TButton;
    btnNump: TButton;
    btnNumm: TButton;
    edtNumber: TEdit;
    MainMenu: TMainMenu;
    Plik1: TMenuItem;
    Zamknij1: TMenuItem;
    btnNum2: TButton;
    procedure Zamknij1Click(Sender: TObject);
    procedure btnNum1Click(Sender: TObject);
    procedure btnNum2Click(Sender: TObject);
    procedure btnNum3Click(Sender: TObject);
    procedure btnNum4Click(Sender: TObject);
    procedure btnNum5Click(Sender: TObject);
    procedure btnNum6Click(Sender: TObject);
    procedure btnNum7Click(Sender: TObject);
    procedure btnNum8Click(Sender: TObject);
    procedure btnNum9Click(Sender: TObject);
    procedure btnNum0Click(Sender: TObject);
  private
     procedure WriteDigit(nNumber:integer);
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.Zamknij1Click(Sender: TObject);
begin
close;
end;

[b]procedure TMainForm.btnNum1Click(Sender: TObject);
begin
 WriteDigit(1)
end;

procedure TMainForm.btnNum2Click(Sender: TObject);
begin
 WriteDigit(2)
end;

procedure TMainForm.btnNum3Click(Sender: TObject);
begin
 WriteDigit(3)
end;

procedure TMainForm.btnNum4Click(Sender: TObject);
begin
 WriteDigit(4)
end;

procedure TMainForm.btnNum5Click(Sender: TObject);
begin
 WriteDigit(5)
end;

procedure TMainForm.btnNum6Click(Sender: TObject);
begin
 WriteDigit(6)
end;

procedure TMainForm.btnNum7Click(Sender: TObject);
begin
 WriteDigit(7)
end;

procedure TMainForm.btnNum8Click(Sender: TObject);
begin
 WriteDigit(8)
end;

procedure TMainForm.btnNum9Click(Sender: TObject);
begin
 WriteDigit(9)
end;

procedure TMainForm.btnNum0Click(Sender: TObject);
begin
 WriteDigit(0)
end;

procedure TMainForm.WriteDigit(nNumber:integer);
begin
  if StrToInt(edtNumber.Text)=0
    then edtNumber.Text:=IntToStr(nNumber)
    else edtNumber.Text:=edtNumber.Text+IntToStr(nNumber);
end;[/b]

end.
Czy mogę usunąc pogrubiony kod, a zamiast niegoi wstawić

Code: Select all

procedure TMainForm1.edtNum1Click(Sender: TObject);
var nNum:integer;
begin
  nNum:=(Sender as TButton).Tag;
  if StrToInt(edtNumber.Text)=0
    then edtNumber.Text:=IntToStr(nNum)
    else edtNumber.Text:=edtNumber.Text+IntToStr(nNum);
end; 
Jeśli tak, to czy wstarczy ta opcja dla każdego przycisku :> ?
•ZNag - Strona domowa
•Intel Core 2 Quad Q9400 2,66GHz, 4GB DDR2 800MHz (Dual Channel), ATI Radeon HD 4850 512MB, 500GB HDD + Pendrive 4GB; Samsung SyncMaster T220
User avatar
Luigi
Moderator
Posts: 475
Joined: 2004-07-15, 19:11
Location: z mm.li.pl
Contact:

Post by Luigi »

Jeśli nadałeś tagi buttonom to możesz to zastąpić i to wystarczy dla każdego przycisku.
Zresztą zrób i sprawdź :-)

Po zrobieniu możesz też (a nawet powinieneś skasować):

Code: Select all

procedure WriteDigit(nNumber:integer); 

Nie używamy już tej procedury, a więc to będzie niepotrzebne.
User avatar
Frost
Moderator
Posts: 1435
Joined: 2004-07-16, 11:04
Location: Family
Contact:

Post by Frost »

Ja jestem zainteresowany. Teraz co prawda pisze coś innego w innym języku, ale...
User avatar
ZNag
HQTM-Team
Posts: 3526
Joined: 2004-07-15, 19:20
Location: W³oc³awek [PL]
Contact:

Post by ZNag »

Ja narazie nie będe mógł dokończyć kalkulatora, ponieważ komputer mi nie chodzi :( :/

//EDIT: Komputer już mi chodzi, ale straciłem wszystkie dane :( :/
•ZNag - Strona domowa
•Intel Core 2 Quad Q9400 2,66GHz, 4GB DDR2 800MHz (Dual Channel), ATI Radeon HD 4850 512MB, 500GB HDD + Pendrive 4GB; Samsung SyncMaster T220
User avatar
Luigi
Moderator
Posts: 475
Joined: 2004-07-15, 19:11
Location: z mm.li.pl
Contact:

Post by Luigi »

Rozumiem, że nikt już nie zamierza kontynuować nauki pisania programów ?
User avatar
Maxoff
HQTM-Team
Posts: 3434
Joined: 2004-07-06, 18:28
Location: Poland
Contact:

Post by Maxoff »

Ja tam kaklulator dokończe, jutro powinna pojawić się dalsza część. Boli mnie jedynie brak zaintersowania :( Chyba, że pisżę tutaj o zbyt oczywistych rzeczach i wszyscy doskonale to wiedzą - jeśli tak, to powiedzcie a przejdziemy na następny poziom :D

PS. Taka długa przerwa była spowodowana moją nieobecnością spowodowaną kłopotami zdrowotnymi.
... You only have to know how to prepare query, google will do the rest ...
... My software ...
... Guide to Punctuation ...
Post Reply