RobertPolson
02-09-2020, 11:58:23
Buenos días,
He desarrollado una calculadora en Delphi Berlin 10.1, con un hilo que se encarga de hacer los cálculos que se le indiquen cuando se pulse el boton '='. Cuando este botón se pulsa se realiza una espera de 3seg para comprobar que, durante la ejecución del hilo, se pueden seguir pulsando botones, por ejemplo si se quiere borrar todo y que el cálculo no se realice finalmente pues que me permita hacerlo. El problema es que durante el primer cálculo sí me permite pulsar botones, pero en los siguientes la pantalla se queda bloqueada hasta que acaba el cálculo.
En cualquier caso el boton de borrar lo he programado para que finalice el hilo y ni siquiera en el primer calculo lo cierra. Pulso, borra la pantalla pero pasados 3 segundos me muestra el resultado. Adjunto el código por si alguien me podría ayudar...Mil gracias de antemano.:)
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ToolWin, Vcl.ComCtrls, Vcl.StdCtrls;
type
TOperacion = (NOOPER, SUMA, RESTA, MULTI, DIVI);
TThreadCaculador = class(TThread)
private
protected
public
procedure Execute; override;
end;
TForm1 = class(TForm)
LabelCreador: TLabel;
EditNumero: TEdit;
boton0: TButton;
boton1: TButton;
boton2: TButton;
boton3: TButton;
boton4: TButton;
boton5: TButton;
boton6: TButton;
boton7: TButton;
boton8: TButton;
boton9: TButton;
botonDiv: TButton;
botonMult: TButton;
botonResta: TButton;
botonSigno: TButton;
botonComa: TButton;
botonSuma: TButton;
LabelOperacion: TLabel;
botonCalcular: TButton;
botonClear: TButton;
LabelEspera: TLabel;
procedure boton0Click(Sender: TObject);
procedure boton1Click(Sender: TObject);
procedure boton2Click(Sender: TObject);
procedure boton3Click(Sender: TObject);
procedure boton4Click(Sender: TObject);
procedure boton5Click(Sender: TObject);
procedure boton6Click(Sender: TObject);
procedure boton7Click(Sender: TObject);
procedure boton8Click(Sender: TObject);
procedure boton9Click(Sender: TObject);
procedure botonSumaClick(Sender: TObject);
procedure botonRestaClick(Sender: TObject);
procedure botonMultClick(Sender: TObject);
procedure botonDivClick(Sender: TObject);
procedure botonCalcularClick(Sender: TObject);
procedure botonClearClick(Sender: TObject);
procedure botonComaClick(Sender: TObject);
procedure botonSignoClick(Sender: TObject);
private
{ Private declarations }
threadCalculador : TThreadCaculador;
public
{ Public declarations }
valor1, valor2 : real; // Operandos
operacion : TOperacion; // Operación (ver constantes de arriba)
end;
var
Form1: TForm1;
HiloCorriendo : Boolean;
implementation
{$R *.dfm}
{------------------------------------------------------------------------------}
{ TThreadCaculador }
{------------------------------------------------------------------------------}
procedure TThreadCaculador.Execute;
var
resultado : real;
i : Integer;
begin
// Salir si no se ha indicado una operacion
if Form1.operacion = NOOPER then exit;
// Evitar division por cero
if (Form1.operacion = DIVI) and (Form1.valor2 = 0) then exit;
HiloCorriendo := True;
// Espera: imprimir '.' cada segundo en la GUI
for i := 1 to 3 do
begin
Sleep(1000);
Synchronize( // Para ejecutar en el hilo principal
procedure
begin
Form1.LabelEspera.Caption := Form1.LabelEspera.Caption + '.'
end
)
end;
Form1.LabelEspera.Caption := '';
// Realizar cálculo
resultado := 0;
if Form1.operacion = SUMA then resultado := Form1.valor1 + Form1.valor2
else if Form1.operacion = RESTA then resultado := Form1.valor1 - Form1.valor2
else if Form1.operacion = MULTI then resultado := Form1.valor1 * Form1.valor2
else if Form1.operacion = DIVI then resultado := Form1.valor1 / Form1.valor2;
// valor1 ahora sera el resultado tambien
//Form1.valor1 := resultado;
// Actualizar valor en la GUI
Synchronize( // Para ejecutar en el hilo principal
procedure
begin
Form1.EditNumero.Text := FloatToStr(resultado);
Form1.operacion := NOOPER;
end
)
end;
{------------------------------------------------------------------------------}
{ TForm1 }
{------------------------------------------------------------------------------}
procedure TForm1.boton0Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '0' else
EditNumero.Text := EditNumero.Text + '0';
end;
procedure TForm1.boton1Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '1' else
EditNumero.Text := EditNumero.Text + '1';
end;
procedure TForm1.boton2Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '2' else
EditNumero.Text := EditNumero.Text + '2';
end;
procedure TForm1.boton3Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '3' else
EditNumero.Text := EditNumero.Text + '3';
end;
procedure TForm1.boton4Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '4' else
EditNumero.Text := EditNumero.Text + '4';
end;
procedure TForm1.boton5Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '5' else
EditNumero.Text := EditNumero.Text + '5';
end;
procedure TForm1.boton6Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '6' else
EditNumero.Text := EditNumero.Text + '6';
end;
procedure TForm1.boton7Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '7' else
EditNumero.Text := EditNumero.Text + '7';
end;
procedure TForm1.boton8Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '8' else
EditNumero.Text := EditNumero.Text + '8';
end;
procedure TForm1.boton9Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '9' else
EditNumero.Text := EditNumero.Text + '9';
end;
procedure TForm1.botonClearClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
LabelOperacion.Caption := '';
EditNumero.Text := '0';
end;
procedure TForm1.botonComaClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
EditNumero.Text := EditNumero.Text + ',';
end;
procedure TForm1.botonSignoClick(Sender: TObject);
var
tmp : real;
begin
tmp := StrToFloat(EditNumero.Text);
tmp := -tmp;
EditNumero.Text := FloatToStr(tmp);
end;
procedure TForm1.botonSumaClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
valor1 := StrToFloat(EditNumero.Text);
LabelOperacion.Caption := EditNumero.Text + ' + ';
EditNumero.Text := '0';
operacion := SUMA;
end;
procedure TForm1.botonRestaClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
valor1 := StrToFloat(EditNumero.Text);
LabelOperacion.Caption := EditNumero.Text + ' - ';
EditNumero.Text := '0';
operacion := RESTA;
end;
procedure TForm1.botonMultClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
valor1 := StrToFloat(EditNumero.Text);
LabelOperacion.Caption := EditNumero.Text + ' x ';
EditNumero.Text := '0';
operacion := MULTI;
end;
procedure TForm1.botonDivClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
valor1 := StrToFloat(EditNumero.Text);
LabelOperacion.Caption := EditNumero.Text + ' / ';
EditNumero.Text := '0';
operacion := DIVI;
end;
procedure TForm1.botonCalcularClick(Sender: TObject);
begin
Form1.valor2 := StrToFloat(Form1.EditNumero.Text);
Form1.LabelOperacion.Caption := Form1.LabelOperacion.Caption + Form1.EditNumero.Text + ' ';
Form1.EditNumero.Text := '';
// Si no he creado ya el thread de cálculo, lo creo (se ejecuta automáticamente)
// Si ya está creado y ha acabado la petición anterior, lo acabo y lo vuelvo a ejecutar
if (not Assigned(threadCalculador)) then
begin
threadCalculador := TThreadCaculador.Create;
threadCalculador.FreeOnTerminate := True;
threadCalculador.Priority := tpLower;
end
else if threadCalculador.Finished then
begin
threadCalculador.Terminate;
threadCalculador.Execute;
end
end;
end.
He desarrollado una calculadora en Delphi Berlin 10.1, con un hilo que se encarga de hacer los cálculos que se le indiquen cuando se pulse el boton '='. Cuando este botón se pulsa se realiza una espera de 3seg para comprobar que, durante la ejecución del hilo, se pueden seguir pulsando botones, por ejemplo si se quiere borrar todo y que el cálculo no se realice finalmente pues que me permita hacerlo. El problema es que durante el primer cálculo sí me permite pulsar botones, pero en los siguientes la pantalla se queda bloqueada hasta que acaba el cálculo.
En cualquier caso el boton de borrar lo he programado para que finalice el hilo y ni siquiera en el primer calculo lo cierra. Pulso, borra la pantalla pero pasados 3 segundos me muestra el resultado. Adjunto el código por si alguien me podría ayudar...Mil gracias de antemano.:)
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ToolWin, Vcl.ComCtrls, Vcl.StdCtrls;
type
TOperacion = (NOOPER, SUMA, RESTA, MULTI, DIVI);
TThreadCaculador = class(TThread)
private
protected
public
procedure Execute; override;
end;
TForm1 = class(TForm)
LabelCreador: TLabel;
EditNumero: TEdit;
boton0: TButton;
boton1: TButton;
boton2: TButton;
boton3: TButton;
boton4: TButton;
boton5: TButton;
boton6: TButton;
boton7: TButton;
boton8: TButton;
boton9: TButton;
botonDiv: TButton;
botonMult: TButton;
botonResta: TButton;
botonSigno: TButton;
botonComa: TButton;
botonSuma: TButton;
LabelOperacion: TLabel;
botonCalcular: TButton;
botonClear: TButton;
LabelEspera: TLabel;
procedure boton0Click(Sender: TObject);
procedure boton1Click(Sender: TObject);
procedure boton2Click(Sender: TObject);
procedure boton3Click(Sender: TObject);
procedure boton4Click(Sender: TObject);
procedure boton5Click(Sender: TObject);
procedure boton6Click(Sender: TObject);
procedure boton7Click(Sender: TObject);
procedure boton8Click(Sender: TObject);
procedure boton9Click(Sender: TObject);
procedure botonSumaClick(Sender: TObject);
procedure botonRestaClick(Sender: TObject);
procedure botonMultClick(Sender: TObject);
procedure botonDivClick(Sender: TObject);
procedure botonCalcularClick(Sender: TObject);
procedure botonClearClick(Sender: TObject);
procedure botonComaClick(Sender: TObject);
procedure botonSignoClick(Sender: TObject);
private
{ Private declarations }
threadCalculador : TThreadCaculador;
public
{ Public declarations }
valor1, valor2 : real; // Operandos
operacion : TOperacion; // Operación (ver constantes de arriba)
end;
var
Form1: TForm1;
HiloCorriendo : Boolean;
implementation
{$R *.dfm}
{------------------------------------------------------------------------------}
{ TThreadCaculador }
{------------------------------------------------------------------------------}
procedure TThreadCaculador.Execute;
var
resultado : real;
i : Integer;
begin
// Salir si no se ha indicado una operacion
if Form1.operacion = NOOPER then exit;
// Evitar division por cero
if (Form1.operacion = DIVI) and (Form1.valor2 = 0) then exit;
HiloCorriendo := True;
// Espera: imprimir '.' cada segundo en la GUI
for i := 1 to 3 do
begin
Sleep(1000);
Synchronize( // Para ejecutar en el hilo principal
procedure
begin
Form1.LabelEspera.Caption := Form1.LabelEspera.Caption + '.'
end
)
end;
Form1.LabelEspera.Caption := '';
// Realizar cálculo
resultado := 0;
if Form1.operacion = SUMA then resultado := Form1.valor1 + Form1.valor2
else if Form1.operacion = RESTA then resultado := Form1.valor1 - Form1.valor2
else if Form1.operacion = MULTI then resultado := Form1.valor1 * Form1.valor2
else if Form1.operacion = DIVI then resultado := Form1.valor1 / Form1.valor2;
// valor1 ahora sera el resultado tambien
//Form1.valor1 := resultado;
// Actualizar valor en la GUI
Synchronize( // Para ejecutar en el hilo principal
procedure
begin
Form1.EditNumero.Text := FloatToStr(resultado);
Form1.operacion := NOOPER;
end
)
end;
{------------------------------------------------------------------------------}
{ TForm1 }
{------------------------------------------------------------------------------}
procedure TForm1.boton0Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '0' else
EditNumero.Text := EditNumero.Text + '0';
end;
procedure TForm1.boton1Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '1' else
EditNumero.Text := EditNumero.Text + '1';
end;
procedure TForm1.boton2Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '2' else
EditNumero.Text := EditNumero.Text + '2';
end;
procedure TForm1.boton3Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '3' else
EditNumero.Text := EditNumero.Text + '3';
end;
procedure TForm1.boton4Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '4' else
EditNumero.Text := EditNumero.Text + '4';
end;
procedure TForm1.boton5Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '5' else
EditNumero.Text := EditNumero.Text + '5';
end;
procedure TForm1.boton6Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '6' else
EditNumero.Text := EditNumero.Text + '6';
end;
procedure TForm1.boton7Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '7' else
EditNumero.Text := EditNumero.Text + '7';
end;
procedure TForm1.boton8Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '8' else
EditNumero.Text := EditNumero.Text + '8';
end;
procedure TForm1.boton9Click(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
if EditNumero.Text = '0' then
EditNumero.Text := '9' else
EditNumero.Text := EditNumero.Text + '9';
end;
procedure TForm1.botonClearClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
LabelOperacion.Caption := '';
EditNumero.Text := '0';
end;
procedure TForm1.botonComaClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
EditNumero.Text := EditNumero.Text + ',';
end;
procedure TForm1.botonSignoClick(Sender: TObject);
var
tmp : real;
begin
tmp := StrToFloat(EditNumero.Text);
tmp := -tmp;
EditNumero.Text := FloatToStr(tmp);
end;
procedure TForm1.botonSumaClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
valor1 := StrToFloat(EditNumero.Text);
LabelOperacion.Caption := EditNumero.Text + ' + ';
EditNumero.Text := '0';
operacion := SUMA;
end;
procedure TForm1.botonRestaClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
valor1 := StrToFloat(EditNumero.Text);
LabelOperacion.Caption := EditNumero.Text + ' - ';
EditNumero.Text := '0';
operacion := RESTA;
end;
procedure TForm1.botonMultClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
valor1 := StrToFloat(EditNumero.Text);
LabelOperacion.Caption := EditNumero.Text + ' x ';
EditNumero.Text := '0';
operacion := MULTI;
end;
procedure TForm1.botonDivClick(Sender: TObject);
begin
if HiloCorriendo then
begin
threadCalculador.Terminate;
HiloCorriendo := False;
end;
valor1 := StrToFloat(EditNumero.Text);
LabelOperacion.Caption := EditNumero.Text + ' / ';
EditNumero.Text := '0';
operacion := DIVI;
end;
procedure TForm1.botonCalcularClick(Sender: TObject);
begin
Form1.valor2 := StrToFloat(Form1.EditNumero.Text);
Form1.LabelOperacion.Caption := Form1.LabelOperacion.Caption + Form1.EditNumero.Text + ' ';
Form1.EditNumero.Text := '';
// Si no he creado ya el thread de cálculo, lo creo (se ejecuta automáticamente)
// Si ya está creado y ha acabado la petición anterior, lo acabo y lo vuelvo a ejecutar
if (not Assigned(threadCalculador)) then
begin
threadCalculador := TThreadCaculador.Create;
threadCalculador.FreeOnTerminate := True;
threadCalculador.Priority := tpLower;
end
else if threadCalculador.Finished then
begin
threadCalculador.Terminate;
threadCalculador.Execute;
end
end;
end.