go 使用fyne实现桌面程序的计算器例子

使用Fyne工具包构建跨平台应用是非常简单的,在此之前我们需要做一些准备功能做,比如安装一些gcc基础图形依赖库,还有go语言本身的运行开发环境都是必要的。

在此之前我们希望你是go语言的已入门用户,掌握go的协程,管道,以及大多数语法,这样会让你学习起来更轻松

下面是实现的代码,有一部分还没有实现,如果需要可以继续研究.

package main

import (
	"image/color"
	"math"
	"strconv"
	"strings"
	"time"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
	"fyne.io/fyne/v2/driver/desktop"
)

// 自定义按钮样式
type calculatorButton struct {
	widget.Button
	bgColor     color.Color
	pressScale  float32    // 按下时的缩放比例
	isPressed   bool       // 按钮是否被按下
	animating   bool       // 是否正在动画中
}

func newCalculatorButton(label string, bgColor color.Color, tapped func()) *calculatorButton {
	button := &calculatorButton{
		bgColor:    bgColor,
		pressScale: 0.95,    // 按下时缩小到95%
		isPressed:  false,
		animating:  false,
	}
	button.ExtendBaseWidget(button)
	button.Text = label
	button.OnTapped = tapped
	return button
}

// 添加鼠标按下事件处理
func (b *calculatorButton) MouseDown(*desktop.MouseEvent) {
	b.isPressed = true
	b.animating = true
	b.Refresh()
}

// 添加鼠标释放事件处理
func (b *calculatorButton) MouseUp(*desktop.MouseEvent) {
	b.isPressed = false
	b.animating = true
	b.Refresh()
}

func (b *calculatorButton) CreateRenderer() fyne.WidgetRenderer {
	background := &canvas.Circle{
		FillColor: b.bgColor,
	}
	
	text := canvas.NewText(b.Text, color.White)
	text.TextSize = 20
	text.Alignment = fyne.TextAlignCenter

	renderer := &calculatorButtonRenderer{
		button:     b,
		background: background,
		text:       text,
		objects:    []fyne.CanvasObject{background, text},
	}

	// 创建动画
	renderer.animation = fyne.NewAnimation(
		time.Millisecond*100,    // 动画持续100毫秒
		func(progress float32) {
			if b.isPressed {
				// 从1.0缩pressScale
				scale := 1.0 - (1.0-b.pressScale)*progress
				renderer.updateScale(scale)
			} else {
				// 从pressScale恢复到1.0
				scale := b.pressScale + (1.0-b.pressScale)*progress
				renderer.updateScale(scale)
			}
			renderer.Refresh()
		},
	)

	return renderer
}

type calculatorButtonRenderer struct {
	button     *calculatorButton
	background *canvas.Circle
	text       *canvas.Text
	objects    []fyne.CanvasObject
	animation  *fyne.Animation    // 添加动画对象
}

// 添加缩放更新函数
func (r *calculatorButtonRenderer) updateScale(scale float32) {
	baseSize := fyne.NewSize(60, 45)  // 使用固定的基础大小
	scaledSize := fyne.NewSize(
		float32(baseSize.Width)*scale,
		float32(baseSize.Height)*scale,
	)
	
	// 计算偏移以保持按钮居中
	offset := fyne.NewPos(
		(float32(baseSize.Width)-scaledSize.Width)/2,
		(float32(baseSize.Height)-scaledSize.Height)/2,
	)
	
	r.background.Resize(scaledSize)
	r.background.Move(offset)
	
	// 更新文本位置
	textSize := r.text.MinSize()
	r.text.Resize(textSize)
	r.text.Move(fyne.NewPos(
		(baseSize.Width-textSize.Width)/2,
		(baseSize.Height-textSize.Height)/2,
	))
}

// 修改 Refresh 函数
func (r *calculatorButtonRenderer) Refresh() {
	if r.button.animating {
		r.animation.Start()
		r.button.animating = false
	}
	
	r.background.FillColor = r.button.bgColor
	r.background.Refresh()
	r.text.Text = r.button.Text
	r.text.Refresh()
}

// 修改 Destroy 函数
func (r *calculatorButtonRenderer) Destroy() {
	r.animation.Stop()
}

