(五)、其他窗体(Other Forms) :

使用uniGUI创建新窗体向导允许创建三种窗体:

  • 登录窗体 (Login Form 继承于TUniLoginForm)
  • 应用程序窗体(Application Form)
  • 自由窗体(Free Form)

应用程序窗体(Application Form)和自由窗体(Free Form) 有一些不同之处,请在下面子章节阅读时特别注意。

1)、应用程序窗体(Application Form)

下面创建一个应用程序窗体(Applicateion Form)后,系统自动生成的代码(已重命名):

unit _AppForm;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, uniGUITypes, uniGUIAbstractClasses,
  uniGUIClasses, uniGUIForm;
 
type
  TAppForm = class(TUniForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
function AppForm: TAppForm;
 
implementation
 
{$R *.dfm}
 
uses
  MainModule, uniGUIApplication;
 
function AppForm: TAppForm;
begin
    Result := TAppForm(UniMainModule.GetFormInstance(TAppForm));
end;
 
end.

而不是像下面这样的窗体变量(传统VCL窗体代码):

var
  AppForm : TAppForm;

上面是传统VCL窗体生成的标准代码,由向导生成了具有相同名称和类型的窗体变量。原始变量的作用域是全局的,但在Web多用户环境(会话)中毫无用处。UniGUI中的窗体函数从会话UniMainModule请求创建实例,自动将窗体本地化给每个对应的会话。该函数不但保留了VCL变量的原始意图和功能,而且每个会话还始终只能访问该窗体的一个对应实例(每个会话都是一个单例)。该函数很灵活,可以管理窗体的生命周期,具体如下:

  • 如果窗体不存在,它将创建窗体
  • 如果窗体被关闭,它将被释放,并从托管窗体列表中注销。(属性FreeOnClose = True)
  • 如果已经存在,则立即返回。

1.1)、使用应用程序窗体的全局函数

uniGUI窗体是动态对象,由UniGUI框架自动分配和配置它们。如上所述,每个uniGUI应用程序窗体都与一个函数相关联,该函数将创建或返回该窗体的实例。提供该函数的主要目的是提供VCL和uniGUI之间的语法兼容性。在传统VCL中,窗体是可以自动创建或手工创建的,自动创建时,所有的窗体全局变量都是在应用程序启动时启动的。在传统VCL中,你可以很容易地使用你的窗体,只需编写简单的语法:Form1.Show;

同样,在uniGUI中,我们提供了一个类似于上面的方便语法,允许您访问您的窗体:UniForm1.Show;

必须记住,在上面的代码中,UniForm1是一个函数,而不是一个窗体变量。它返回当前会话的正确窗体实例,如果还没有创建实例,它将自动创建一个新实例并返回给此调用函数。

特别强调一下:这个函数仅用于执行某些任务,它不应该被视为全局变量,因为它一开始就不是变量。这个全局函数仅仅只能在你想实例化和显示此窗体时使用,并且只能在同一事件中。

UniForm1.Caption := 'New Caption';   // 创建一个新的表单实例(赋值时系统会自动创建此窗体),并为标题分配一个新值

UniForm1.Show;                       // 接着在创建后立即调用Show函数,显示此窗体

另一个重要的细节是,必须在创建uniGUI窗体时立即显示它们。不能在一个事件中创建一个窗体,然后在另一个事件中显示它(这点与VCL不同)。如果您尝试这样做,uniGUI将会自动显示窗体,哪怕您没有显式地调用show或ShowModal,当然最好开发者自动显示窗体,而不应该让UniGUI来帮你“纠正”这个错误。
下面这样写是错误的或不规范的:

procedure TMainForm.UniButton4Click(Sender: TObject);
begin
    UniForm1.Caption := 'New Caption';
end;

正确的写法如下:

procedure TMainForm.UniButton4Click(Sender: TObject);
begin
    UniForm1.Caption := 'New Caption';
    UniForm1.Show;  //同一事件中必须要调用Show
end;

