你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 网络与通信
怎样利用局域网在大屏幕上显示体育比赛成绩
 

随着中国申奥成功,我国许多大中城市都在建设自己的体育中心(或体育场)。应当说这些场和馆的许多设计和设施,起点都是很高的。比如新落成的四万座“烟台中心体育场”,不仅有自己独立的局域网、大屏幕显示,而且有先进的“田、径”比赛记分的裁判系统。这些硬件设施,施工时往往是各大公司各自完成,所以整个工程完工后,如何使这些硬件用软件联系起来,使之协调工作,这就是体育中心自己的事了。本文的作者,自始至终参入了这项工作,略有所得,也走过一些弯路,现把成功的东西写下来,愿与同行交流。

烟台中心体育场的硬件系统框图如下:

   记分裁判系统              局域网                   大屏幕显示系统

 

(由深圳菲普公司提供) (由广东信息工程施工) (由北京利亚德施工)

 

 

 

图一中,记分裁判系统、大屏幕显示系统的软件部分都是自己本公司开发的。(记分裁判系统平台是WindowsNT;大屏幕显示系统平台是Windows98),两者连接的中心环节硬件则是局域网,软件需自己编写。

本文作者用Delphi5Windows2K平台编写,已调试通过。具体做法如下:

1.按图2设计界面。

 

 

 

图二中使用了Delphi中两个重要组件,ServerSoket ClientSoket 。这两个组件位于VCL面板的 Internet 页上。它们是 Delphi 为实现 TCP/IP 协议,封装了 Windows 提供的一组名为 WinSock API函数。所以设计者不必知道TCP/IP 的细节,只要简单的说明:

Host  - 服务器的域名;

Address - 服务器的IP地址;(在运行时确定)

Port  - 指定应用程序使用的端口;(在设计时确定)

Service  - 服务器名称字符串,

就可以了。

   图二界面全部程序如下:

  unit main;

interface

uses

  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

  Menus, StdCtrls, Buttons, ScktComp, ExtCtrls, ComCtrls;

type

  TChatForm = class(TForm)

    MainMenu1: TMainMenu;

    File1: TMenuItem;

    Exit1: TMenuItem;

    FileConnectItem: TMenuItem;

    FileListenItem: TMenuItem;

    StatusBar1: TStatusBar;

    Bevel1: TBevel;

    Panel1: TPanel;

    Memo1: TMemo;

    Memo2: TMemo;

    N1: TMenuItem;

    SpeedButton1: TSpeedButton;

    Disconnect1: TMenuItem;

    ServerSocket: TServerSocket;

    ClientSocket: TClientSocket;

    BitBtn1: TBitBtn;

    procedure FileListenItemClick(Sender: TObject);

    procedure FileConnectItemClick(Sender: TObject);

    procedure Exit1Click(Sender: TObject);

    procedure Memo1KeyDown(Sender: TObject; var Key: Word;

      Shift: TShiftState);

    procedure FormCreate(Sender: TObject);

    procedure ServerSocketError(Sender: TObject; Number: Smallint;

      var Description: string; Scode: Integer; const Source,

      HelpFile: string; HelpContext: Integer; var CancelDisplay: Wordbool);

    procedure Disconnect1Click(Sender: TObject);

    procedure ClientSocketConnect(Sender: TObject;

      Socket: TCustomWinSocket);

    procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);

    procedure ServerSocketClientRead(Sender: TObject;

      Socket: TCustomWinSocket);

    procedure ServerSocketAccept(Sender: TObject;

      Socket: TCustomWinSocket);

    procedure ServerSocketClientConnect(Sender: TObject;

      Socket: TCustomWinSocket);

    procedure ClientSocketDisconnect(Sender: TObject;

      Socket: TCustomWinSocket);

    procedure ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;

      ErrorEvent: TErrorEvent; var ErrorCode: Integer);

    procedure ServerSocketClientDisconnect(Sender: TObject;

      Socket: TCustomWinSocket);

    procedure BitBtn1Click(Sender: TObject);

  protected

    IsServer: Boolean;

  end;

