Pri*_*eat -1 delphi pascal delphi-xe2
我的代码输出到富编辑时遇到问题。当我单击按钮计算所有内容然后显示所有内容时,它不会输出生成的 ClientNum 和 Price。但是,当我之后第二次单击该按钮时,它会毫不费力地输出所有内容?我的代码是否有问题,或者可能是诸如防病毒软件之类的外部问题干扰了输出?
type
TfrmTourBooking = class(TForm)
rgpDestination: TRadioGroup;
rgpAccommodation: TRadioGroup;
sedPeopleAmount: TSpinEdit;
Label1: TLabel;
edtID: TEdit;
Label2: TLabel;
Label3: TLabel;
redOut: TRichEdit;
btnCalc: TButton;
bmbClose: TBitBtn;
rgpTransport: TRadioGroup;
edtName: TEdit;
Label4: TLabel;
rgpTourLength: TRadioGroup;
edtPhoneNum: TLabeledEdit;
edtEmail: TLabeledEdit;
bmbReset: TBitBtn;
dtpTime: TDateTimePicker;
procedure FormActivate(Sender: TObject);
procedure btnCalcClick(Sender: TObject);
procedure rgpDestinationClick(Sender: TObject);
procedure rgpTourLengthClick(Sender: TObject);
procedure rgpAccommodationClick(Sender: TObject);
procedure bmbResetClick(Sender: TObject);
function GetFinalPriceWithVAT : real;
function toString : string;
const
vatRate = 0.15;
private
{ Private declarations }
objGeneralRetrieval:TGenRet;
sDBName,sDBMail,sDBID,sDBPhone,sDBBirth:string;
iDBPeople:integer;
rTranPrice:real;
arrDestinations: array [0..5] of string;
arrDestPrice: array [0..5] of integer;
specialArray: array [1..10] of char;
procedure DatabasePrep;
procedure CasesForRadioGroups;
procedure Validations;
procedure ValidationForPeopleAmount;
procedure ValidationForID;
procedure ValidationForEmail;
procedure ValidationForName;
procedure ValidationForPhoneNum;
procedure ValidationForDOB;
procedure RadioCheck;
public
{ Public declarations }
iPeopleAmount:integer;
sBookName,sID,sPhoneNum,sEmail,sDOB,sDestName:string;
sClientNum:string;
sAccPrint,sTransportPrint,sTLP:string;
rPrelimPrice:real;
rPriceWithVAT:real;
rPrice:real;
end;
var
frmTourBooking: TfrmTourBooking;
implementation
{$R *.dfm}
//this button resets the form
procedure TfrmTourBooking.bmbResetClick(Sender: TObject);
begin
//re-disable the radiogroups
rgpTourLength.Enabled:=False;
rgpTransport.Enabled:=False;
rgpAccommodation.Enabled:=False;
//reset the inputs
edtID.Clear;
dtpTime.Date:=Date;
edtName.Clear;
edtPhoneNum.Clear;
edtEmail.Clear;
rgpDestination.ItemIndex:= -1;
rgpAccommodation.ItemIndex:= -1;
rgpTransport.ItemIndex:= -1;
rgpTourLength.ItemIndex:= -1;
sedPeopleAmount.Value:= 0;
//clear the output
redOut.Clear;
end;
//this button calculates everything and gives an output afterwards
procedure TfrmTourBooking.btnCalcClick(Sender: TObject);
begin
Validations;
CasesForRadioGroups;
redOut.lines.Add(toString);
DatabasePrep;
end;
//validates all the inputs
procedure TfrmTourBooking.Validations;
begin
//people amount check
ValidationForPeopleAmount;
//ID check
ValidationForID;
//Email check
ValidationForEmail;
//Name check
ValidationForName;
//phone number check
ValidationForPhoneNum;
//DOB check
ValidationForDOB;
//if none of the options on the radio groups are checked
RadioCheck;
end;
//the seperate validation procedures
procedure TfrmTourBooking.ValidationForPeopleAmount;
begin
if (sedPeopleAmount.Value < 1) then
begin
ShowMessage('Error: please enter a valid amount of people going on the tour');
//disable the radiogroups
rgpTourLength.Enabled := False;
rgpTransport.Enabled := False;
rgpAccommodation.Enabled := False;
//reset the inputs
edtID.Clear;
edtName.Clear;
edtPhoneNum.Clear;
edtEmail.Clear;
dtpTime.Date:=Date;
rgpDestination.ItemIndex := -1;
rgpAccommodation.ItemIndex := -1;
rgpTransport.ItemIndex := -1;
rgpTourLength.ItemIndex := -1;
sedPeopleAmount.Value := 0;
//clear the output
redOut.Clear;
end;
if (sedPeopleAmount.Value > 30) then
begin
ShowMessage('Error: please enter a valid amount of people going on the tour');
//disable the radiogroups
rgpTourLength.Enabled := False;
rgpTransport.Enabled := False;
rgpAccommodation.Enabled := False;
//reset the inputs
edtID.Clear;
edtName.Clear;
edtPhoneNum.Clear;
edtEmail.Clear;
rgpDestination.ItemIndex := -1;
rgpAccommodation.ItemIndex := -1;
rgpTransport.ItemIndex := -1;
rgpTourLength.ItemIndex := -1;
sedPeopleAmount.Value := 0;
//clear the output
redOut.Clear;
end;
end;
procedure TfrmTourBooking.ValidationForID;
var
iIDLength: integer;
c:char;
i: Integer;
begin
iIDLength := Length(edtID.Text);
//array of special characters
specialArray[1]:= '@';
specialArray[2]:= '!';
specialArray[3]:= '#';
specialArray[4]:= '$';
specialArray[5]:= '%';
specialArray[6]:= '^';
specialArray[7]:= '&';
specialArray[8]:= '*';
specialArray[9]:= '(';
specialArray[10]:= ')';
//end of array
if (iIDLength = 13) then
begin
for c in sID do
begin
for i := 1 to 10 do
begin
if c = specialArray[i] then
begin
ShowMessage('Error: invalid format');
//disable the radiogroups
rgpTourLength.Enabled := False;
rgpTransport.Enabled := False;
rgpAccommodation.Enabled := False;
//reset the inputs
edtID.Clear;
edtName.Clear;
edtPhoneNum.Clear;
edtEmail.Clear;
rgpDestination.ItemIndex := -1;
rgpAccommodation.ItemIndex := -1;
rgpTransport.ItemIndex := -1;
rgpTourLength.ItemIndex := -1;
sedPeopleAmount.Value := 0;
//clear the output
redOut.Clear;
end;
end;
end;
end;
end;
procedure TfrmTourBooking.ValidationForEmail;
begin
end;
procedure TfrmTourBooking.ValidationForName;
begin
end;
procedure TfrmTourBooking.ValidationForPhoneNum;
begin
end;
procedure TfrmTourBooking.ValidationForDOB;
begin
end;
procedure TfrmTourBooking.RadioCheck;
begin
end;
//end of validation procedures
//outputs everything to the rich edit
function TfrmTourBooking.toString : string;
var
firstLine,secondLine,thirdLine,fourthLine,fifthLine:string;
output:string;
begin
iPeopleAmount:= sedPeopleAmount.Value;
sEmail:=edtEmail.Text;
sDOB:=DateToStr(dtpTime.Date);
sBookName:=edtName.Text;
sID:=edtID.Text;
sPhoneNum:=edtPhoneNum.Text;
rPrice:= GetFinalPriceWithVAT;
firstLine:= 'QUOTATION FOR: '+ sClientNum + #13+#13+'Amount of people going on the tour: '+ IntToStr(iPeopleAmount) + #13 + #13 ;
secondLine:='CLIENT DETAILS: '+ #13 + 'Name of booker: '+ sBookName + #13 + 'DOB: ' + sDOB + #13 + 'ID number: '+ sID + #13 + 'Contact Number: '+ sPhoneNum +#13+ 'Email: '+ sEmail + #13 + #13;
thirdLine:= 'TOUR DETAILS: ' + #13 + 'Destination: ' + sDestName + #13 + 'Tour Length: '+ sTLP +#13+ 'Transport type: ' + sTransportPrint + #13 + 'Accomodation: '+ sAccPrint + #13 + #13;
fourthLine:= 'PRICING: ' + #13 + FloatToStrF(rPrice,ffCurrency,6,2)+ #13;
fifthLine:= #13 + '©The Travel Agency 2020';
output:= firstLine + secondLine + thirdLine + fourthLine + fifthLine;
Result:= output;
end;
//this procedure is to handle the nitty gritty of the database input
procedure TfrmTourBooking.DatabasePrep;
begin
//create the object
objGeneralRetrieval := TGenRet.Create(edtName.Text, edtID.Text, edtPhoneNum.Text, sedPeopleAmount.Value, edtEmail.Text);
//get variables for db input from object
sDBName:=objGeneralRetrieval.GetName;
sDBID:=objGeneralRetrieval.GetID;
sDBMail:=objGeneralRetrieval.GetEmail;
sDBPhone:=objGeneralRetrieval.GetPhoneNum;
iDBPeople:=objGeneralRetrieval.GetPeopleAmount;
sDBBirth:=sDOB;
sClientNum := AnsiUpperCase(objGeneralRetrieval.GetClientNum);
//destroy object when done
objGeneralRetrieval.Free;
end;
//this procedure is for the multiple radio groups' outcomes
procedure TfrmTourBooking.CasesForRadioGroups;
var
iBasePrice: Integer;
rMultiplied: Real;
rAdded: Real;
begin
iBasePrice:=0;
rMultiplied:=0;
rAdded:=0;
//the starting prices
arrDestPrice[1]:=4000;
arrDestPrice[2]:=5000;
arrDestPrice[3]:=2500;
arrDestPrice[4]:=3000;
arrDestPrice[5]:=1950;
//when you choose the destination
case (rgpDestination.ItemIndex) of
0:
begin
iBasePrice := arrDestPrice[1];
sDestName := arrDestinations[1];
end;
1:
begin
iBasePrice := arrDestPrice[2];
sDestName := arrDestinations[2];
end;
2:
begin
iBasePrice := arrDestPrice[3];
sDestName := arrDestinations[3];
end;
3:
begin
iBasePrice := arrDestPrice[4];
sDestName := arrDestinations[4];
end;
4:
begin
iBasePrice := arrDestPrice[5];
sDestName := arrDestinations[5];
end;
end;
//When you choose the length of the tour
case (rgpTourLength.ItemIndex) of
0:
begin
rMultiplied := (iBasePrice * 1.5);
sTLP:='3 days';
end;
1:
begin
rMultiplied := (iBasePrice * 2);
sTLP:='5 days';
end;
2:
begin
rMultiplied := (iBasePrice * 2.5);
sTLP:='7 days';
end;
end;
//When you choose the accommodation
case (rgpAccommodation.ItemIndex) of
0:
begin
rAdded := 1500;
sAccPrint:='Hotel';
end;
1:
begin
rAdded := 850;
sAccPrint:='Guesthouse';
end;
2:
begin
rAdded := 0;
sAccPrint:='Own Accommodation';
end;
end;
//When you choose a mode of transport
case (rgpTransport.ItemIndex) of
0:
begin
rTranPrice := 1000;
sTransportPrint:='Bus';
end;
1:
begin
rTranPrice := 3000;
sTransportPrint:='Flight';
end;
2:
begin
rTranPrice := 0;
sTransportPrint:='Own Transport';
end;
end;
rPrelimPrice:= (rMultiplied + rAdded + rTranPrice) * iPeopleAmount;
end;
//to calculate the final price with VAT
function TfrmTourBooking.GetFinalPriceWithVAT : real;
var
vat:real;
begin
vat:= rPrelimPrice * vatRate;
rPriceWithVAT := vat + rPrelimPrice;
Result:= rPriceWithVAT;
end;
//this is when the form starts
procedure TfrmTourBooking.FormActivate(Sender: TObject);
begin
//disable other radio groups than destination at startup
rgpTourLength.Enabled:=False;
rgpAccommodation.Enabled:=False;
rgpTransport.Enabled:=False;
//array initialize
arrDestinations[1]:='Cape Town';
arrDestinations[2]:='Camps Bay';
arrDestinations[3]:='Mossel Bay';
arrDestinations[4]:='Knysna';
arrDestinations[5]:='Oudtshoorn';
//end of array initialize
end;
//these are to disable the radio groups until the previous group is clicked
procedure TfrmTourBooking.rgpAccommodationClick(Sender: TObject);
begin
rgpTransport.Enabled:=True;
end;
procedure TfrmTourBooking.rgpDestinationClick(Sender: TObject);
begin
rgpTourLength.Enabled:=True;
end;
procedure TfrmTourBooking.rgpTourLengthClick(Sender: TObject);
begin
rgpAccommodation.Enabled:=True;
end;
end.
Run Code Online (Sandbox Code Playgroud)
让我们看看您的按钮单击处理程序,它负责填充 Rich Edit 控件:
procedure TfrmTourBooking.btnCalcClick(Sender: TObject);
begin
Validations;
CasesForRadioGroups;
redOut.lines.Add(toString);
DatabasePrep;
end;
Run Code Online (Sandbox Code Playgroud)
如果您查看toString创建输出的方法,您会发现它使用了公共sClientNum字段。
你什么时候真正设置这个变量?它只设置一次,在DatabasePrep. 所以在你运行之前DatabasePrep,这个字符串将是空字符串(因为类字段总是被初始化)。
那么,你DatabasePrep什么时候打电话?你只把它在btnCalcClick,但你已经填充了丰富的编辑控制后,才。
因此,第一次单击按钮时,您将获得带有空字符串的输出,第二次您将获得完整的输出。
您的代码中还有其他问题:
每次创建对象时,都必须对其进行保护以避免内存泄漏:
procedure TfrmTourBooking.DatabasePrep;
begin
objGeneralRetrieval := TGenRet.Create(edtName.Text, edtID.Text, edtPhoneNum.Text, sedPeopleAmount.Value, edtEmail.Text);
try
sDBName := objGeneralRetrieval.GetName;
sDBID := objGeneralRetrieval.GetID;
sDBMail := objGeneralRetrieval.GetEmail;
sDBPhone := objGeneralRetrieval.GetPhoneNum;
iDBPeople := objGeneralRetrieval.GetPeopleAmount;
sDBBirth := sDOB;
sClientNum := AnsiUpperCase(objGeneralRetrieval.GetClientNum);
finally
objGeneralRetrieval.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
该objGeneralRetrieval变量仅在 中使用DatabasePrep,因此它应该是那里的局部变量。这是危险的把它作为一类领域,特别是因为这将是一个悬摆指针你释放对象之后没有设置指针nil。
在 Microsoft Windows 平台上,换行顺序为 CRLF:#13#10
其他一些提示:
specialArray 应该是一个常数,而不是一个变量:
const
SpecialChars: array[1..10] of Char = '@!#$%^&*()';
Run Code Online (Sandbox Code Playgroud)
当你迭代这个数组时,你做for i := 1 to 10 do. 但是如果你添加了一个新的特殊字符而忘记更新这个for循环行怎么办?最好做for i := Low(SpecialChars) to High(SpecialChars)。使用for..in循环更好。
这段代码:
case (rgpDestination.ItemIndex) of
0:
begin
iBasePrice := arrDestPrice[1];
sDestName := arrDestinations[1];
end;
1:
begin
iBasePrice := arrDestPrice[2];
sDestName := arrDestinations[2];
end;
2:
begin
iBasePrice := arrDestPrice[3];
sDestName := arrDestinations[3];
end;
3:
begin
iBasePrice := arrDestPrice[4];
sDestName := arrDestinations[4];
end;
4:
begin
iBasePrice := arrDestPrice[5];
sDestName := arrDestinations[5];
end;
end;
Run Code Online (Sandbox Code Playgroud)
可以写得更简洁:
if rgpDestination.ItemIndex <> -1 then
begin
iBasePrice := arrDestPrice[rgpDestination.ItemIndex + 1];
sDestName := arrDestinations[rgpDestination.ItemIndex + 1];
end;
Run Code Online (Sandbox Code Playgroud)
更少的代码更容易阅读和推理。减少愚蠢错别字的风险。
| 归档时间: |
|
| 查看次数: |
441 次 |
| 最近记录: |