// 添加Layout方法
func (r *calculatorButtonRenderer) Layout(size fyne.Size) {
	// 设置背景大小和位置
	r.background.Resize(size)
	
	// 文本居中
	textSize := r.text.MinSize()
	r.text.Resize(textSize)
	r.text.Move(fyne.NewPos(
		(size.Width-textSize.Width)/2,
		(size.Height-textSize.Height)/2,
	))
}

// 添加MinSize方法
func (r *calculatorButtonRenderer) MinSize() fyne.Size {
	return fyne.NewSize(60, 45)
}

// 添加Objects方法
func (r *calculatorButtonRenderer) Objects() []fyne.CanvasObject {
	return r.objects
}

// 添加自定义显示组件
type calculatorDisplay struct {
	widget.BaseWidget
	text string
	process string  // 添加计算过程
}

func newCalculatorDisplay() *calculatorDisplay {
	display := &calculatorDisplay{text: "0", process: ""}
	display.ExtendBaseWidget(display)
	return display
}

func (d *calculatorDisplay) CreateRenderer() fyne.WidgetRenderer {
	result := canvas.NewText(d.text, color.White)
	result.TextSize = 32
	result.Alignment = fyne.TextAlignTrailing

	process := canvas.NewText(d.process, color.Gray{Y: 180})  // 灰色显示计算过程
	process.TextSize = 20
	process.Alignment = fyne.TextAlignTrailing

	return &calculatorDisplayRenderer{
		display: d,
		result:  result,
		process: process,
		objects: []fyne.CanvasObject{result, process},
	}
}

type calculatorDisplayRenderer struct {
	display *calculatorDisplay
	result  *canvas.Text
	process *canvas.Text
	objects []fyne.CanvasObject
}

func (r *calculatorDisplayRenderer) MinSize() fyne.Size {
	return fyne.NewSize(280, 70)  // 增加高度以容纳两行文本
}

func (r *calculatorDisplayRenderer) Layout(size fyne.Size) {
	processHeight := float32(25)
	r.process.Resize(fyne.NewSize(size.Width, processHeight))
	r.process.Move(fyne.NewPos(0, 0))
	
	r.result.Resize(fyne.NewSize(size.Width, size.Height-processHeight))
	r.result.Move(fyne.NewPos(0, processHeight))
}

func (r *calculatorDisplayRenderer) Refresh() {
	r.result.Text = r.display.text
	r.process.Text = r.display.process
	r.result.Refresh()
	r.process.Refresh()
}

func (r *calculatorDisplayRenderer) Objects() []fyne.CanvasObject {
	return r.objects
}

func (r *calculatorDisplayRenderer) Destroy() {}

