Você está na página 1de 121

Programação Orientada a Eventos

FreePascal + Lazarus

Armando Jorge Sousa (asousa@fe.up.pt)

Professor Auxiliar
Depart. de Engenharia Electrotécnica e de Computadores
FEUP

Versão 9, 30 Março 2008

asousa@fe.up.pt --- 1 ---


Índice

● Introdução POE
● Solução FPC/Lazarus
● Resenha Histórica
● Básicos de FreePascal (Object Pascal)
● Lazarus IDE (e primeiro programa)
● Lazarus IDE avançado
(incluindo debugger e navegação em programas longos)
● FPC avançado (e algumas configurações do IDE)
● Controlos visuais (padrão) mais frequentes
● Componentes adicionais

asousa@fe.up.pt --- 2 ---


Introdução

asousa@fe.up.pt --- 3 ---


Paradigma «Programação Orientada a Eventos» (POE)

● O SO fornece um sistema de processamento de eventos em ciclo


▪ Eventos podem ser clicks do rato, mensagens de rede, etc.
▪ A linguagem colabora mapeando callbacks
▪ Adicionando eventos à fila
● Os programas do utilizador são chamados pelo SO
▪ Processam o evento comunicado pelo SO e retornam
▪ O sistema operativo com interface gráfica distribui eventos
(pelos diversos programas) - Multi Janela !
▪ As “forms” janelas pertencem a diferentes programas !
● Estes conceitos integram bem com Multi-Processo / Multi-User

asousa@fe.up.pt --- 4 ---


Benefícios da Programação Orientada a Eventos (POE)

● SO e linguagem colaboram no sentido de:


▪ Optimizar o desempenho / eliminar polling
▪ Identificar Idle Time
▪ Atender eventos na lista de forma adequada
▪ Diminuir mudanças de contexto (forçadas)
▪ Tornar transparentes os acessos remotos ou ao hardware
▪ Facilitar a programação gráfica / interactiva

asousa@fe.up.pt --- 5 ---


Conceitos a abandonar quando se faz POE

● Abordagem procedimental pura


● A noção dos microcontroladores de “tempo para «queimar»”
● Loops de espera
● Operações de polling

Abandonar em definitivo a noção de que o


programa tem um ciclo principal,
começa aí e aí acaba

asousa@fe.up.pt --- 6 ---


Linguagens de programação modernas

● Funcionalidades acrescidas
▪ Independência de SO e ao hardware
● Abordagem JAVA: Máquina Virtual
▪ Byte Code a interpretar(/JIT Compile) é portável
▪ Lento (...)
● Outra abordagem (FPC/Lazarus):
▪ O ambiente de desenvolvimento e a linguagem asseguram a
correcta implementação das mesmas funcionalidades em
ambientes diferentes
▪ Portar para outro ambiente SO/HW implica recompilar
▪ Código executável convencional (rápido)

asousa@fe.up.pt --- 7 ---


Estrutura de camadas

Lazarus / Delphi / Kylix


Maiores
FCL + LCL / VCL / CLX Funcionali-
S.O. Windows / S.O. Linux dades
Hardware
● Funcionalidades
● VCL – Delphi
Cross-Platform à custa de
diversas camadas de software
● CLX – Delphi>=6 e Kylix ● “Footprint” grande
● Não mais lentos por causa
● FCL e LCL - Lazarus disso...

asousa@fe.up.pt --- 8 ---


FPC/Lazarus

asousa@fe.up.pt --- 9 ---


Uma Solução Possível: Lazarus + FreePascal

• “Freeware” with source


• Sem royalties / GPL !
• Bibliotecas LGPL* (pode linkar estaticamente)
• RAD (Rapid Application Development)
• GUI altera código fonte após edição (2 way tool)
• Cross Platform
• Fácil ligação a diversos SGBD
• Facilmente Extensível: pacotes e componentes
• Permite POE ou não + facilidade de instalar servidores
• Linguagem OO, moderna, simples mas poderosa
• Inclui excepções, variantes e operator overloading

asousa@fe.up.pt --- 10 ---


Lazarus cross-platform


FPC+Lazarus portado para:

Processadores:

Intel x86, Amd64/x86 64, PowerPC, Sparc, ...
● Sistemas Operativos:
● Windows 32, Linux, FreeBSD, Mac OS X/Darwin,

Mac OS classic, DOS, OS/2, Netware (libc and


classic), MorphOS, ...

asousa@fe.up.pt --- 11 ---


Histórico

asousa@fe.up.pt --- 12 ---


História do Lázarus

• Borland:
• Turbo Pascal / B. Pascal + Delphi + Kylix

• Internet:
• Free Pascal + Lazarus

• Lazarus feito em Lazarus + FPC,


“autocompilável” !

asousa@fe.up.pt --- 13 ---


História do Lázarus

• Pascal (1971):
• Simplificação do Algol (1960)
• Genérica
• Educativa (ponteiros, “:= vs ==”,... )
• Strong Typed
• Case Insensitive
• Statically Linked
• Rápida
• Inicializações/Finalizações

asousa@fe.up.pt --- 14 ---


Desenvolvimento Integrado - IDEs

• Borland Turbo Pascal


• DOS - IDE - 1983
• Borland Delphi
• Windows – RAD - 1993
• Borland Kylix
• Linux - RAD - 2001
• Actualmente “clássico” da Borland
• Lazarus: RAD Cross Platform