必须避免在数据模块(DataModule)中使用窗体实例,除非使用它创建和显示上面演示的窗体。您必须避免从DataModule或其他窗体访问窗体的公共变量。因为有这些都是违反良好OOP设计规则的。
       窗体不能用于存储应用程序全局变量或数据组件,例如供其他窗体使用的数据连接组件。必须将每个窗体视为应用程序的原子元素,应用程序将拥有自己的私有变量以供内部使用。如果要为会话定义公共变量,则必须放在为此目的定义主模块(MainModule)或其他MainModule(如:ServerModule或从MainModule类中继承出来的其他MainModule)。
       例如,在下面的代码中,窗体中的UniLabel用于显示字段数据。如上所述,必须避免这种形式的使用。

procedure TDataModule2.DataSource1DataChange(Sender: TObject; Field: TField);
begin
  UniForm1.UniLabel1.Caption := Field.DisplayText;  //窗体函数不应直接调用属于另一个窗体/模块的组件的事件处理程序中
end;

相反,您可以通过简单地使用数据感知控件(如TUniDBText)并将其连接到数据源来解决这个问题。如果想实现上述问题的功能,标准的解决方案是将TDataSource组件直接放在窗体上,并使用其OnDataChange事件来更新窗体的可视控件内容。这里的经验法则是避免从不属于该窗体的其他组件的事件处理程序更新窗体的可视元素。
      上述规则的唯一例外是,当您完全控制特定窗体的生存期时。也就是说,您显式地在自己的代码中创建和销毁它,也是可以这样做的(一般情况下,UniGUI不建议手工代码创建窗体或销毁窗体)。

2)、自由窗体(Free Form)

下面是创建一个自由窗体(Free Form)后,系统自动生成的代码(已重命名):

unit _FreeForm;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, uniGUITypes, uniGUIAbstractClasses,
  uniGUIClasses, uniGUIForm;
 
