当前位置: 首页 > news >正文

网站建设的技术问题苏州吴江建设局招标网站

网站建设的技术问题,苏州吴江建设局招标网站,wordpress国外主题 雅黑,python做网站好不好项目开源地址 energy v2.0 系列, LCL 原生控件, CEFlcl v3.0 v3.0 系列为, LCL 原生控件, CEF, Webview2, Webkit2XTA SDK 源码分析 本文主要介绍 xtaui.go 是一个基于 LCL 框架的 Go 语言 GUI 应用程序的主文件。 它通过嵌入资源、初始化框架、创建主窗体并运行应用&#x…

项目开源地址

  • energy v2.0 系列, LCL 原生控件, CEF
  • lcl v3.0 v3.0 系列为, LCL 原生控件, CEF, Webview2, Webkit2
  • XTA SDK

源码分析

本文主要介绍 xtaui.go 是一个基于 LCL 框架的 Go 语言 GUI 应用程序的主文件。
它通过嵌入资源、初始化框架、创建主窗体并运行应用,实现了完整的程序生命周期管理。
本文从资源嵌入、初始化、异常处理、主窗体创建等方面对源码进行了详细分析。

1. 文件结构和包声明

源码文件为 xtaui.go,包声明为 main,表示这是一个可执行的 Go 程序。

2. 导入的包
  • embed: 用于嵌入静态资源文件。
  • fmt: 标准输出包,用于打印日志。
  • github.com/energye/lcl/initsgithub.com/energye/lcl/lcl: 这是 LCL(Light Controls Library)框架的包,用于创建跨平台的 GUI 应用。
  • xta/xtaui/window: 本地包,用于定义主窗口逻辑。
3. 嵌入资源
  • 使用 go:embed 指令嵌入了两个目录:
    • assets: 用于存放静态资源(如图片、配置文件等)。
    • libs: 用于存放动态链接库(如平台依赖的二进制文件)。
4. 主函数 (main())
  • 初始化资源: 调用 inits.Init(lib, resources),将嵌入的资源和库文件传递给 LCL 框架进行初始化。
  • 初始化应用: 调用 lcl.Application.Initialize(),初始化 LCL 框架。
  • 设置异常处理: 通过 SetOnException 方法设置全局异常处理函数,捕获并打印错误信息。
  • 设置主窗体: 调用 SetMainFormOnTaskBar(true),确保主窗体显示在任务栏中。
  • 创建和运行主窗体: 通过 CreateForm 创建主窗体(MainWindow),并调用 Run() 方法启动应用。

源码概述

xtaui.go 是一个基于 LCL 框架的 Go 语言 GUI 应用程序的主文件。它通过嵌入静态资源和动态链接库,初始化 LCL 框架,并创建和运行主窗口。


资源嵌入与初始化
  • 资源嵌入
    使用 go:embed 指令将 assetslibs 目录嵌入到可执行文件中。这种方式可以避免在运行时依赖外部文件,使程序更加 portable( portable,便于移植)。

  • 初始化流程

    1. 调用 inits.Init(lib, resources),将嵌入的资源传递给 LCL 框架。
    2. 调用 lcl.Application.Initialize(),完成 LCL 框架的初始化。

异常处理机制

通过 SetOnException 方法,程序全局捕获异常并打印错误信息。这种机制可以有效避免程序因未捕获的异常而崩溃,同时为调试提供日志支持。


主窗体的创建与运行
  • 创建主窗体
    调用 lcl.Application.CreateForm(&window.MainWindow) 创建主窗体。MainWindow 是从本地包 xta/xtaui/window 中导入的结构体,用于定义窗体的外观和行为。

  • 运行应用
    调用 lcl.Application.Run() 启动应用程序,进入消息循环,处理用户交互。


LCL 框架简介

LCL是一个跨平台的 GUI 开发框架,支持 Windows、Linux 和 macOS 操作系统。通过 LCL,开发者可以使用 Go 语言快速构建功能丰富的桌面应用。


示例截图
程序文件大小

执行文件: 15M
压缩后: 5M

截图

在这里插入图片描述
在这里插入图片描述