• Outro RAD muito diferente: MS .NET studio

asousa@fe.up.pt --- 15 ---


Lazarus TimeLine

• Free Pascal - 1993


• FCP 1.0 – 2000
• FPC 2.0 – 2005
• Lazarus começa em 1999
(renascido depois do projecto “Megido”)
• Lazarus 0.9.20 - 2007
• Lazarus 1.0 – brevemente !

asousa@fe.up.pt --- 16 ---


FreePascal / Object Pascal

• Object Reference Model


• Herança, instanciação, propriedades, métodos,
overloading, polimorfismo
(só em run time se vai saber o método)
• Private / Protected / Public
• Cascata de criações/libertações
• Excepções

asousa@fe.up.pt --- 17 ---


• Programação para os S.O. actuais:

Programação Visual !!!


Orientada aos Eventos !!!

• Para cada acção na GUI ou cada evento, o S.O.


chama determinada rotina do programa

asousa@fe.up.pt --- 18 ---


Robustez Multi-Thread -- Synchronize

• Evitar conflitos entre threads (Thread Safe), ver:


http://wiki.lazarus.freepascal.org/index.php/Multithreaded_Application_Tutorial

• Programa deve libertar processador para o SO sempre que


espera, ie., não deve haver ciclos de espera

• Para programação gráfica a eventos não é necessário


recorrer a mutex'es

asousa@fe.up.pt --- 19 ---


Introdução ao Pascal

• EBooks gratuitos
“Essential Pascal” e “Essential Delphi”
No URL:
http://www.marcocantu.com

• Ver na biblioteca qualquer livro do mesmo autor!

• Tutorial de Pascal_FPC
http://www.taoyue.com/tutorials/pascal/

asousa@fe.up.pt --- 20 ---


FreePascal
FPC

asousa@fe.up.pt --- 21 ---


Documentação FreePascal + Lazarus

•Documentação de referência do FreePascal (FPC)


ftp://ftp.freepascal.org/pub/fpc/docs-pdf/ref.pdf

• Documentação do Lazarus:
http://lazarus-ccr.sourceforge.net/docs/

• Tutoriais do Lazarus
http://wiki.lazarus.freepascal.org/Special:Allpages

• Lazarus DB FAQ
http://wiki.lazarus.freepascal.org/index.php/Lazarus_DB_Faq

quase tudo o que disser respeito a kylix ou delphi !!!

asousa@fe.up.pt --- 22 ---


Estrutura do Código

Program Elementar;

begin

// ...

end. // termina com ponto final

asousa@fe.up.pt --- 23 ---


Dicas para pascal

• Atribuições :=
• Comparações =
• Strong Typed (casts automáticos limitados)
• Case Insensitive
• Inicializações/Finalizações
• Blocos com begin/end
• Programas e unidades terminam com end.

asousa@fe.up.pt --- 24 ---


Estrutura do Código

Program Elementar;

const
csAVOG : real = 6.02; // constante global

var
UmInteiro : integer; // var global

begin

// ...

UmInteiro:=Trunc(csAVOG);

// ...

end.

asousa@fe.up.pt --- 25 ---


Estrutura do Código

• O nome do program será o


Program elementar; nome do ficheiro de disco
(elementar.pas) e
Uses Forms {sistema}, MyUnit; possivelmente dará o nome
do executável
begin
• Um programa utiliza units do
// ... sistema e do utilizador, que
são linkadas para produzir o
Application.Run; executável

end. • As units permitem dividir o


código em blocos
• Tipicamente 1 form implica
uma unit para encapsular
todo o código associado

asousa@fe.up.pt --- 26 ---


Estrutura do Código

• O nome da unit será o nome


unit MyUnit; do ficheiro de disco
(MyUnit.pas)
interface • A porção de código
// definições e declarações
// a exportar “Interface” é conhecida
pelos módulos exteriores à
implementation unit
// código local à unit • A porção “implementation” é
local e inacessível do
end. exterior

asousa@fe.up.pt --- 27 ---


Estrutura do Código

unit MyUnit;
• MyUnit utiliza e importa a
interface
interface das unidades A,B,C
uses A, B, C; • MyUnit exporta as declarações de
const AlmostZero = 0.001; AlmostZero e TotalSum
• O programa unidades podem
var TotalSum: Real;
utilizar MyUnit
// ...

Program elementar;
• Programa utiliza MyUnit
Uses
Forms, MyUnit; • Passa a conhecer as variáveis
globais da unidade MyUnit
/// ... (AlmostZero e Total)

asousa@fe.up.pt --- 28 ---


Estrutura do Código

// ...

implementation

uses // outras units a importar/utilizar


D, E;

var // variável local (não será exportada)


UmInteiro : Integer;

procedure MyProcedure;
begin
// ...
end;

initialization
// Inicialização da unidade (opcional)

finalization
// Finalização da unidade (opcional)
end.

asousa@fe.up.pt --- 29 ---


IDE Lazarus

asousa@fe.up.pt --- 30 ---


File,
New Application

 Gere um Projecto
que inclui:
 Programa
 Unit (Forms)
 Unit

 2 Way !!!
 Editor gráfico
encontra código
adequado (...)
 Mudar nome de
componente muda
código todo (...)

asousa@fe.up.pt --- 31 ---