var

  ChatForm: TChatForm;

  Server: String;

implementation

uses Unit1;

{$R *.DFM}

procedure TChatForm.FileListenItemClick(Sender: TObject);

begin

  FileListenItem.Checked := not FileListenItem.Checked;

  if FileListenItem.Checked then

  begin

    ClientSocket.Active := False;

    ServerSocket.Active := True;

    Statusbar1.Panels[0].Text := 'Listening...';

  end

  else

  begin

    if ServerSocket.Active then

      ServerSocket.Active := False;

    Statusbar1.Panels[0].Text := '';

  end;

end;

procedure TChatForm.FileConnectItemClick(Sender: TObject);

begin

  if ClientSocket.Active then ClientSocket.Active := False;

  if InputQuery('Computer to connect to', 'Address Name:', Server) then

    if Length(Server) > 0 then

      with ClientSocket do

      begin

        Host := Server;

        Active := True;

        FileListenItem.Checked := False;

      end;

end;

procedure TChatForm.Exit1Click(Sender: TObject);

begin

  ServerSocket.Close;

  ClientSocket.Close;

  Close;

end;

procedure TChatForm.Memo1KeyDown(Sender: TObject; var Key: Word;

  Shift: TShiftState);

begin

  if Key = VK_Return then

    if IsServer then

      ServerSocket.Socket.Connections[0].SendText(Memo1.Lines[Memo1.Lines.Count - 1])

    else

      ClientSocket.Socket.SendText(Memo1.Lines[Memo1.Lines.Count - 1]);

end;

 

procedure TChatForm.FormCreate(Sender: TObject);

begin

  FileListenItemClick(nil);

end;

procedure TChatForm.ServerSocketError(Sender: TObject; Number: Smallint;

  var Description: string; Scode: Integer; const Source, HelpFile: string;

  HelpContext: Integer; var CancelDisplay: Wordbool);

begin

  ShowMessage(Description);

end;

procedure TChatForm.Disconnect1Click(Sender: TObject);

begin

  ClientSocket.Active := False;

  ServerSocket.Active := True;

  Statusbar1.Panels[0].Text := 'Listening...';

end;

procedure TChatForm.ClientSocketConnect(Sender: TObject;

  Socket: TCustomWinSocket);

begin

  Statusbar1.Panels[0].Text := 'Connected to: ' + Socket.RemoteHost;

end;

procedure TChatForm.ClientSocketRead(Sender: TObject;

  Socket: TCustomWinSocket);

begin

  Memo2.Lines.Add(Socket.ReceiveText);

end;

procedure TChatForm.ServerSocketClientRead(Sender: TObject;

  Socket: TCustomWinSocket);

begin

  Memo2.Lines.Add(Socket.ReceiveText);

end;

procedure TChatForm.ServerSocketAccept(Sender: TObject;

  Socket: TCustomWinSocket);

begin

  IsServer := True;

  Statusbar1.Panels[0].Text := 'Connected to: ' + Socket.RemoteAddress;

end;

procedure TChatForm.ServerSocketClientConnect(Sender: TObject;

  Socket: TCustomWinSocket);

begin

  Memo2.Lines.Clear;

end;

procedure TChatForm.ClientSocketDisconnect(Sender: TObject;

  Socket: TCustomWinSocket);

begin

  FileListenItemClick(nil);

end;

procedure TChatForm.ClientSocketError(Sender: TObject;

  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;

  var ErrorCode: Integer);

begin

  Memo2.Lines.Add('Error connecting to : ' + Server);

  ErrorCode := 0;

end;

procedure TChatForm.ServerSocketClientDisconnect(Sender: TObject;

  Socket: TCustomWinSocket);

begin

  Statusbar1.Panels[0].Text := 'Listening...';

end;