type
  TFreeForm = class(TUniForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
implementation
 
uses
  uniGUIApplication;
 
{$R *.dfm}
 
end.

这种自由窗体(Free Form)和应用程序窗体(Application Form)之间的主要区别是缺少窗体函数,相当于VCL全局变量。
更重要的区别是,用户可以通过自由窗体(Free Form),来完成下面应用程序窗体(Application Form)无法实现的事情:

  • 可以创建窗体的多个实例(举个例子:在屏幕上留下几个非模态窗体,显示数据集的不同记录)
  • 用户将对窗体生命周期有更严格的控制

下一个例子显示了相同的窗体,但经过修改以捕获文本作为模态窗体:

unit _FreeForm;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, uniGUITypes, uniGUIAbstractClasses,
  uniGUIClasses, uniGUIForm, uniButton, uniGUIBaseClasses, uniEdit;
 
type
  TFreeForm = class(TUniForm)
    edtText: TUniEdit;
    btnOk: TUniButton;
    btnCancel: TUniButton;
  private
    function GetText: string;
  public
    property Text : string read GetText;
  end;
 
  function GetText : string;
 
implementation
 
uses
  uniGUIApplication;
 
{$R *.dfm}
 
function GetText : string;
var
  frm : TFreeForm;
begin
  frm := TFreeForm.Create(uniGUIApplication.UniApplication);
 
  if frm.ShowModal = mrOk then
    Result := frm.Text
  else
    Result := ''; 
end;
 
{ TFreeForm }
 
function TFreeForm.GetText: string;
begin
  Result := edtText.Text;
end;
 
end.

自由窗体的所有者不是全局应用程序,而是处理当前会话的实例。
       还要注意:窗体(frm)是自动释放的(FreeOnClose为true,并会给窗体ModalResult分配一个值)。变量本身将在超出范围(当函数GetText执行完毕且退出后)后释放。
       当用户对GetText之类的服务感兴趣而不是对窗体感兴趣时,自由窗体(Free Form)非常方便。如果是这种情况,窗体将始终作为服务实现的一部分创建和运行,而不应该公开给程序的其他部分。因为程序所期望的只是服务。

【一起学UniGUI】--UniGUI的窗体和模块(7)相关推荐

  1. 【一起学UniGUI】--UniGUI的窗体和模块(6)

    每个uniGUI应用程序都是使用一个主窗体(MainForm)的专用窗体和两个专用的模块主模块(MainModule)和服务模块(ServerModule)组成且自动创建的.登录窗体(LoginFor ...

  2. 学成在线--媒资管理模块

    完整版请移步至我的个人博客查看:https://cyborg2077.github.io/ 学成在线–项目环境搭建 学成在线–内容管理模块 学成在线–媒资管理模块 学成在线–课程发布模块 学成在线–认 ...

  3. Sklearn 损失函数如何应用到_菜鸟学机器学习,Sklearn库主要模块功能简介

    导读 作为一名数据分析师,当我初次接触数据分析三剑客(numpy.pandas.matplotlib)时,感觉每个库的功能都很多很杂,所以在差不多理清了各模块功能后便相继推出了各自教程(文末附链接): ...

  4. 菜鸟学机器学习,Sklearn库主要模块功能简介

    导读 作为一名数据分析师,当我初次接触数据分析三剑客(numpy.pandas.matplotlib)时,感觉每个库的功能都很多很杂,所以在差不多理清了各模块功能后便相继推出了各自教程(文末附链接): ...

  5. ib课程计算机学什么,IB课程六大课程模块介绍

    原标题:IB课程六大课程模块介绍 IB即国际文凭组织IBO,成立于1968年,迄今为止遍布138个国家与2815个学校合作,学生数量超过77万.与A-level.VCE等课程并称全球四大高中课程体系. ...

  6. 零基础学Python(第十七章 模块import)

    本套学习内容共计[22]个章节,每个章节都会有对应的从0-1的学习过程详细讲解,希望可以给更多的人提供帮助. 开发环境:[Win10] 开发工具:[Visual Studio 2019] 本章内容为: ...

  7. 动手学深度学习-pytorch 导入d2lzh_pytorch模块时报错 No moudel named 'd2lzh_pytorch'

    运行以下代码将生成一个d2lzh_pytorch.py的文件,然后就可以正常导入了. 首先运行,如下代码.这个代码就是从github找到的d2lzh_pytorch的代码 import collect ...

  8. 《跟着小吴哥学python》之 08 python模块

    Python本身就内置了很多非常有用的模块,只要安装完毕,这些模块就可以立刻使用. 在Python中,安装第三方模块,是通过包管理工具pip完成的. 注意:Mac或Linux上有可能并存Python ...

  9. 【一起学UniGUI】--创建新的uniGUI应用程序(11)

    打开Delphi 10.3.1,在Delphi IDE中可以通过uniGUI应用程序向导轻松创建一个新的uniGUI应用程序(必须通过此方式来创建一个新的uniGUI应用程序),并按向导界面提示操作. ...

最新文章

  1. 如何确定最初克隆本地Git存储库的URL?
  2. JQuery Tab菜单的实现
  3. 为工厂分配用于公司间Invoice的销售范围
  4. 【小白学习keras教程】一、基于波士顿住房数据集训练简单的MLP回归模型
  5. 从操作系统的PV操作理解JAVA的synchronized同步方法,同步代码块实现,及比较
  6. 查询数据库中所有表的行数(sqlserver 2000)
  7. 321. Create Maximum Number 解题方法详解
  8. C#使用DataContractJsonSerializer来进行JSON解析
  9. 惯性制导精度是多少_美军激光炸弹真实精度性能:炸小卡车,直接从驾驶员车窗钻进去炸...
  10. pyqt5 qwidget 边框_实战PyQt5: 116-画刷类QBrush
  11. linux oracle异常处理,Oracle SQL 异常处理
  12. 为什么SQL用UPDATE语句更新时更新行数会多3行有触发器有触发器有触发器有触发器有触发器有触发器...
  13. [core java学习笔记][第十一章异常断言日志调试]
  14. 【c语言数学函数库】
  15. Behavior Designer 行为树中文版教程
  16. 江西省吉安市谷歌高清卫星地图下载
  17. c语言人民日报排版的代码,人民日报都在玩的排版黑科技,教你1分钟上手!
  18. 秋风荷桂香 晚风拂夕阳
  19. C++多线程技术--API
  20. python日期推算

热门文章

  1. it转正述职报告_it试用期转正工作总结范文
  2. 文本数据分析之中文酒店评论数据分析
  3. 使用CSS连接数据库
  4. 高斯模糊效果实现方案及性能对比
  5. STM32Cube中usart的使用
  6. Mac上效率软件推荐
  7. 【JavaScript 逆向】极验三代滑块验证码逆向分析
  8. 超详细的MySQL三万字总结
  9. Java项目:ssm医院管理系统
  10. python对象方法 反射