asousa@fe.up.pt --- 32 ---
asousa@fe.up.pt --- 33 ---
 File, Save ALL: unit_ola, project_ola

 Mudar “Name” da Form para “Form_Ola”


“Caption” vem mudada (ver no editor)

 Colocar TButton na Form


 Mudar “Name” para BProximo
 Botões devem começar com letra “B”
 Mudar “Caption” para “Próximo”

asousa@fe.up.pt --- 34 ---


• Fazendo Double Click no botão da form que estamos a
desenhar, o IDE leva-nos até ao código que será executado
quando (em run-time) o utilizador premir o botão uma vez
(evento “OnClick”)

procedure Tform_Ola.BProximoClick (Sender: TObject);


begin
|
end;

asousa@fe.up.pt --- 35 ---


Código do Projecto Elementar de Teste

procedure Tform_Ola.BProximoClick(Sender: TObject);


begin
BProximo.Caption:='Olá Mundo';
end;

• Após introduzir o código mostrado acima, premir F9 ou


seleccionar Menu Run, Opção Run para compilar o código
e executá-lo de seguida
• Depois de compilar sem problemas, o programa gerado é
executado e aparece a janela que desenhamos
• Depois de carregar no botão, o texto inscrito no botão
caption é alterado e passa mostrar “Olá Mundo”
• Saia da aplicação carregando no x do canto da form

asousa@fe.up.pt --- 36 ---


Código do Projecto de teste 2

asousa@fe.up.pt --- 37 ---


SnapShots do projecto de teste 2 (windows e linux)

asousa@fe.up.pt --- 38 ---


Notas para iniciados

● Para facilidade de localização dos ficheiros importantes,


criar uma directoria para cada projecto novo
● Criar o projecto e logo depois gravar todos os ficheiros
(Save All); gravar todos os ficheiros da aplicação na mesma
directoria
● Não alterar código que não foi feito por nós !!!
● Ligar logo as opções de verificação: Project,
Compiler_Options, Code:

asousa@fe.up.pt --- 39 ---


IDE Avançado

asousa@fe.up.pt --- 40 ---


Ajudas à codificação: Code Templates

for (premir CTRL+J)

for | := to do
begin
forb (premir CTRL+J)
end;

asousa@fe.up.pt --- 41 ---


Ajudas à codificação: Code Templates

If, CTRL+J => menu de templates


ifb,CTRL+J=>if| then/begin/end

asousa@fe.up.pt --- 42 ---


Ajuda à codificação: Completion

CTRL+SPACE: Context sensitive Completion

asousa@fe.up.pt --- 43 ---


Ajuda à codificação: Navegação em código extenso

● Bookmarks (máximo de 10 pontos de interesse no código):


▪ Para definir um ponto de interesse no código:
CTRL+Shift+.. (teclas de 1 a 0)
▪ Para levar o cursor até um ponto de interesse no
código: CTRL+.. (teclas de 1 a 0)
● Saltar entre Declaração e Código de procedimento ou
função: CTRL+ e CTRL+
● Saltar para a declaração de variável: CTRL+MouseClick
● Saltar (de volta) para ponto anterior de edição: CTRL H

asousa@fe.up.pt --- 44 ---


Ajuda à codificação: Navegação entre janelas

● F12: troca entre form e código

● F11: Object Inspector


● CTRL+F12: View Units
● Shift+F12: View Forms

asousa@fe.up.pt --- 45 ---


Debugging

asousa@fe.up.pt --- 46 ---


Debugging

Breakpoint

asousa@fe.up.pt --- 47 ---


Debugging

● Premir Ctrl+Alt+L para listar todas as variáveis locais


● Para o cursor do rato em cima de uma variável para ver o
seu valor (funcionalidade em melhoramento)
● Premir F7/F8 para single stepping
● Premir F4 para ir até ao cursor

asousa@fe.up.pt --- 48 ---


Help de contexto

● Premir F1 leva a activar o browser para levar a uma página


de context sensitive help, ie, leva a um help associado ao
texto onde o cursor está

procedure Tform_Ola.BProximoClick(Sender: TObject);


begin
BProximo.Caption|:='Olá Mundo';
end;

● Com o cursor no texto caption do botão, o help de


TControl.Caption é mostrado no browser

asousa@fe.up.pt --- 49 ---


Dúvidas Frequentes

• Procedure não devolve dados


• Function devolve dados

• If (x=y) then begin


x:=x+1;
end else begin // cuidado não pode ter “;” !!!
x:=x+2;y:=x+2;
end;

• Format( ' Total %d ' , [ N ] );

asousa@fe.up.pt --- 50 ---


Funções

• Function devolve um dado de determinado tipo

function InverteString ( S : string ) : string;

var
TempStr : string;
i : integer;
Siz : integer;

begin
TempStr:='';
Siz:=length(S);
if Siz>0 then
for I:=Siz downto 1 do
TempStr:=TempStr+S[I]; !
InverteString:=TempStr;
end;

asousa@fe.up.pt --- 51 ---


Funções e tipos de parâmetros

// Func1 passa param de entrada na função por cópia


// Mudar S dentro da função não altera S fora da função !
function func1 ( S : string ) : string;
// ...

// Func2 passa param por endereço (param. de entrada e saída)


function func2 ( var S : string ) : string;
// ...

// Func3 passa param const -> compilador não deixa alterar