func main() {
	a := app.New()
	w := a.NewWindow("计算器")
	w.SetFixedSize(true)

	// 设置深色主题
	a.Settings().SetTheme(theme.DarkTheme())

	// 声明计算器状态变量
	var (
		firstNumber float64
		operation   string
		newNumber   = true
		showingResult = false  // 添加这个变量
	)

	// 使用新的显示组件替代原来的Entry
	display := newCalculatorDisplay()

	// 定义颜色
	grayColor := &color.NRGBA{R: 51, G: 51, B: 51, A: 255}
	orangeColor := &color.NRGBA{R: 255, G: 159, B: 10, A: 255}
	lightGrayColor := &color.NRGBA{R: 165, G: 165, B: 165, A: 255}
	darkerGrayColor := &color.NRGBA{R: 40, G: 40, B: 40, A: 255}

	// 数字按钮
	numbers := map[string]*calculatorButton{}
	for i := 0; i <= 9; i++ {
		number := i
		numbers[strconv.Itoa(i)] = newCalculatorButton(strconv.Itoa(i), grayColor, func() {
			if newNumber || showingResult {
				display.text = ""
				if showingResult {
					display.process = ""  // 清除之前的计算过程
				}
				newNumber = false
				showingResult = false
			}
			display.text += strconv.Itoa(number)
			display.Refresh()
		})
	}

	// 运算符按钮
	add := newCalculatorButton("+", orangeColor, func() {
		if showingResult {
			firstNumber, _ = strconv.ParseFloat(display.text, 64)
			display.process = display.text + " +"  // 开始新的计算过程
			showingResult = false
		} else {
			if !newNumber {
				secondNumber, _ := strconv.ParseFloat(display.text, 64)
				firstNumber = calculateResult(firstNumber, secondNumber, operation)
				display.text = strconv.FormatFloat(firstNumber, 'f', -1, 64)
				display.process = display.text + " +"  // 更新计算过程
			} else {
				firstNumber, _ = strconv.ParseFloat(display.text, 64)
				display.process = display.text + " +"  // 显示第一个数字和运算符
			}
		}
		operation = "+"
		newNumber = true
		display.Refresh()
	})

	subtract := newCalculatorButton("-", orangeColor, func() {
		if showingResult {
			firstNumber, _ = strconv.ParseFloat(display.text, 64)
			showingResult = false
		} else {
			if !newNumber {
				secondNumber, _ := strconv.ParseFloat(display.text, 64)
				firstNumber = calculateResult(firstNumber, secondNumber, operation)
				display.text = strconv.FormatFloat(firstNumber, 'f', -1, 64)
			} else {
				firstNumber, _ = strconv.ParseFloat(display.text, 64)
			}
		}
		operation = "-"
		newNumber = true
		display.Refresh()
	})

	multiply := newCalculatorButton("×", orangeColor, func() {
		if showingResult {
			firstNumber, _ = strconv.ParseFloat(display.text, 64)
			showingResult = false
		} else {
			if !newNumber {
				secondNumber, _ := strconv.ParseFloat(display.text, 64)
				firstNumber = calculateResult(firstNumber, secondNumber, operation)
				display.text = strconv.FormatFloat(firstNumber, 'f', -1, 64)
			} else {
				firstNumber, _ = strconv.ParseFloat(display.text, 64)
			}
		}
		operation = "*"
		newNumber = true
		display.Refresh()
	})

	divide := newCalculatorButton("÷", orangeColor, func() {
		if showingResult {
			firstNumber, _ = strconv.ParseFloat(display.text, 64)
			showingResult = false
		} else {
			if !newNumber {
				secondNumber, _ := strconv.ParseFloat(display.text, 64)
				firstNumber = calculateResult(firstNumber, secondNumber, operation)
				display.text = strconv.FormatFloat(firstNumber, 'f', -1, 64)
			} else {
				firstNumber, _ = strconv.ParseFloat(display.text, 64)
			}
		}
		operation = "/"
		newNumber = true
		display.Refresh()
	})

	equals := newCalculatorButton("=", orangeColor, func() {
		if !newNumber {
			secondNumber, _ := strconv.ParseFloat(display.text, 64)
			display.process += " " + display.text + " ="  // 完成计算过程
			result := calculateResult(firstNumber, secondNumber, operation)
			display.text = strconv.FormatFloat(result, 'f', -1, 64)
			firstNumber = result
			showingResult = true
			display.Refresh()
		}
	})

	// 额外的功能按钮
	ac := newCalculatorButton("AC", lightGrayColor, func() {
		display.text = "0"
		display.process = ""  // 清除计算过程
		firstNumber = 0
		operation = ""
		newNumber = true
		showingResult = false
		display.Refresh()
	})

	plusMinus := newCalculatorButton("+/-", lightGrayColor, func() {
		if current, err := strconv.ParseFloat(display.text, 64); err == nil {
			display.text = strconv.FormatFloat(-current, 'f', -1, 64)
			display.Refresh()
		}
	})

	percent := newCalculatorButton("%", lightGrayColor, func() {
		if current, err := strconv.ParseFloat(display.text, 64); err == nil {
			display.text = strconv.FormatFloat(current/100, 'f', -1, 64)
			display.Refresh()
		}
	})

	decimal := newCalculatorButton(".", grayColor, func() {
		if !strings.Contains(display.text, ".") {
			display.text += "."
			display.Refresh()
		}
	})

	// 科学计算器的额外功能按钮
	mc := newCalculatorButton("mc", darkerGrayColor, func() {
		// 内存清除功能
	})

	mPlus := newCalculatorButton("m+", darkerGrayColor, func() {
		// 内存加功能
	})

	mMinus := newCalculatorButton("m-", darkerGrayColor, func() {
		// 内存减功能
	})

	mr := newCalculatorButton("mr", darkerGrayColor, func() {
		// 内存调用功能
	})

	// 科学运算按钮
	sin := newCalculatorButton("sin", darkerGrayColor, func() {
		if val, err := strconv.ParseFloat(display.text, 64); err == nil {
			result := math.Sin(val * math.Pi / 180) // 转换为弧度
			display.text = strconv.FormatFloat(result, 'f', -1, 64)
			display.Refresh()
		}
	})

	cos := newCalculatorButton("cos", darkerGrayColor, func() {
		if val, err := strconv.ParseFloat(display.text, 64); err == nil {
			result := math.Cos(val * math.Pi / 180)
			display.text = strconv.FormatFloat(result, 'f', -1, 64)
			display.Refresh()
		}
	})

	tan := newCalculatorButton("tan", darkerGrayColor, func() {
		if val, err := strconv.ParseFloat(display.text, 64); err == nil {
			result := math.Tan(val * math.Pi / 180)
			display.text = strconv.FormatFloat(result, 'f', -1, 64)
			display.Refresh()
		}
	})

	ln := newCalculatorButton("ln", darkerGrayColor, func() {
		if val, err := strconv.ParseFloat(display.text, 64); err == nil {
			result := math.Log(val)
			display.text = strconv.FormatFloat(result, 'f', -1, 64)
			display.Refresh()
		}
	})

	log := newCalculatorButton("log₁₀", darkerGrayColor, func() {
		if val, err := strconv.ParseFloat(display.text, 64); err == nil {
			result := math.Log10(val)
			display.text = strconv.FormatFloat(result, 'f', -1, 64)
			display.Refresh()
		}
	})

	sqrt := newCalculatorButton("√x", darkerGrayColor, func() {
		if val, err := strconv.ParseFloat(display.text, 64); err == nil {
			result := math.Sqrt(val)
			display.text = strconv.FormatFloat(result, 'f', -1, 64)
			display.Refresh()
		}
	})

	square := newCalculatorButton("x²", darkerGrayColor, func() {
		if val, err := strconv.ParseFloat(display.text, 64); err == nil {
			result := math.Pow(val, 2)
			display.text = strconv.FormatFloat(result, 'f', -1, 64)
			display.Refresh()
		}
	})

	pi := newCalculatorButton("π", darkerGrayColor, func() {
		display.text = strconv.FormatFloat(math.Pi, 'f', -1, 64)
		display.Refresh()
	})

	e := newCalculatorButton("e", darkerGrayColor, func() {
		display.text = strconv.FormatFloat(math.E, 'f', -1, 64)
		display.Refresh()
	})

	factorial := newCalculatorButton("x!", darkerGrayColor, func() {
		if val, err := strconv.ParseFloat(display.text, 64); err == nil {
			n := int(val)
			result := 1.0
			for i := 2; i <= n; i++ {
				result *= float64(i)
			}
			display.text = strconv.FormatFloat(result, 'f', -1, 64)
			display.Refresh()
		}
	})

	// 添加模式切换状态
	var isScientificMode = false
	
	// 声明updateLayout变量(在最前面)
	var updateLayout func()
	
	// 创建主容器
	mainContainer := container.NewVBox()
	
	// 创建显示区域容器
	displayContainer := container.NewPadded(display)
	
	// 创建基本计算器布局
	createBasicLayout := func() *fyne.Container {
		return container.NewGridWithColumns(4,
			ac, plusMinus, percent, divide,
			numbers["7"], numbers["8"], numbers["9"], multiply,
			numbers["4"], numbers["5"], numbers["6"], subtract,
			numbers["1"], numbers["2"], numbers["3"], add,
			numbers["0"], decimal, equals,
		)
	}

	// 创建科学计算器布局
	createScientificLayout := func() *fyne.Container {
		return container.NewGridWithColumns(10,
			// 第一行
			newCalculatorButton("(", darkerGrayColor, nil),
			newCalculatorButton(")", darkerGrayColor, nil),
			mc, mPlus, mMinus, mr,
			ac, plusMinus, percent, divide,
			// 第二行
			newCalculatorButton("2ⁿᵈ", darkerGrayColor, nil),
			square,
			newCalculatorButton("x³", darkerGrayColor, nil),
			newCalculatorButton("xʸ", darkerGrayColor, nil),
			e,  // 使用 e 按钮
			newCalculatorButton("10ˣ", darkerGrayColor, nil),
			numbers["7"], numbers["8"], numbers["9"], multiply,
			// 第三行
			factorial,  // 使用阶乘按钮
			sqrt,      // 使用平方根按钮
			pi,        // 使用 π 按钮
			ln,        // 使用自然对数按钮
			log,       // 使用常用对数按钮
			newCalculatorButton("EE", darkerGrayColor, nil),
			numbers["4"], numbers["5"], numbers["6"], subtract,
			// 第四行
			sin,       // 使用正弦按钮
			cos,       // 使用余弦按钮
			tan,       // 使用正切按钮
			newCalculatorButton("sinh", darkerGrayColor, nil),
			newCalculatorButton("cosh", darkerGrayColor, nil),
			newCalculatorButton("tanh", darkerGrayColor, nil),
			numbers["1"], numbers["2"], numbers["3"], add,
			// 第五行
			newCalculatorButton("Rad", darkerGrayColor, nil),
			newCalculatorButton("sinh⁻¹", darkerGrayColor, nil),
			newCalculatorButton("cosh⁻¹", darkerGrayColor, nil),
			newCalculatorButton("tanh⁻¹", darkerGrayColor, nil),
			newCalculatorButton("Rand", darkerGrayColor, nil),
			newCalculatorButton("EE", darkerGrayColor, nil),
			numbers["0"], decimal, equals,
		)
	}
	
	// 创建顶部工具栏(不包含modeSwitch)
	toolbar := container.NewHBox(
		widget.NewSeparator(),
	)

	// 定义updateLayout函数
	updateLayout = func() {
		var layout fyne.CanvasObject
		if isScientificMode {
			layout = createScientificLayout()
		} else {
			layout = createBasicLayout()
		}
		
		mainContainer.Objects = []fyne.CanvasObject{
			toolbar,
			displayContainer,
			layout,
		}
		mainContainer.Refresh()
	}

	// 现在定义modeSwitch(在updateLayout之后)
	modeSwitch := newCalculatorButton("⚙", lightGrayColor, func() {
		isScientificMode = !isScientificMode
		
		startSize := w.Canvas().Size()
		var targetWidth float32
		if isScientificMode {
			targetWidth = 600
		} else {
			targetWidth = 300
		}
		targetSize := fyne.NewSize(targetWidth, 450)
		
		animation := fyne.NewAnimation(
			time.Millisecond*300,
			func(progress float32) {
				width := startSize.Width + (targetSize.Width-startSize.Width)*progress
				height := startSize.Height + (targetSize.Height-startSize.Height)*progress
				w.Resize(fyne.NewSize(width, height))
			},
		)
		
		animation.Start()
		updateLayout()
	})

	// 更新toolbar,添加modeSwitch
	toolbar.Objects = append([]fyne.CanvasObject{modeSwitch}, toolbar.Objects...)

	// 初始化布局
	updateLayout()

	// 直接使用mainContainer作为窗口内容
	w.SetContent(mainContainer)
	w.Resize(fyne.NewSize(300, 450))
	w.ShowAndRun()
}