程序部分源码
main 入口
package mainimport ("embed""fmt""github.com/energye/lcl/inits""github.com/energye/lcl/lcl""xta/xtaui/window"
)//go:embed assets
var resources embed.FS//go:embed libs
var lib embed.FSfunc main() {inits.Init(lib, resources)lcl.Application.Initialize()lcl.Application.SetOnException(func(sender lcl.IObject, e lcl.IException) {fmt.Println("Exception:", e.ToString())})lcl.Application.SetMainFormOnTaskBar(true)lcl.Application.CreateForm(&window.MainWindow)lcl.Application.Run()
}
程序主窗口
package windowimport ("bufio""errors""fmt""github.com/energye/lcl/lcl""github.com/energye/lcl/rtl""github.com/energye/lcl/types""github.com/energye/lcl/types/colors""github.com/energye/xta/chat""io/fs""os""time"_ "xta/xtaui/syso"
)type TMainWindow struct {lcl.TFormmessage lcl.IMemochat    lcl.IMemoai      chat.IGiteeAIchatBtn lcl.IButtonselFileBtn lcl.IButtonselDirDlg  lcl.ISelectDirectoryDialogsaveChatBtn lcl.IButtonsaveDirDlg  lcl.ISaveDialogsavePathInp lcl.IMemosaveFileBuf *bufio.WriterfileWindow []*FileWindowtitle string
}var MainWindow TMainWindowfunc (m *TMainWindow) FormCreate(sender lcl.IObject) {m.title = "ENERGY - XTA Chat UI"m.SetCaption(m.title)m.SetPosition(types.PoScreenCenter)m.SetWidth(1024)m.SetHeight(768)m.SetShowHint(true)m.Constraints().SetMinWidth(types.TConstraintSize(m.Width()))m.Constraints().SetMinHeight(types.TConstraintSize(m.Height()))png := lcl.NewPngImage()png.LoadFromFSFile("assets/icon.png")lcl.Application.Icon().Assign(png)png.Free()m.initMainBox()
}func (m *TMainWindow) initMainBox() {go m.initXTASDK()openURL := lcl.NewLinkLabel(m)openURL.SetParent(m)openURL.SetCaption(`<a href="https://ai.gitee.com/models"> [Gitee AI API 获取] </a>`)openURL.SetAlign(types.AlRight)openURL.SetTop(5)openURL.Font().SetSize(12)openURL.SetOnLinkClick(func(sender lcl.IObject, link string, linktype types.TSysLinkType) {rtl.SysOpen(link)})open1URL := lcl.NewLinkLabel(m)open1URL.SetParent(m)open1URL.SetCaption(`<a href="https://github.com/energye/xta"> [XTA AI SDK] </a>`)open1URL.SetAlign(types.AlRight)open1URL.SetTop(5)open1URL.Font().SetSize(12)open1URL.SetOnLinkClick(func(sender lcl.IObject, link string, linktype types.TSysLinkType) {rtl.SysOpen(link)})modules := lcl.NewComboBox(m)modules.SetParent(m)modules.SetLeft(150)modules.Items().AddStrings2(chat.GiteeAIModels())modules.SetItemIndex(17)modules.SetHeight(35)modules.SetWidth(300)modules.Font().SetSize(12)modules.SetOnChange(func(sender lcl.IObject) {module := chat.GiteeAIModelNameEnum(modules.Items().Strings(modules.ItemIndex()))m.ai.SetModel(module)m.message.Lines().Add("模型: " + m.ai.Model())m.SetCaption(m.title + " " + m.ai.Model())})apiKey := lcl.NewEditButton(m)apiKey.SetParent(m)apiKey.SetLeft(modules.Left() + modules.Width() + 5)apiKey.SetPasswordChar(uint16('*'))apiKey.SetHeight(35)apiKey.SetWidth(200)apiKey.Font().SetSize(12)apiKey.Button().SetCaption("API KEY")//apiKey.Button().SetLeft(100)apiKey.Button().SetWidth(80)apiKey.SetOnClick(func(sender lcl.IObject) {m.ai.Options().APIKey = apiKey.Text()})// 消息m.message = lcl.NewMemo(m)m.message.SetParent(m)m.message.SetTop(40)m.message.SetLeft(150)m.message.SetWidth(m.Width() - 150)m.message.SetHeight(m.Height() - 190)m.message.SetBorderStyle(types.BsNone)m.message.SetReadOnly(true)m.message.SetScrollBars(types.SsAutoBoth)m.message.SetWordWrap(true)m.message.SetAnchors(types.NewSet(types.AkLeft, types.AkTop, types.AkRight, types.AkBottom))// 聊天m.chat = lcl.NewMemo(m)m.chat.SetParent(m)m.chat.SetBorderStyle(types.BsNone)m.chat.SetScrollBars(types.SsAutoBoth)m.chat.SetTop(m.message.Top() + m.message.Height() + 3)m.chat.SetLeft(150)m.chat.SetWidth(m.Width())m.chat.SetHeight(100)m.chat.SetAnchors(types.NewSet(types.AkLeft, types.AkRight, types.AkBottom))chatLabel := lcl.NewLabel(m)chatLabel.SetParent(m)chatLabel.SetCaption("发送消息")chatLabel.SetTop(m.chat.Top() + 40)chatLabel.SetLeft(20)chatLabel.Font().SetSize(18)chatLabel.Font().SetColor(colors.ClGray)chatLabel.SetAnchors(types.NewSet(types.AkLeft, types.AkBottom))// 发送消息m.chatBtn = lcl.NewButton(m)m.chatBtn.SetParent(m)m.chatBtn.SetTop(m.chat.Top() + m.chat.Height() + 3)m.chatBtn.SetWidth(100)m.chatBtn.SetHeight(45)m.chatBtn.SetCaption("发 送")m.chatBtn.Font().SetSize(16)m.chatBtn.SetLeft(m.Width() - 100)m.chatBtn.SetAnchors(types.NewSet(types.AkRight, types.AkBottom))m.chatBtn.SetOnClick(m.SendMessage)// 选择文件m.selDirDlg = lcl.NewOpenDialog(m)m.selDirDlg.SetOptions(m.selDirDlg.Options().Include(types.OfShowHelp, types.OfAllowMultiSelect))m.selDirDlg.SetTitle("XTA - AI SDK 打开文件 多选")m.selFileBtn = lcl.NewButton(m)m.selFileBtn.SetParent(m)m.selFileBtn.SetTop(m.chat.Top() + m.chat.Height() + 3)m.selFileBtn.SetWidth(150)m.selFileBtn.SetHeight(40)m.selFileBtn.SetCaption("选择文件/多选")m.selFileBtn.Font().SetSize(12)m.selFileBtn.SetLeft(150)m.selFileBtn.SetOnClick(m.selectFileOrDir)m.selFileBtn.SetAnchors(types.NewSet(types.AkLeft, types.AkBottom))// 保存消息m.saveDirDlg = lcl.NewSaveDialog(m)m.saveDirDlg.SetFilter("文本文件(*.txt)|*.txt|所有文件(*.*)|*.*")m.saveDirDlg.SetTitle("XTA - AI SDK 消息保存")m.saveChatBtn = lcl.NewButton(m)m.saveChatBtn.SetParent(m)m.saveChatBtn.SetTop(m.chat.Top() + m.chat.Height() + 3)m.saveChatBtn.SetLeft(m.selFileBtn.Left() + m.selFileBtn.Width() + 3)m.saveChatBtn.SetCaption("保存消息")m.saveChatBtn.SetWidth(100)m.saveChatBtn.SetHeight(40)m.saveChatBtn.Font().SetSize(12)m.saveChatBtn.SetAnchors(types.NewSet(types.AkLeft, types.AkBottom))m.saveChatBtn.SetOnClick(func(sender lcl.IObject) {if m.saveDirDlg.Execute() {m.savePathInp.SetText(m.saveDirDlg.FileName())}})m.savePathInp = lcl.NewMemo(m)m.savePathInp.SetParent(m)m.savePathInp.SetTop(m.chat.Top() + m.chat.Height() + 3)m.savePathInp.SetLeft(m.saveChatBtn.Left() + m.saveChatBtn.Width() + 3)m.savePathInp.SetHeight(40)m.savePathInp.SetWidth(300)m.savePathInp.Font().SetSize(15)m.savePathInp.SetWordWrap(false)m.savePathInp.SetAnchors(types.NewSet(types.AkLeft, types.AkBottom))var savefile *os.Filem.savePathInp.SetOnChange(func(sender lcl.IObject) {if savefile != nil {savefile.Close()savefile = nilm.saveFileBuf = nil}path := m.savePathInp.Text()fe, err := os.Open(path)if err == nil {defer fe.Close()st, err := fe.Stat()if err == nil {if !st.IsDir() {savefile, err = os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)if err == nil {m.saveFileBuf = bufio.NewWriter(savefile)}}}} else if errors.Is(err, fs.ErrNotExist) {savefile, err = os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)if err == nil {m.saveFileBuf = bufio.NewWriter(savefile)}}})// 窗口显示m.SetOnShow(func(sender lcl.IObject) {m.chat.SetFocus()apiKey.SetText(m.ai.APIKey())})//clearHistory := lcl.NewButton(m)//clearHistory.SetParent(m)//clearHistory.SetOnClick(func(sender lcl.IObject) {//	m.ai.History()//})
}// 主窗口左侧创建文件项
func (m *TMainWindow) createFileItem(filewindow *FileWindow) {btn := lcl.NewButton(m)btn.SetParent(m)caption := filewindow.fileDescif caption == "" {caption = filewindow.filenames}btn.SetCaption(caption)btn.SetOnClick(func(sender lcl.IObject) {m.removeFileBtn(filewindow.id)})btn.SetHint("点击删除该文件项")filewindow.fileBtn = btnm.fileWindow = append(m.fileWindow, filewindow)m.resortFileBtns()
}func (m *TMainWindow) removeFileBtn(id string) {var newwindows []*FileWindowfor _, fw := range m.fileWindow {if fw.id == id {lcl.RunOnMainThreadAsync(func(id uint32) {fw.fileBtn.Free()fw.Close()})} else {newwindows = append(newwindows, fw)}}m.fileWindow = newwindowsm.resortFileBtns()
}func (m *TMainWindow) resortFileBtns() {for i, fw := range m.fileWindow {fw.fileBtn.SetLeft(5)fw.fileBtn.SetWidth(130)fw.fileBtn.SetHeight(30)fw.fileBtn.SetTop(int32(i*30) + 5)}
}func (m *TMainWindow) selectFileOrDir(sender lcl.IObject) {if m.selDirDlg.Execute() {files := m.selDirDlg.Files()var file []stringfor i := 0; i < int(files.Count()); i++ {fmt.Println(files.ValueFromIndex(int32(i)))file = append(file, files.ValueFromIndex(int32(i)))}win := createWindow(file, func(window *FileWindow) {m.createFileItem(window)})win.Show()}
}func nowDatetime() string {return time.Now().Format("2006-01-02 15:04:05")
}
XTA - AI SDK
package windowimport ("bytes""fmt""github.com/energye/lcl/lcl""github.com/energye/xta/chat""os""strings"
)func (m *TMainWindow) initXTASDK() {options := chat.DefaultGiteeAIOptionsoptions.APIKey = os.Getenv(chat.ENV_AI_API_KEY)m.ai = chat.NewGiteeAI(options, false)m.ai.System("【系统角色】你具备跨领域知识整合与结构化推理能力的智能助手。始终遵循:事实准确性 > 响应速度 > 表达流畅度的优先级原则。【响应规范】1. 解析阶段:识别问题类型(事实/观点/方法需求),标注关键信息置信度2. 处理阶段:- 事实类:提供最新权威信源+时间戳- 观点类:多视角分析+概率评估 - 方法类:分步实施框架+风险预案3. 输出阶段:采用「结论-依据-延伸」结构,技术概念附带白话解释【安全协议】- 对潜在争议内容自动附加免责声明- 医疗/法律建议必须提示咨询专业人士- 实时监测对话情感倾向,对焦虑/紧急表达启动安抚话术")isFirstRec := falsem.ai.SetOnReceive(func(message *chat.TResponse) {if !isFirstRec {m.message.Lines().Add("回复: " + nowDatetime())isFirstRec = true}// 在异步UI线程里操作lcl.RunOnMainThreadAsync(func(id uint32) {if message != nil {if message.Error != "" {s := fmt.Sprintf("错误: %v %v", message.Error, message.ErrorType)m.message.Lines().Add(s)if m.saveFileBuf != nil {m.saveFileBuf.WriteString(s)m.saveFileBuf.Flush()}}choices := message.Choicesfor _, choice := range choices {if strings.Contains(choice.Delta.Content, "\n") {m.message.Lines().Add(choice.Delta.Content)} else {m.message.SetSelStart(int32(len(m.message.Lines().Text())))m.message.SetSelText(choice.Delta.Content)}if m.saveFileBuf != nil {m.saveFileBuf.WriteString(choice.Delta.Content)m.saveFileBuf.Flush()}}} else {fmt.Println("结束")m.message.Lines().Add("")m.chatBtn.SetEnabled(true)isFirstRec = false}})})m.ai.SetOnFail(func(message *chat.TResponseError) {lcl.RunOnMainThreadSync(func() {s := fmt.Sprintf("  错误: %v %v %v", message.Code, message.Message, message.Type)m.message.Lines().Add(s)m.chatBtn.SetEnabled(true)isFirstRec = false})})lcl.RunOnMainThreadSync(func() {m.message.Lines().Add("XTA - AI SDK 初始化完成")m.message.Lines().Add("模型: " + m.ai.Model())//m.message.Lines().Add("APIKEY: ........." + m.ai.APIKey()[5:10] + "............")m.SetCaption(m.title + " " + m.ai.Model())})
}func (m *TMainWindow) SendMessage(sender lcl.IObject) {msg := m.chat.Lines().Text()if msg != "" {m.message.Lines().Add("我: " + nowDatetime())m.message.Lines().Add("  " + msg)buf := bytes.Buffer{}buf.WriteString(msg + "\n")for _, fw := range m.fileWindow {if fw.isSend {continue}fw.isSend = truebuf.WriteString(fw.text.Text() + "\n")buf.WriteString(strings.Join(fw.fileContent, "\n"))}m.sendMessage(buf.String())m.chat.SetText("")}
}func (m *TMainWindow) sendMessage(content string) {// 在协程里操作go m.ai.ChatStream(content)m.chatBtn.SetEnabled(false)
}
http://www.dtcms.com/a/464754.html

相关文章:

  • 河南省村镇建设处网站网站配色与布局 教材
  • Prometheus运维之路(ES监控接入)
  • OpenAMP专题(一):一文了解OpenAMP全貌
  • C++ 中 rfind 方法详解
  • SpringBoot 教程(十四) SpringBoot之集成 Redis(优化版)
  • 【Linux】线程同步与互斥(上)
  • 图观 模型编辑器
  • Win11 输入延迟与鼠标卡顿:系统化排查与优化指南
  • 【开题答辩全过程】以 爱运动健身小程序的设计与实现为例,包含答辩的问题和答案
  • Linux 内核IIO sensor驱动
  • 《Linux系统编程之入门基础》【Linux的前世今生】
  • 活动汪活动策划网站龙岗建设网站
  • Apache IoTDB 架构特性与 Prometheus+Grafana 监控体系部署实践
  • LLM时代基于unstructured解析非结构化pdf
  • uniapp tab切换及tab锚点效果(wx小程序及H5端)
  • Hadoop面试题及详细答案 110题 (71-85)-- 集群部署与运维
  • 5-1〔OSCP ◈ 研记〕❘ SQL注入攻击▸SQL注入理论基础
  • 南充市企业网站建设wordpress极客主题
  • 企业做小红书关键词搜索排名推广时,怎么找到小红书上有一定搜索量但竞争度低的蓝海词?
  • 数据仓库与数据挖掘基础知识
  • 鸿蒙:使用Rating组件实现五角星打分评价
  • 外国人可以在中国做网站吗做个网站得花多少钱
  • 双均线策略
  • 【vLLM 学习】Neuron
  • 网站做行业认证好处施工企业在施工过程中发现工程设计图纸存在差错的
  • 迅为RK3576开发板挂载Windows以及虚拟机Ubuntu测试
  • 第1篇:创建基础电商AI客服
  • 【MyBatis从入门到入土】告别JDBC原始时代:零基础MyBatis极速上手指南
  • MaxScript 科研绘图教程:从数据到精确的可视化
  • org.apache.http.conn.HttpHostConnectException: Connect to localhost:8086