// E S_out é parâmetro de saída
procedure func3 ( const S_in : string ; out S_out : string );
// ...

asousa@fe.up.pt --- 52 ---


Funções multi parâmetros

procedure func4 (const S1,S2 : string; out S3 : string) ;

function func5 ( i,j,k : integer ; s : string ) : string ;

asousa@fe.up.pt --- 53 ---


ShowMessage

ShowMessage('Olá, isto é um teste');

asousa@fe.up.pt --- 54 ---


Pascal Avançado

asousa@fe.up.pt --- 55 ---


Referência

• Prioridades:
• unários[@,not,-]
• *,/,div,mod,and,shl,shr
• +,-,or,xor,=,<>,<,>,<=,>=, in/is
• Tipos básicos
• string / Pchar, integer, boolean, char,
TDateTime, Set, Pointer, variant...
• high(vector)/low(vector)/sizeof(variável)
• Ord(...)+Chr(...)

asousa@fe.up.pt --- 56 ---


Projecto, Unidade e Form

• Project, New Project,


program Project1; Application cria uma nova
(●●●) aplicação vazia
• É criado um projecto vazio
uses
(●●●) Unit1;
e uma unidade vazia
associada a uma form vazia
begin • Programa é Project1
Application.Initialize;
Application.CreateForm(TForm1, Form1); • Utiliza a Unit1
Application.Run; • Para ver este ficheiro fazer
end.
Menu Project, View Source
• Este código é gerado e
gerido automaticamente,
não é necessário
alterar nada !

asousa@fe.up.pt --- 57 ---


Unidade e Form

unit Unit1;
• Na interface da Unit1 é
interface
definida a TForm1 e a
(●●●) variável Form1
• Neste caso a Form1 tem um
type
{ TForm1 } botão e um procedimento
Button1Click(...)
TForm1 = class(TForm) • É o programa (não a
Button1: TButton;
procedure Button1Click((●●●)); unidade) que dá instruções
(●●●) ao S.O. para efectivamente
end; abrir a janela e executá-la
var • Adicionando componentes à
Form1: TForm1; form, o código da definição
do tipo da form é alterado
Obs: A classe não descreve na automaticamente
totalmente a form !

asousa@fe.up.pt --- 58 ---


Unidade e Form

object Form1: TForm1


Left = 412
Height = 320
Top = 121
Width = 400
(●●●)
object Button1: TButton • A descrição completa da
Left = 86 form estará no ficheiro .lfm
Height = 25
Top = 70
Width = 75 • Não alterar nada !
OnClick = Button1Click
(●●●)
end
end

asousa@fe.up.pt --- 59 ---


Tipos

Type

// Começar os tipos por 'T'

TUpCaseLetters = 'A'..'Z'; // subrange

TDaysOfMonth = array [1..31] of Integer;

TMyDate = record
Month : Byte;
Day : Byte;
Year : Integer;
end;

asousa@fe.up.pt --- 60 ---


Tipos

type
// tipo enumerado
TColors = ( ColorRed, ColorGreen, ColorBlue ); // RGB

// set, isto é, conjunto !!!


TSetOfLetters = set of Char;

var
AnArray: array [10..24] of Byte;
ColorCode: array [ColorRed .. ColorGreen] of Word;
Palette: set of TColors;

asousa@fe.up.pt --- 61 ---


Operações com Conjuntos (sets)

type
TSetOfLetters = set of Char;
var
Letters1, Letters2 : TConjLetras;
begin
Letters1 := ['A', 'B', 'C'];
Letters2 := [];
if ('A' in Letters1) then ShowMessage('A');
if (['A','B'] <= Letters1) then ShowMessage('A,B');
if (['E'] <= Letters1) then ShowMessage('Falso');
if (Letters2 = []) then ShowMessage('Vazio');
end;

asousa@fe.up.pt --- 62 ---


Range Check

type
TDozen = array [1..12] of Integer;
var
UmMes : TDozen;

procedure WorkSomethingOnADozen;
begin
UmMes[1] := 10;
UmMes[2] := 12;
UmMes[0] := 18; // erro compile-time
UmMes[25] := 18; // erro compile-time
end;

asousa@fe.up.pt --- 63 ---


type

TBiDimVector = array [1..12, 1..12] of Integer;

var

ABiDimVector : TBiDimVector;

asousa@fe.up.pt --- 64 ---


Apontadores

type
PointerToInt = ^Integer;

var
P: ^Integer;
X : Integer;

begin
P := @X;
// Muda variável de duas formas diferentes
X := 10;
P^ := 20;
end;

asousa@fe.up.pt --- 65 ---


Apontadores

var
P: ^Integer;

begin

New (P); // criar / iniciar

P^ := 20; // atribuir

ShowMessage (IntToStr (P^));

Dispose (P); // terminar

end;

asousa@fe.up.pt --- 66 ---


Apontadores – com detecção de limites (range check)

procedure TForm_Ola.Button1Click(Sender: Tobject);


var
x : integer;
DayTemp : array [ 1 .. 31 ] of Integer;
begin
x:=123456;
DayTemp [x] := 18; // GPF – Segmentation Fault
end;

asousa@fe.up.pt --- 67 ---


IFs

if N>0 then begin


ShowMessage('Positivo');
if N>1 then begin
ShowMessage(' >1');
end;
end else begin // relativo ao N>0 (ie N<=0)
ShowMessage('Negativo');
if N<-1 then begin
ShowMessage(' <-1');
end;
end;