procedure TChatForm.BitBtn1Click(Sender: TObject);

begin

   form1.show;

end;

end.

2.代码重点部分说明

ServerSocket ClientSocket 有一个共同的属性 Active,它用来控制组件是否处于工作状态。当ServerSocket 设置为True ,服务器端开始监听是否有客户要与之连接。当ClintSocket 设置为True,客户端准备与服务器端连接。在上述代码中:

procedure TChatForm.FileListenItemClick(Sender: TObject);

begin

  FileListenItem.Checked := not FileListenItem.Checked;

  if FileListenItem.Checked then

  begin

    ClientSocket.Active := False;

    ServerSocket.Active := True;

    Statusbar1.Panels[0].Text := 'Listening...';

  end

  else

  begin

    if ServerSocket.Active then

      ServerSocket.Active := False;

    Statusbar1.Panels[0].Text := '';

  end;

end;

   是这样的:

   如果Listen菜单有复选标记,用户单击它后取消复选标记,关闭服务器,打开客户端,将这个窗口作为客户程序来运行。如果Listen菜单没有复选标记,用户单击它后标上复选标记,打开服务器,关闭客户端,将这个窗口作为服务器程序来运行。同时界面状态栏的文字,提醒用户处于的状态。

   以下代码:

   procedure TChatForm.FileConnectItemClick(Sender: TObject);

begin

  if ClientSocket.Active then ClientSocket.Active := False;

  if InputQuery('Computer to connect to', 'Address Name:', Server) then

    if Length(Server) > 0 then

      with ClientSocket do

      begin

        Host := Server;

        Active := True;

        FileListenItem.Checked := False;

      end;

end;

的作用是这样的:

这个菜单项被触发时,首先关闭 ClientSocket 。然后调用 InputQuery 函数,询问用户要连接服务器的IP地址,用户正确输入后,将新的IP值付给 ClientSocket Address Name 属性,同时设置 Active True ,让它用新的IP地址与指定的服务器连接。

 

3.图二界面的作用

   记分裁判系统送出的比赛数据,是按标准 IP/TCP 格式- START,……,END ”送出的。下面是一组具体的例子:

    START,男子组100米决赛1组,4,1,4,90029,刘子雨,,11.22,2,6,90028,刘英力,,11.43,3,3,90032,刘英男,,11.49,4,5,90019,周淑华,,11.57,END        

 上面各组数据是用“,”分开的,它们是这样约定的:

第一个分号前,“ START ”                  格式头

第二个分号前,“ 男子组100米决赛1组 ”   组别

      第三个分号前,“ 4 ”                      参加人数

第四个分号前,“ 1 ”                   第一名

第五个分号前,“ 4 ”                   第一名所在跑道

第六个分号前,“ 90029 ”               第一名编号

第七个分号前,“ 刘子雨 ”              第一名姓名

第九个分号前,“ 11.22 ”                第一名成绩 (注:前面夹一分号)

第十个分号前,“ 6 ”                   第二名所在跑道

       .

.

.

        (共四组这样的数据)

END                                        格式尾

 

按装在大屏幕主机上“ 界面二”,用菜单项 “ Listen ” 置为监听状态,做服务器端;按装在裁判系统主机上“ 界面二”,用菜单项 “Listen ”置为客户机状态,做客户端。并随时准备与“ 连接键”联用,给出 IP 地址,与服务器连接。

界面二中 Memo2 的是为接受裁判系统送来的数据而设计的。它的WordWrap 属性为 False 。这样它接受到数据,无论多长,它都是一行数据。这为以后从Memo2剥离数据打下基础。

至于界面二中的其他组件,读者看一下程序,不需赘述自明。

4.剥离数据的中间界面

    前面我们说过,裁判系统送来的是一组“ START …… END ”数据,它里面除了我们有用的数据外,还有一些格式分界用的代码,象“START”;“END”;“,” 等等。我们必须从“ START …… END ”数据中,分离出我们所要显示的数据。而不必理会不需显示的数据。下面“图 三”即是为这个目的而设计的。

                      

 

 