// 添加一个辅助函数来计算结果
func calculateResult(first, second float64, op string) float64 {
	var result float64
	switch op {
	case "+":
		result = first + second
	case "-":
		result = first - second
	case "*":
		result = first * second
	case "/":
		if second != 0 {
			result = first / second
		}
	}
	return result
}

go.mod文件

module calc

go 1.23.1

require fyne.io/fyne/v2 v2.5.2

require (
	fyne.io/systray v1.11.0 // indirect
	github.com/BurntSushi/toml v1.4.0 // indirect
	github.com/davecgh/go-spew v1.1.1 // indirect
	github.com/fredbi/uri v1.1.0 // indirect
	github.com/fsnotify/fsnotify v1.7.0 // indirect
	github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe // indirect
	github.com/fyne-io/glfw-js v0.0.0-20240101223322-6e1efdc71b7a // indirect
	github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 // indirect
	github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 // indirect
	github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect
	github.com/go-text/render v0.2.0 // indirect
	github.com/go-text/typesetting v0.2.0 // indirect
	github.com/godbus/dbus/v5 v5.1.0 // indirect
	github.com/gopherjs/gopherjs v1.17.2 // indirect
	github.com/jeandeaual/go-locale v0.0.0-20240223122105-ce5225dcaa49 // indirect
	github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e // indirect
	github.com/nicksnyder/go-i18n/v2 v2.4.0 // indirect
	github.com/pmezard/go-difflib v1.0.0 // indirect
	github.com/rymdport/portal v0.2.6 // indirect
	github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect
	github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect
	github.com/stretchr/testify v1.8.4 // indirect
	github.com/yuin/goldmark v1.7.1 // indirect
	golang.org/x/image v0.18.0 // indirect
	golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a // indirect
	golang.org/x/net v0.25.0 // indirect
	golang.org/x/sys v0.20.0 // indirect
	golang.org/x/text v0.16.0 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/901505.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++进阶篇】——STL的简介

【C进阶篇】——STL的简介 1.什么是STL STL(standard template libaray-标准模板库)&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且是一个包罗数据结构与算法的软件框架。 2.STL的版本 原始版本 Alexander Stepanov、Meng Lee 在…

【Linux系统】环境变量

一、通俗例子解释环境变量概念与作用 想象你在厨房做饭&#xff0c;需要找到各种调料和工具。这些调料和工具就相当于计算机中的“资源”&#xff0c;而环境变量就像厨房里的一本规则书&#xff0c;里面列出了厨房里所有调料和工具的位置。 具有全局性&#xff08;所有人都能用…

MCU SCT文件学习

硬件&#xff1a;GD32F427, 外设&#xff1a;FreeRtos,ADC,DMA 现象&#xff1a;注释掉一些线程&#xff0c;发现ADC采样的线程采样不到数据了。 开始猜测是线程重入&#xff0c;破坏了地址&#xff0c;后来思考一下发现不对&#xff0c;因为注释掉线程&#xff0c;ADCDMA采…

【Vulnhub靶场】DC-4

DC-4靶场下载地址https://www.five86.com/downloads/DC-4.zip 本机IP&#xff1a;192.168.118.128 靶机IP&#xff1a;192.168.118.0/24 信息收集 扫描主机存活&#xff0c;扫描端口&#xff0c;扫描服务 第一步扫描出主机ip为192.168.118.141 nmap -sP 192.168.118.0/24 nm…

高级 SQL 技巧全面教程:提升你的数据库操作能力

高级 SQL 技巧全面教程&#xff1a;提升你的数据库操作能力 引言 在数据驱动的时代&#xff0c;SQL&#xff08;结构化查询语言&#xff09;是与数据库交互的核心工具。虽然基础 SQL 语法足以满足日常需求&#xff0c;但掌握一些高级技巧能够显著提高你的工作效率和数据处理能…

Node.js初学者指南:搭建HTTP服务器、获取请求信息及响应、变量声明与NPM包管理

精神畅快&#xff0c;心气平和&#xff1b;饮食有节&#xff0c;寒暖当心&#xff1b;起居以时&#xff0c;劳逸均匀 文章目录 node.js使用http搭建服务器的问题获取请求相关的信息响应相关的信息var、let、const对比npm使用全局安装包 node.js 概念 node.js是一个基于Chrome …

RTE 2024 隐藏攻略

大家好&#xff01;想必今年 RTE 大会议程大家都了解得差不多了&#xff0c;这将是一场实时互动和多模态 AI builder 的年度大聚会。 大会开始前&#xff0c;我们邀请了参与大会策划的 RTE 开发者社区和超音速计划的成员们&#xff0c;分享了不同活动的亮点和隐藏攻略。 请收…

使用Poste搭建内网邮件服务器

使用Poste搭建内网邮件服务器 Poste.io 也是一个流行的邮件服务器方案&#xff0c;它可以通过 Docker 容器轻松部署&#xff0c;非常适合搭建内部邮件服务器。 本文档将向您展示如何开始使用 Poste.io 邮件服务器。在 5 分钟内&#xff0c;您将拥有一个可发送和接收邮件的邮件…

WSL2 Ubuntu22.04编译安装LLVM

前提 这两天因为工作需要&#xff0c;要编译一个Debug版本的llvm。这里对编译安装过程进行一个简单的记录&#xff0c;同时也记录下这个过程中遇到的几个问题。 下载源码并编译 有关llvm编译安装的官方文档在这里。 从git仓库clone llvm的源码。 git clone https://github.c…

SD-WAN企业组网的应用场景

SD-WAN&#xff08;软件定义广域网&#xff09;能够实现企业不同站点之间的高效互联&#xff0c;确保分支机构、总部、数据中心以及云平台等站点的顺畅通信。本文将探讨从企业的WAN业务需求出发&#xff0c;可以将SD-WAN的组网场景分为哪几类。 SD-WAN的典型组网场景 企业站点之…

Docker中如何控制服务启动顺序实现探讨

文章目录 一、Docker概述二、Docker三剑客1. Compose2. Machine3. Swarm 三、简要需求1. 样例工程2. 代码模块3. 调用方向4. 期望启动顺序 四、思路分析1.各走各路1.&#xff09;docker-compose -f指定不同配置文件2.&#xff09;docker-compose up -d service-name指定服务名3…

基于SpringBoot的高校体测管理系统设计与实现(源码+定制+开发)高校体测记录系统设计、高校体测信息管理平台、智能体测管理系统开发、高校体测记录系统设计

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

如何将markdown文件转换为pdf

最近笔者在用vscode写markdown&#xff0c;但是提交时往往需要交pdf。所以就涉及到如何将markdown转化为pdf格式。 首先&#xff0c;需要在vscode上安装插件 markdown Preview Enhanced 之后在vscode的右上角即可看到下述图标&#xff0c;点击&#xff0c;vscode右半面就会显示…

Spring Boot驱动的植物健康监测革命

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理植物健康系统的相关信息成为必然。开发合适…

VulkanTutorial(1·简述,vs环境搭建)

介绍&#xff1a; 与OpenGL&#xff0c;WebGL和Direct3D等API&#xff08;(Application Programming Interface, 应用程序编程接口)&#xff09;相比&#xff0c;valkan更偏向于底层&#xff0c;有更多的GPU控制接口&#xff0c;因此它有更好的性能和更小的驱动开销&#xff0…

检索增强型生成模型RichRAG:为多面查询提供丰富回应

人工智能咨询培训老师叶梓 转载标明出处 大模型在处理静态知识更新和信息准确性方面仍面临挑战。为了解决这些问题&#xff0c;检索增强型生成&#xff08;RAG&#xff09;模型应运而生&#xff0c;它们通过检索文档来辅助语言模型生成更可靠的回答。但现有的RAG研究大多集中在…

springboot079信息化在线教学平台的设计与实现(论文+源码)_kaic

信息化在线教学平台的设计与实现 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了信息化在线教学平台的开发全过程。通过分析信息化在线教学平台管理的不足&#xff0c;创建了一个计算机管理信息化在线教学平台…

【人工智能】——matplotlib教程

文章目录 1.matplotlib简介2.基本绘图功能2.1给图形添加辅助功能2.2在一个坐标系中绘制多个图像2.3多个坐标系显示图像 3.常见图像绘制 1.matplotlib简介 matplotlib 是一个用于创建二维图表和数据可视化的 Python 库&#xff0c;它提供了一种类似于 MATLAB 的绘图接口。matplo…

Mybatis-07.基础操作-环境准备

一.需求说明 二.准备工作

网关三问:为什么微服务需要网关?什么是微服务网关?网关怎么选型?

文章整体介绍 本文旨在解答关于微服务网关的三个核心问题&#xff1a; 1&#xff09;为什么需要网关&#xff1f;也即在何种场景下应采用微服务网关以优化系统架构&#xff1b; 2&#xff09;什么是微服务网关&#xff1f;主要讲构成微服务网关的关键能力&#xff0c;包括但…