asousa@fe.up.pt --- 68 ---


Case

case MyChar of
'+' : Text := 'Soma';
'-' : Text := 'Subtracção';
'*', '/' : Text := 'Multiplicação ou divisão';
'0'..'9' : Text := 'Algarismo';
'a'..'z' : Text := 'Minúscula';
'A'..'Z' : Text := 'Maiúscula';
else
Text := 'Outro Caracter';
end;

asousa@fe.up.pt --- 69 ---


Ciclo for

... • A variável do ciclo


Soma := 0; pode ser qualquer
for i := 1 to 10 do ordinal, incluindo
Soma := Soma + i; tipos enumerados
...
• Ciclos for são muito
mais restritivos em
Pascal que em C

... • Tal como em qualquer


Soma := 0; outro ciclo for, o corpo
for i := 10 downto 1 do do ciclo pode ser não
begin executado nunca
Soma := Soma + i;
end;
...

asousa@fe.up.pt --- 70 ---


Ciclos While e Repeat Until

While ( (I <= 100) and (J <= 100) ) do


begin
...
I := I + 1;
J := J + 1;
end;

repeat
...
I := I + 1;
J := J + 1;
until (I > 100) or (J > 100);

asousa@fe.up.pt --- 71 ---


Procedimentos e funções

function DoubleVersion1 (Value: Integer) : Integer;


begin
DoubleVersion1 := Value * 2;
end;

function DoubleVersion2 (Value: Integer) : Integer;


begin
Result := Value * 2;
end;

procedure DoubleProc (var Value : Integer);


begin
Value := Value * 2;
end;

asousa@fe.up.pt --- 72 ---


Vectores Dinâmicos

Var DynArray : Array of Integer; // Vector Dinâmico

procedure TForm1.FormCreate(Sender: TObject);


begin
SetLength (DynArray, 100); // alocar
end;

procedure TForm1.BFillClick(Sender: TObject);


var I: Integer;
begin
for I := Low (DynArray) to High (DynArray) do
Array1 [I] := I;
end;

procedure TForm1.BGrowClick(Sender: TObject);


begin
SetLength (DynArray, 200); // mantém + cresce lim sup
end;

asousa@fe.up.pt --- 73 ---


Formatação de Strings

string:=format ('%-8d,%f', [var_i,var_f]);

TYPE SPECIFIER DESCRIPTION


The corresponding integer value is converted to a string of
d (decimal)
decimal digits.
The corresponding integer value is converted to a string of
x (hexadecimal)
hexadecimal digits.
The corresponding pointer value is converted to a string expressed
p (pointer)
with hexadecimal digits.
The corresponding string, character, or PChar value is copied to
s (string)
the output string.
The corresponding floating-point value is converted to a string
e (exponential)
based on exponential notation.

asousa@fe.up.pt --- 74 ---


Formatação de Strings

The corresponding floating-point value is converted to a string


f (floating point)
based on floating point notation.
The corresponding floating-point value is converted to the
g (general) shortest possible decimal string using either floating-point or
exponential notation.
The corresponding floating-point value is converted to a floating-
n (number)
point string but also uses thousands separators.
The corresponding floating-point value is converted to a string
representing a currency amount. The conversion is based on
m (money)
regional settings-see the Delphi Help file under Currency and
date/time formatting variables.

asousa@fe.up.pt --- 75 ---


Ciclos Prolongados

for i := 1 to VeryLargeNumber do begin


Application.ProcessMessages;
Total := Total + i;
end;

for i := 1 to VeryLargeNumber do begin


Application.HandleMessage; // Permite IdleTime
Total := Total + i;
end;

asousa@fe.up.pt --- 76 ---


Excepções (i)

var
n2, n1, n0 : integer;
begin
try
n0 := 0;
n1 := 1;
n2 := n1 div n0;
ShowMessage('1 / 0 = '+IntToStr(n2));
except
on E : Exception do
begin
ShowMessage('Nome da classe = '+E.ClassName);
ShowMessage('Mensagem da excepção = '+E.Message);
end;
end;
end;

asousa@fe.up.pt --- 77 ---


Excepções (ii)

...
except
// IO error
on E : EInOutError do
ShowMessage('IO error : '+E.Message);
// Dibision by zero
on E : EDivByZero do
ShowMessage('Div by zero error : '+E.Message);
// Catch other errors
else
ShowMessage('Unknown error');
end;

asousa@fe.up.pt --- 78 ---


Excepções (iii)

var
number, zero : Integer;
begin
// Try to divide an integer by zero - to raise an exception
number := -1;
Try
zero := 0;
number := 1 div zero;
ShowMessage('number / zero = '+IntToStr(number));
finally
if number = -1 then
begin
ShowMessage('Not assigned - using default');
number := 0;
end;
end;
end;

asousa@fe.up.pt --- 79 ---


Excepções (iv)

...
int2:=2;int1:=1;int0:=0;
vf2:=2.0;vf1:=1.0;vf0:=0.0;
try
case RadioGroup.ItemIndex of
0 : int2 := int1 div int0;
1 : vf2 := vf1 / vf0;
2 : assert(False,'Just Testing');
end;
Memo.Append('Sem erro:='+FloatToStr(vf2)+';'+ IntToStr(int2));
except
on E : EDivByZero do
Memo.Append('Div int por 0:'+e.ClassName+': '+e.Message);
on E : EZeroDivide do
Memo.Append('Div Virg Flt 0:'+e.ClassName+':'+e.Message);
on E : Exception do Memo.Append('outro erro -- '+
e.ClassName+': '+e.Message);
end;
Memo.Append('Continua, Normal');
...