按一下“模拟”键(这是为调机设计的),会触发 OpenDaiglog1 对话框,询问输入“ START …… END ”数据(本文电子版提供两组这样的数据,调试者可事先复制到机器的一个目录中)。当完成OpenDaiglog1 对话框操作后,会在图二的 Memo2 中出现这组数据。

当再按“显示”键时,程序会要分两步走:

★:第一步,将图三显示成“图四”

 

图 四

  从上图中可以看出,Memo2 的每一行是以“,”为“断点”,阶梯式显示 START …… END ”内容。Memo3 的每一行,是对应 Memo2 最后一个“,”所在的位置(左第一个为“1”)。Memo4 是已剥离出带“,”的数据。

 

完成以上功能,只需以下代码:

procedure TForm1.BitBtn1Click(Sender: TObject);

 var

      s,s1,s2:string;

      i,j,m,n,k,g:integer;

 

begin

      s:=chatform.memo2.Text ;

       j:=length(s);

       for i:=1 to j do

       begin

         if s[i]=',' then

         begin

          s1:=copy(s,-i,i);

           j:=length(s1);

           memo2.Lines .add(s1);

            memo3.Lines .add(inttostr(j));

           end ;

           end ;

             for  g:=0  to memo3.Lines.Count-2   do

             begin

            m:= strtoint(trim(memo3.lines[g]));

 

            n:= strtoint(trim(memo3.lines[g+1]));

            k:=n-m;

            memo4.Lines.add(copy(memo2.Lines [g+1],m,k)) ;

            end;

 

为了最终将比赛成绩,在Memo2Memo3Memo4 上覆盖了一个 panel1 如图五 (运行是时,实际看不到Memo2Memo3Memo4的内容)

 

 

图 五

     :第二步,将图五显示成图六。

 

 

图 六

以上两步的完整程序如下:

unit Unit1;

interface

uses

 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

  StdCtrls, ExtCtrls, Buttons;

