• 教程三 在Go中使用Energy创建跨平台应用 - 状态控制


    教程-示例-文档


    本文介绍在Energy中如何像浏览器一样控制状态, 页面的加载、前进、后退、刷新、暂停刷新

    前提-需要安装好开发环境参考: 教程一 环境安装

    创建应用

    • 开发环境中 MacOSX平台必须在"GlobalCEFInit"之前设置CEF
    • 设置使用CEF 和 CEF框架目录,生成开发执行应用程序包
      • macapp.MacApp.IsCEF(common.IsDarwin())
    • 全局初始化 每个应用都必须调用的
      • cef.GlobalCEFInit(&libs, &resources)
    • 可选的应用配置
      • cfg := cef.NewApplicationConfig()
    • 指定chromium的二进制包框架根目录, 不指定为当前程序执行目录
      • 环境变量ENERGY_HOME="/app/cefframework" 配置框架所在目录

        if common.IsWindows() {
            //SetFrameworkDirPath 或 配置环境变量 ENERGY_HOME
            //cfg.SetFrameworkDirPath("D:\\app.exe\\energy\\chromium64")
        } else if common.IsLinux() {
            //cfg.SetFrameworkDirPath("/home/sxm/app/swt/energy/chromium")
        }

    • 创建应用
      • cef.NewApplication(cfg)
    • 主进程窗口初始化函数
      • src.MainBrowserWindow()

    1. package main
    2. import (
    3. "embed"
    4. "github.com/energye/energy/cef"
    5. "github.com/energye/energy/common"
    6. "github.com/energye/energy/example/browser-control/src"
    7. "github.com/energye/golcl/pkgs/macapp"
    8. )
    9. //go:embed resources
    10. var resources embed.FS
    11. //go:embed libs
    12. var libs embed.FS
    13. func main() {
    14. //开发环境中 MacOSX平台必须在"GlobalCEFInit"之前设置CEF
    15. //设置使用CEF 和 CEF框架目录,生成开发执行应用程序包
    16. macapp.MacApp.IsCEF(common.IsDarwin())
    17. //环境变量 ENERGY_HOME="/app/cefframework" 配置框架所在目录
    18. //全局初始化 每个应用都必须调用的
    19. cef.GlobalCEFInit(&libs, &resources)
    20. //可选的应用配置
    21. cfg := cef.NewApplicationConfig()
    22. //指定chromium的二进制包框架根目录,
    23. //不指定为当前程序执行目录
    24. if common.IsWindows() {
    25. //SetFrameworkDirPath 或 配置环境变量 ENERGY_HOME
    26. //cfg.SetFrameworkDirPath("D:\\app.exe\\energy\\chromium64")
    27. } else if common.IsLinux() {
    28. //cfg.SetFrameworkDirPath("/home/sxm/app/swt/energy/chromium")
    29. }
    30. //创建应用
    31. cefApp := cef.NewApplication(cfg)
    32. //主进程窗口
    33. src.MainBrowserWindow()
    34. //运行应用
    35. cef.Run(cefApp)
    36. }

    系统UI和Energy

    使用系统组件 golcl 创建控制相关按钮

    初始主进程和窗口

    • 在非主进程中有些代码是不必执行的。通过IsMain函数判断是否为主进程
      • commons.Args.IsMain()
    • 使用主浏览器的配置属性对浏览器进行了简单的配置
      • cef.BrowserWindow.Config
    • 使用ChromiumConfig配置开启右键菜单和开发者工具
      • config.SetEnableMenu(true)
      • config.SetEnableDevTools(true)

    • 创建窗口时的回调函数 对浏览器事件设置,和窗口属性组件等创建和修改
    • cef.BrowserWindow.SetBrowserInit 窗口初始函数
    • 在窗口初始函数中
      • 设置更多的窗口属性
      • 窗口的事件
      • 浏览器的事件
    • cef.QueueAsyncCall 函数,在Linux中和操作UI相关的功能中,需要使用该函数包裹住,该函数会将被执行的函数移至主线程中执行。否则操作UI相关或Linux系统中会导致UI线程锁死
    • func controlUI 函数,在SetBrowserInit 函数中调用,主要创建主窗口内的系统UI组件
    1. package src
    2. import (
    3. "fmt"
    4. "github.com/energye/energy/cef"
    5. "github.com/energye/energy/common"
    6. "github.com/energye/golcl/lcl"
    7. "github.com/energye/golcl/lcl/types"
    8. )
    9. //主浏览器窗口
    10. func MainBrowserWindow() {
    11. //只有启动主进程才会继续执行
    12. if !common.Args.IsMain() {
    13. return
    14. }
    15. //主窗口的配置
    16. //指定一个URL地址,或本地html文件目录
    17. cef.BrowserWindow.Config.DefaultUrl = "https://energy.yanghy.cn/"
    18. //窗口的标题
    19. cef.BrowserWindow.Config.Title = "Energy - 浏览器控制"
    20. //窗口宽高
    21. cef.BrowserWindow.Config.Width = 1024
    22. cef.BrowserWindow.Config.Height = 768
    23. //chromium配置
    24. config := cef.NewChromiumConfig()
    25. config.SetEnableMenu(true)
    26. config.SetEnableDevTools(true)
    27. cef.BrowserWindow.Config.SetChromiumConfig(config)
    28. //创建窗口时的回调函数 对浏览器事件设置,和窗口属性组件等创建和修改
    29. cef.BrowserWindow.SetBrowserInit(func(event *cef.BrowserEvent, browserWindow *cef.TCefWindowInfo) {
    30. //设置应用图标 这里加载的图标是内置到执行程序里的资源文件
    31. lcl.Application.Icon().LoadFromFSFile("resources/icon.ico")
    32. //在窗体初始化时创建窗口内的组件
    33. back, forward, stop, refresh, progressLabel, addr := controlUI(browserWindow)
    34. //页面加载处理进度
    35. event.SetOnLoadingProgressChange(func(sender lcl.IObject, browser *cef.ICefBrowser, progress float64) {
    36. //linux 更新UI组件必须使用 QueueAsyncCall 主线程异步同步
    37. cef.QueueAsyncCall(func(id int) {
    38. //参数-进度
    39. progressLabel.SetCaption(fmt.Sprintf("%v", progress*100))
    40. })
    41. })
    42. //页面加载状态,根据状态判断是否加载完成,和是否可前进后退
    43. event.SetOnLoadingStateChange(func(sender lcl.IObject, browser *cef.ICefBrowser, isLoading, canGoBack, canGoForward bool) {
    44. //linux 更新UI组件必须使用 QueueAsyncCall 主线程异步同步
    45. cef.QueueAsyncCall(func(id int) {
    46. //控制按钮状态
    47. stop.SetEnabled(isLoading)
    48. refresh.SetEnabled(!isLoading)
    49. back.SetEnabled(canGoBack)
    50. forward.SetEnabled(canGoForward)
    51. })
    52. })
    53. event.SetOnAddressChange(func(sender lcl.IObject, browser *cef.ICefBrowser, frame *cef.ICefFrame, url string) {
    54. cef.QueueAsyncCall(func(id int) {
    55. addr.SetText(url)
    56. })
    57. })
    58. })
    59. //创建窗口之后对对主窗口的属性、组件或子窗口的创建
    60. cef.BrowserWindow.SetBrowserInitAfter(func(browserWindow *cef.TCefWindowInfo) {
    61. fmt.Println("SetBrowserInitAfter")
    62. })
    63. }
    64. //控制组件UI
    65. //地址栏和控制按钮创建
    66. func controlUI(browserWindow *cef.TCefWindowInfo) (goBack *lcl.TButton, goForward *lcl.TButton, stop *lcl.TButton, refresh *lcl.TButton, progressLabel *lcl.TLabel, addrBox *lcl.TComboBox) {
    67. window := browserWindow.Window
    68. //这里使用系统UI组件
    69. //创建panel做为地址栏的父组件
    70. addrPanel := lcl.NewPanel(window) //设置父组件
    71. addrPanel.SetParent(window)
    72. addrPanel.SetAnchors(types.NewSet(types.AkLeft, types.AkTop, types.AkRight)) //设置锚点定位,让宽高自动根据窗口调整大小
    73. addrPanel.SetHeight(25)
    74. addrPanel.SetWidth(window.Width())
    75. //创建 按钮-后退
    76. goBack = lcl.NewButton(addrPanel) //设置父组件
    77. goBack.SetParent(addrPanel)
    78. goBack.SetCaption("后退")
    79. goBack.SetBounds(0, 0, 35, 25)
    80. goForward = lcl.NewButton(addrPanel) //设置父组件
    81. goForward.SetParent(addrPanel)
    82. goForward.SetCaption("前进")
    83. goForward.SetBounds(35, 0, 35, 25)
    84. stop = lcl.NewButton(addrPanel) //设置父组件
    85. stop.SetParent(addrPanel)
    86. stop.SetCaption("停止")
    87. stop.SetBounds(35+35, 0, 35, 25)
    88. refresh = lcl.NewButton(addrPanel) //设置父组件
    89. refresh.SetParent(addrPanel)
    90. refresh.SetCaption("刷新")
    91. refresh.SetBounds(35+35+35, 0, 35, 25)
    92. //创建下拉框
    93. addrBox = lcl.NewComboBox(addrPanel)
    94. addrBox.SetParent(addrPanel)
    95. addrBox.SetLeft(35 + 35 + 35 + 35) //这里是设置左边距 上面按钮的宽度
    96. addrBox.SetWidth(window.Width() - (35 + 35 + 35 + 35 + 35 + 35)) //宽度 减按钮的宽度
    97. addrBox.SetAnchors(types.NewSet(types.AkLeft, types.AkTop, types.AkRight)) //设置锚点定位,让宽高自动根据窗口调整大小
    98. addrBox.Items().Add("https://energy.yanghy.cn")
    99. addrBox.Items().Add("https://www.baidu.com")
    100. //显示加载进度
    101. progressLabel = lcl.NewLabel(addrPanel) //设置父组件
    102. progressLabel.SetParent(addrPanel)
    103. progressLabel.SetCaption("0")
    104. progressLabel.SetBounds(window.Width()-(35+35)-10, 3, 35, 25)
    105. progressLabel.SetAnchors(types.NewSet(types.AkTop, types.AkRight)) //设置锚点定位,让宽高自动根据窗口调整大小
    106. goUrl := lcl.NewButton(addrPanel) //设置父组件
    107. goUrl.SetParent(addrPanel)
    108. goUrl.SetCaption("GO")
    109. goUrl.SetBounds(window.Width()-35, 0, 35, 25)
    110. goUrl.SetAnchors(types.NewSet(types.AkTop, types.AkRight)) //设置锚点定位,让宽高自动根据窗口调整大小
    111. //重新调整browser窗口的Parent属性
    112. //重新设置了上边距,宽,高
    113. window.WindowParent().SetAlign(types.AlNone) //重置对齐,默认是整个客户端
    114. window.WindowParent().SetTop(25)
    115. window.WindowParent().SetHeight(window.Height() - 25)
    116. window.WindowParent().SetWidth(window.Width())
    117. //设置锚点定位,让宽高自动根据窗口调整大小
    118. //因为窗口大小已调整,这里不能使用 SetAlign 了
    119. window.WindowParent().SetAnchors(types.NewSet(types.AkTop, types.AkLeft, types.AkRight, types.AkBottom))
    120. //给按钮增加事件
    121. goBack.SetOnClick(func(sender lcl.IObject) {
    122. browserWindow.Chromium().GoBack()
    123. })
    124. goForward.SetOnClick(func(sender lcl.IObject) {
    125. browserWindow.Chromium().GoForward()
    126. })
    127. stop.SetOnClick(func(sender lcl.IObject) {
    128. browserWindow.Chromium().StopLoad()
    129. })
    130. refresh.SetOnClick(func(sender lcl.IObject) {
    131. browserWindow.Chromium().Reload()
    132. })
    133. goUrl.SetOnClick(func(sender lcl.IObject) {
    134. var url = addrBox.Text()
    135. if url != "" {
    136. browserWindow.Chromium().LoadUrl(url)
    137. }
    138. })
    139. return
    140. }

    go run xx.go

    go build

    go build -ldflags “-H windowsgui -s -w”

    说明

    需要你自己下载编译好的框架二进制包,或使用energy命令行工具安装环境,参考教程CEF和Enregy使用
    这里面用到了系统UI组件

    1. 首先创建了应用,应用创建属于不管主进程还是渲染进程(子进程)都要执行的代码, 通过NewApplicationConfig配置应用参数,需要你使用(SetFrameworkDirPath)指定框架目录,如果执行文件在框架目录中,则不需要指定.
    2. 创建主窗口,在CEF中主窗口是主进程,UI的主进程,也是brower的主进程,大多数业务逻辑都要在该进程中实现
    3. 在主进程中创建了窗口组件,按钮控制组件,事件监听,窗口属性设置等等.

    控制事件

    在回调函数BrowserWindow.SetBrowserInit设置事件监听

    cef.BrowserWindow.SetBrowserInit(func(event *cef.BrowserEvent, browserWindow *cef.TCefWindowInfo)

    设置加载进度改变事件

    event.SetOnLoadingProgressChange(func(sender lcl.IObject, browser *cef.ICefBrowser, progress float64)

    设置页面加载状态事件

    event.SetOnLoadingStateChange(func(sender lcl.IObject, browser *cef.ICefBrowser, isLoading, canGoBack, canGoForward bool)

  • 相关阅读:
    存储资源盘活系统,“盘活”物联网架构难题(下)
    数据库系统原理与应用教程(076)—— MySQL 练习题:操作题 160-167(二十):综合练习
    (尚硅谷)2021 版 SpringMVC 教程笔记
    使用爬虫批量下载图片链接并去重
    栈在求值表达式中的应用
    使用宝塔部署项目
    GoJS 使用笔记
    新品上线 Naive Admin Tenant 开箱即用多租户开发框架
    Everything扫描非C盘
    【OpenGL】六、深度测试和模板测试
  • 原文地址:https://blog.csdn.net/snxamdf/article/details/128035515