asousa@fe.up.pt --- 80 ---


Variants

procedure TFormMain.Button1Click(Sender: TObject);


var
V : Variant;
I : Integer;

begin
V:='100';
I:=V;
Button1.Caption:='I = ' + IntToStr(I); // OK
V:='Something else';
I:=V;
Button1.Caption:='I = ' + IntToStr(I); // NOK
end;

• Something else não é um inteiro válido

•Na 2ª atribuição é gerada uma excepção

asousa@fe.up.pt --- 81 ---


Código Condicional (cross platform, etc)

{$IFDEF LINUX}

// Código para Linux

{$ELSE}

// Código para outras plataformas

{$ENDIF}

asousa@fe.up.pt --- 82 ---


Componentes & Pacotes

• Para acrescentar
funcionalidades, qualquer
programador pode criar
componentes

• Components, Open Package

• Package graph

asousa@fe.up.pt --- 83 ---


Mais Controlos
Visuais Padrão

asousa@fe.up.pt --- 84 ---


Botões

● TButton
● TBitButton
● TSpeedButton

asousa@fe.up.pt --- 85 ---


Texto numa linha

● TLabel

● TEdit

● TStatusBar

asousa@fe.up.pt --- 86 ---


Caixa de texto (memo box)

● TMemo

● Baseado na classe TStrings


que permite muitas operações
interessantes !

asousa@fe.up.pt --- 87 ---


TMemo

... with FormMain.Memo do begin ...

• Append('Mais Uma Linha');

• Lines.SaveToFile('c:\memo.txt'); // windows

• Lines.Delete(0); // apaga primeira linha

• Lines[0]:='... substitui a 1a linha ...';

• UmaStringGrande:=text; // toda a memo

• Memo.Lines.LoadFromFile('~/memo.txt'); // linux

... end; ...

Obs1: Ver Scroll Bars, Wrap, ReadOnly, ...


Obs2: Ver variável global DirectorySeparator

asousa@fe.up.pt --- 88 ---


CheckBox / Group

● TCheckBox
● TCheckGroup

asousa@fe.up.pt --- 89 ---


RadioGroup

● TRadioGroup

asousa@fe.up.pt --- 90 ---


ListBox e ComboBox

asousa@fe.up.pt --- 91 ---


Image, PaintBox, Shape

● TImage (.Picture)
● TPaintBox (.Canvas)
● TShape (.Canvas)

asousa@fe.up.pt --- 92 ---


Caixas de diálogo Standard (Gravar, Abrir, ...)

● Componentes que desaparecem


durante a execução do código
● Chamam as caixas standard do S.O.
● OpenDialog1, SaveDialog, SelectDirectoryDialog
● Chamar método execute

asousa@fe.up.pt --- 93 ---


Temporizador

● TTimer (separador system)


● Tempo em milisegundos
● Dificuldades em cumprir
restrições de tempos curtos

asousa@fe.up.pt --- 94 ---


Gráficos

● TBarChart

asousa@fe.up.pt --- 95 ---


Menus

● TMainMenu
▪ Fazendo double click abre-se o editor de menus
▪ É possível acrescentar diversas opções:
◦ check box
◦ Ícone
◦ Tecla atalho
◦ ...

asousa@fe.up.pt --- 96 ---


Componente de persistência

● TXMLPropStorage
(Separdor Misc)
(depois utilizar a propriedade da form.SessionProperties)
● À saída do programa grava-se estado actual dos elementos
listados em SessionProperties que serão carregados de volta
à entrada, eliminando necessidade de gravar
explicitamente configurações
● Grava um ficheiro em formato XML

● Existe um outro componente TIniPropStorage


que faz o mesmo com ficheiros INI

asousa@fe.up.pt --- 97 ---


Aplicções Multi Form

● Para acrescentar ao projecto File, New Form (acrescenta


uma unidade para esta form)
● Para mostrar uma form:
▪ A form nova é criada automaticamente
▪ É necessário utilizar a unit correspondente:
uses UnitWhereFormSecondaryIs
▪ FormSecondary.Show;
● Para fechar fechar a form
▪ FormMain.Close;
● Para obrigar a ter apenas uma janela da aplicação activa:
▪ FormSecondary.ShowModal;

asousa@fe.up.pt --- 98 ---


Componentes
Externos Úteis

asousa@fe.up.pt --- 99 ---


Componentes a utilizar

• ZeosLib - http://sourceforge.net/projects/zeoslib/

• A ligação ao PostGreSQL é nativa a partir da


versão Lazarus 0.9.12

• Sdpo_Serial – 5dpo component pack

• lNnet - LightWeight Networking Library


http://wiki.lazarus.freepascal.org/lNet

• Todos estes pacotes são (win32 + linux)

asousa@fe.up.pt --- 100 ---


Sdpo Serial

• Para utilizar SDPO_Serial sob Linux


• uses cthreads em 1º em todas as units e no *.LPR

•{$DEFINE UseCThreads} no *.LPR