type

  TForm1 = class(TForm)

    BitBtn1: TBitBtn;

    Edit1: TEdit;

    Memo4: TMemo;

    Memo2: TMemo;

    Memo3: TMemo;

    Panel1: TPanel;

    Label9: TLabel;

    Label2: TLabel;

    Label30: TLabel;

    Label3: TLabel;

    Label14: TLabel;

    Label10: TLabel;

    Label11: TLabel;

    Label12: TLabel;

    Label13: TLabel;

    Label4: TLabel;

    Label5: TLabel;

    Label6: TLabel;

    Label7: TLabel;

    Label8: TLabel;

    Label19: TLabel;

    Label15: TLabel;

    Label16: TLabel;

    Label17: TLabel;

    Label18: TLabel;

    Label24: TLabel;

    Label23: TLabel;

    Label22: TLabel;

    Label27: TLabel;

    Label26: TLabel;

    Label25: TLabel;

    Label20: TLabel;

    Label21: TLabel;

    Label28: TLabel;

    Label29: TLabel;

    OpenDialog1: TOpenDialog;

    Button2: TButton;

    Label1: TLabel;

    Label31: TLabel;

    Label32: TLabel;

    procedure BitBtn1Click(Sender: TObject);

   // procedure Button1Click(Sender: TObject);

    procedure Button2Click(Sender: TObject);

    procedure Edit1DblClick(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;

var

  Form1: TForm1;

implementation

uses main;

{$R *.DFM}

procedure TForm1.BitBtn1Click(Sender: TObject);

 var

      s,s1,s2:string;

      i,j,m,n,k,g:integer;

begin

      s:=chatform.memo2.Text ;

       j:=length(s);

       for i:=1 to j do

       begin

         if s[i]=',' then

         begin

          s1:=copy(s,-i,i);

           j:=length(s1);

           memo2.Lines .add(s1);

            memo3.Lines .add(inttostr(j));

           end ;

           end ;

             for  g:=0  to memo3.Lines.Count-2   do

             begin

            m:= strtoint(trim(memo3.lines[g]));

            n:= strtoint(trim(memo3.lines[g+1]));

            k:=n-m;

            memo4.Lines.add(copy(memo2.Lines [g+1],m,k)) ;

            end;

            label2.Caption :=copy (memo4.Lines[2],2,60);   //类别

            label3.Caption :=copy (memo4.Lines[3],2,2);   //人数

            //label4.Caption :=copy (memo4.Lines[4],2,2);  //名次

            label5.Caption :=copy (memo4.Lines[5],2,2);  //跑道 -1

            label6.Caption :=copy (memo4.Lines[6],2,5);  //编号 -1

            label7.Caption :=copy (memo4.Lines[7],2,6);  //姓名 -1

            label8.Caption :=copy (memo4.Lines[9],2,6);  //成绩 -1

            label15.Caption :=copy (memo4.Lines[11],2,2);  //跑道 -2

            label16.Caption :=copy (memo4.Lines[12],2,5);  //编号 -2

            label17.Caption :=copy (memo4.Lines[13],2,6);  //姓名 -2

            label18.Caption :=copy (memo4.Lines[15],2,6);  //成绩 -2

            label21.Caption :=copy (memo4.Lines[17],2,2);  //跑道 -3

            label22.Caption :=copy (memo4.Lines[18],2,5);  //编号 -3

            label23.Caption :=copy (memo4.Lines[19],2,6);  //姓名 -3

            label24.Caption :=copy (memo4.Lines[21],2,6);  //成绩 -3

            label26.Caption :=copy (memo4.Lines[23],2,2);  //跑道 -4

            label27.Caption :=copy (memo4.Lines[24],2,5);  //编号 -4

            label28.Caption :=copy (memo4.Lines[25],2,6);  //姓名 -4

            label29.Caption :=copy (memo4.Lines[27],2,6);  //成绩 -4

           panel1.Visible :=true;

 end;

procedure TForm1.Button2Click(Sender: TObject);

var

  F: Textfile;

  S:string;

begin

    memo2.Lines.Clear ;

    memo2.Lines.Add('0');

    memo3.Lines.Clear ;

    memo3.Lines.Add('0');

    memo4.Lines.Clear ;

    memo4.Lines.Add('0');

  OpenDialog1.Execute;

   AssignFile(F, OpenDialog1.FileName);

    Reset(F);

    Readln(F, S);     { Read the first line out of the file }

   chatform.memo2.Text := S;   { Put string in a TEdit control }

    CloseFile(F);

end;

procedure TForm1.Edit1DblClick(Sender: TObject);

begin

   label1.Caption :=edit1.Text ;

end;

end.

procedure TForm1.Button1Click(Sender: TObject);

 var

  F: Textfile;

  S:string;

begin

    memo2.Lines.Clear ;

    memo2.Lines.Add('0');

    memo3.Lines.Clear ;

    memo3.Lines.Add('0');

    memo4.Lines.Clear ;

    memo4.Lines.Add('0');

  OpenDialog1.Execute;

   AssignFile(F, OpenDialog1.FileName);

    Reset(F);

    Readln(F, S);   { Read the first line out of the file }

   form1.memo2.Text := S;     { Put string in a TEdit control }

    CloseFile(F);

end;

end.

最后应当说明的是,我们所设计的界面二,不但可以显示体育比赛成绩,还可以在比赛中,随时与有联系的其他客户端通信,这些读者稍看一下程序,很容易看出。
  推荐精品文章

·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录
·2023年10月目录
·2023年9月目录 
·2023年8月目录 
·2023年7月目录
·2023年6月目录 
·2023年5月目录
·2023年4月目录 
·2023年3月目录 
·2023年2月目录 
·2023年1月目录 

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089