(abrir o *.LPR através do Project Inspector)
[automático no lazarus 0.9.20]
• Recompilar o Lazarus e o LCL com a opção
-dUseCThreads
(Tools, Configure Build Lazarus e depois Build Lazarus)
• Obs1: executar o programa na command line para obter
mensagens de erro adicionais
• Obs2: a sincronização (-dUSE_SYNCHRONIZE)
é desnecessária a partir da versão 0.9.12 do Lazarus

asousa@fe.up.pt --- 101 ---


Lazarus FAQs

After I installed a component, Lazarus crashes with the following message:


Threading has been used before cthreads was initialized. Make cthreads one of the first units in
your uses clause. Runtime error 211
How can I fix this?
Your freshly installed component is using threads. Fpc on *nix doesn't automatically include threading
support, but it must be intialized. This initialization is done in the cthreads unit. Every application
using the component needs to add this unit to the uses clause of the main program. Lazarus itself is
no exception. This can be done in two ways:
1) Change the source of ide/lazarus.pp: add the cthreads as first unit to the uses clause, so that is looks
like this:
uses
cthreads,
{$IFDEF IDE_MEM_CHECK}
...
and rebuild lazarus. [su, cd laz_dir, make clean bigide ou make clean all]

asousa@fe.up.pt --- 102 ---


Lazarus FAQs

2) In order to avoid modifying lazarus.pp file, a fpc compiler option could be used. Once package that
uses threads has been compiled, open menu Tools->Configure "build Lazarus". Configure "build
Lazarus" dialog will be shown, in field "Options:" type -Facthreads and then press "OK" button. The
next step is to install the package. Lazarus will be built with option -Facthreads which means that it
will treat main program as if unit cthreads where first in uses clause.

Hint:
Maybe your old (non-crashing) lazarus executable is stored as lazarus.old in the same directory as
the crashing lazarus executable.

asousa@fe.up.pt --- 103 ---


Mais detalhes funcionamento Porta Série

• Comando exemplo envio:


SdpoSerial.WriteData(EditSend.text);
• Receber:
• Evento OnRxData tem cadência imprevisível -
algumas vezes pode-se receber byte a byte, outras não,
é obrigatório o programa lidar com este facto !!!
• Exemplo de recepção:
SdpoSerial.SynSer.RecvPacket(0);
• Cuidado com as permissões e os portos (tty0, ttyUSB0):
chmod a+rw /dev/tty*
chmod a+rwx /var/lock

asousa@fe.up.pt --- 104 ---


RADs & acesso Bases de Dados

● Cursor – aponta para um tuplo (linha de tabela de BD)


● Dataset – colecção de tuplos (tabela de BD)
● BD: Local ou Remota (Cliente / Servidor)
▪ CLI - Call Level Interface
▪ ODBC JDBC BDE
● Propriedades ACID:
Atomicity-Consistency-Isolation-Durability
● Middleware: CORBA, DCOM, DataSnap (=MIDAS)
● D6 & Kylix dBExpress – SQL Thin DB access Layer

asousa@fe.up.pt --- 105 ---


Data Aware Objects (i)

SGBD

DBGrid
Query/ DBEdit
DataSource
/Dataset DBLabel
...

asousa@fe.up.pt --- 106 ---


Sequência para ligar à BD PGSQL em Lazarus 0.9.12

•Colocar na form os componentes das respectivas tabs:


• PQConnection - SQLdb
• SQLQuery - SQLdb
• SQLTransaction - SQLdb
• DataSource - DataAccess
• DBGrid - DataControls
•PQConnection preencher:
• Transaction + Database + HostName + UserName + password
•Verificar que SQLTransaction aponta para PQConnection
•Na SQLQuery preencher:
• Transacção + Database
• SQL (exemplo: 'select * from anytable')
•Na DataSource preencher DataSet como SQLQuery
•Na DBGrid preencher DataSource

asousa@fe.up.pt --- 107 ---


Data Aware Objects (ii) - DBGrid

asousa@fe.up.pt --- 108 ---


Data Aware Objects (iii) - DBEdit

...
dbGrid.ReadOnly:= ... (sempre!!!)
...
SQLQuery.Post;
...

asousa@fe.up.pt --- 109 ---


Alterações directas à Base de Dados

...
begin
enter:=chr(13)+chr(10);
s:='update copias set nalugueres=nalugueres+1 where'+
'codcopia='+IntToStr(EstaCopia); // string de código SQL
try
PQConChange.Connected:=True;
PQConChange.ExecuteDirect('Begin Work;');
PQConChange.ExecuteDirect(s);
PQConChange.ExecuteDirect('Commit Work;');
PQConChange.Connected:=False;
except
on E : EDatabaseError do
MemoLog.Append('ERROBD:'+enter+
E.ClassName+enter+E.Message);
on E : Exception do
MemoLog.Append('ERRO:'+enter+
E.ClassName+enter+E.Message);
end;
end;

asousa@fe.up.pt --- 110 ---


Observações acerca de Lazarus e PGSQL

• Não utilizar dados tipo “text” mas sim “varchar”


• Não utilizar “numeric” mas antes inteiros ou “float8”
• As tabelas devem ter uma chave primária
• Utilizar nomes sempre e só com minúsculas e sem caracteres
portugueses
• É obrigatório proteger todas as operações directas sobre a base de
dados com transacções
• É obrigatório o ficheiro libpq.dll e as outras DLLs binárias do
PostGreSQL estarem no path do sistema operativo

asousa@fe.up.pt --- 111 ---


Sockets com componente visual

● Descarregar a partir de:


▪ http://ovh.dl.sourceforge.net/sourceforge/lazarus-ccr/lnet-0.4.0.zip

● Instalar o *.lpk run_time e depois *.lpk relativo ao IDE

asousa@fe.up.pt --- 112 ---


lnet/visual/examples/tcpudp

...
FNet: TLNetComponent; // TCP ou UDP
...

procedure TForm1.LTCPComponentReceive(aSocket: TLSocket);


var
s: string;
begin
if aSocket.GetMessage(s) > 0 then begin
MemoText.Append(s);
MemoText.SelStart:=Length(MemoText.Lines.Text);
FNet.IterReset;
if FIsServer then repeat
FNet.SendMessage(s, FNet.Iterator);
until not FNet.IterNext;
end;
end;

asousa@fe.up.pt --- 113 ---


lnet/visual/examples/tcpudp

procedure TForm1.SendButtonClick(Sender: TObject);


var
AllOK: Boolean;
n: Integer;
begin
if Length(EditSend.Text) > 0 then begin
AllOk:=True;
if Assigned(FNet.Iterator) then repeat
n:=FNet.SendMessage(EditSend.Text, FNet.Iterator);
if n < Length(EditSend.Text) then begin
MemoText.Append('Error on send [' + IntToStr(n) + ']');
AllOK:=False;
end;
until not FNet.IterNext;
if FIsServer and AllOK then
MemoText.Append(EditSend.Text);
EditSend.Text:='';
end;
end;

asousa@fe.up.pt --- 114 ---


lnet/visual/examples/tcpudp

procedure TForm1.ListenButtonClick(Sender: TObject);


begin
if FNet.Listen(StrToInt(EditPort.Text)) then begin
MemoText.Append('Accepting connections');
FIsServer:=True;
end;
end;

procedure TForm1.ConnectButtonClick(Sender: TObject);


begin
if FNet.Connect(EditIP.Text, StrToInt(EditPort.Text)) then
FIsServer:=False;
end;

asousa@fe.up.pt --- 115 ---


lnet/visual/examples/tcpudp

procedure TForm1.DiconnectButtonClick(Sender: TObject);


begin
FNet.Disconnect;
MemoText.Append('Disconnected');
end;

procedure TForm1.SendEditKeyPress
(Sender: TObject; var Key: char);
begin
if Key = #13 then
SendButtonClick(Sender);
end;

asousa@fe.up.pt --- 116 ---


TAChart

procedure TForm1.Button1Click(Sender: TObject);


var
Serie:TTASerie;
i:Integer;
begin
Serie:=TTASerie.Create(TAChart1);
TAChart1.AddSerie(Serie);
Serie.ShowLines:=True;
Serie.ShowPoints:=False;
Serie.Title:='Sinus';
for i:=-500 to 499 do
Serie.AddXY(i/10,Sin(i/10)*10,clBlack);
end;

asousa@fe.up.pt --- 117 ---


Operator Overloading

type
complex = record type
re : real; complex = record
im : real; re : real;
end; im : real;
end;

// ... var
Z2:=Z1; R1 : real;
//... Z1,Z2 : complex;

// Atribuição de
// record's do // Operator Overloading
// mesmo tipo
// Z2:=Z1 operator := (r : real) z : complex;
// é a atribuição de begin
// todos os campos z.re:=r;
z.im:=0.0;
end;

asousa@fe.up.pt --- 118 ---


Ligações interessantes

● Mailing List do Lazaros, arquivo e pesquisa:


http://www.lazarus.freepascal.org/mailarchives
http://www.lazarus.freepascal.org/modules.php?op=modload&name=Search
● Todos os Wiki's:
http://wiki.lazarus.freepascal.org/Special:Allpages
● Lazarus & Pascal:
http://wiki.lazarus.freepascal.org/Lazarus_Documentation
● Bases de dados:http://wiki.lazarus.freepascal.org/index.php/Lazarus_Database_Tutorial

http://wiki.lazarus.freepascal.org/TPSQL
● RXLib:
▪ http://wiki.lazarus.freepascal.org/RXfpc
▪ http://www.alexs75.narod.ru/fpc/rxfpc/index.html

asousa@fe.up.pt --- 119 ---


Ligações interessantes

● http://wiki.lazarus.freepascal.org/Lazarus_Faq
● http://wiki.lazarus.freepascal.org/Installing_Lazarus
● http://wiki.lazarus.freepascal.org/LCL_Defines
● http://wiki.lazarus.freepascal.org/Getting_Lazarus
● http://wiki.lazarus.freepascal.org/Icon_Editor
● http://wiki.lazarus.freepascal.org/GLScene
● http://wiki.lazarus.freepascal.org/Multiplatform_Programming_Guide
● http://wiki.lazarus.freepascal.org/Multithreaded_Application_Tutorial
● http://wiki.lazarus.freepascal.org/lNet
● http://wiki.lazarus.freepascal.org/Pascal_Script

asousa@fe.up.pt --- 120 ---


Programação Orientada a Eventos
+ FPC/Lazarus

- Fim -

asousa@fe.up.pt --- 121 ---

Você também pode gostar