用Java模拟打字:深入解析 java.awt.Robot 的键盘控制艺术
作为开发者,我们有时会遇到需要自动化用户界面交互的场景,比如自动化测试、脚本编写、或者制作一些辅助工具。而模拟键盘输入,尤其是“打字”,是这类自动化任务中非常基础且常见的一环。
在 Java 中,实现这一目标的利器是 java.awt.Robot
类。这个类允许我们生成本地系统的输入事件,就像一个“软件机器人”在替我们操作鼠标和键盘一样。
但是,别高兴得太早,使用 Robot
模拟“打字”并非像想象中那么简单地直接输入字符串。它模拟的是物理按键的按下和释放。理解这一点,是掌握 Robot
的关键。
本文将带你深入理解如何使用 Robot
来模拟键盘输入,从简单的字母数字到复杂的中文,并探讨其中的挑战和最佳实践。
1. 理解 java.awt.Robot
:它模拟的是“手指”
java.awt.Robot
类属于 Java 的 Abstract Window Toolkit (AWT) 包,主要用于自动化测试和演示。它的核心能力是生成本地操作系统级别的输入事件。这意味着:
- 它模拟的是你按下键盘上的某个键(比如
A
键),然后松开。 - 它不理解应用程序内部的文本输入逻辑,也不理解输入法 (IME) 的选词、组句过程。
- 它将事件发送到当前拥有输入焦点的窗口。
因此,如果你尝试用 Robot
模拟输入 “你好”,它做的是模拟按下 n
, i
, h
, a
, o
这五个物理按键。至于这五个按键能否触发输入法、输入法会如何响应、最终是输入 “nihao” 还是 “你好”,完全取决于当时系统的输入法状态、目标输入框的类型以及用户正在使用的具体输入法。
这引出了一个重要的结论:Robot
原生不直接支持模拟输入法(IME)的复杂输入。
2. 模拟简单字符输入:按键的组合与时机
对于英文字母、数字、简单的标点符号、回车、空格等,Robot
是非常有效的,因为这些字符通常对应键盘上的一个或少数几个物理按键(有时需要配合 Shift 键)。
模拟一个按键的过程基本是:
- 按下某个键 (
robot.keyPress(keyCode)
) - 短暂延迟 (
robot.delay(milliseconds)
),给系统处理事件的时间 - 释放该键 (
robot.keyRelease(keyCode)
) - 在输入下一个字符前,再次延迟 (
robot.delay(milliseconds)
),模拟打字间隔
KeyEvent
类提供了大量的虚拟键码常量(以 VK_
开头),用于表示不同的键,比如 KeyEvent.VK_A
代表 A 键,KeyEvent.VK_ENTER
代表回车键,KeyEvent.VK_SHIFT
代表 Shift 键。
对于需要 Shift 键输入的字符(如大写字母、!、@ 等),你需要:
- 按下
Shift
键 (robot.keyPress(KeyEvent.VK_SHIFT)
) - 短暂延迟
- 按下并释放对应的字符键(如
VK_A
对于大写 ‘A’,VK_1
对于 ‘!’) - 短暂延迟
- 释放
Shift
键 (robot.keyRelease(KeyEvent.VK_SHIFT)
)
为了方便模拟打字,我们可以建立一个字符到键码和修饰键的映射。
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;public class SimpleTyper {private Robot robot;private int typingDelay = 50; // 每个键之间的延迟,单位毫秒// 映射字符到KeyEvent虚拟键码,以及是否需要Shift键// {字符, {主键码, 修饰键码 (0表示无)}}private static final Map<Character, int[]> keyEventMap = new HashMap<>();static {// 初始化映射表 (示例部分,实际应用可能需要更完整)// 小写字母for (char c = 'a'; c <= 'z'; c++) {// getExtendedKeyCodeForChar 尝试根据字符获取键码,但不总是精确或跨平台keyEventMap.put(c, new int[]{KeyEvent.getExtendedKeyCodeForChar(c), 0});}// 大写字母for (char c = 'A'; c <= 'Z'; c++) {// 大写字母需要 ShiftkeyEventMap.put(c, new int[]{KeyEvent.getExtendedKeyCodeForChar(c), KeyEvent.VK_SHIFT});}// 数字for (char c = '0'; c <= '9'; c++) {keyEventMap.put(c, new int[]{KeyEvent.getExtendedKeyCodeForChar(c), 0});}// 常用符号 (示例)keyEventMap.put(' ', new int[]{KeyEvent.VK_SPACE, 0});keyEventMap.put('.', new int[]{KeyEvent.VK_PERIOD, 0});keyEventMap.put(',', new int[]{KeyEvent.VK_COMMA, 0});keyEventMap.put('\n', new int[]{KeyEvent.VK_ENTER, 0}); // 换行通常是回车// 更多符号映射... 可以根据KeyEvent常量和键盘布局补充keyEventMap.put('!', new int[]{KeyEvent.VK_1, KeyEvent.VK_SHIFT});keyEventMap.put('@', new int[]{KeyEvent.VK_2, KeyEvent.VK_SHIFT});// ... 等等}public SimpleTyper() throws AWTException {robot = new Robot();// 确保键盘灯同步,但不是必须的robot.setAutoWaitForIdle(true); // 等待系统处理完事件}public void setTypingDelay(int delay) {this.typingDelay = delay;}/*** 模拟输入单个字符* @param c 要输入的字符*/private void typeChar(char c) {int[] keyInfo = keyEventMap.get(c);if (keyInfo != null) {int keyCode = keyInfo[0];int modifier = keyInfo[1];if (modifier != 0) { // 如果需要按下修饰键robot.keyPress(modifier);robot.delay(10); // 按下修饰键后短暂延迟}// 检查主键码是否有效 (getExtendedKeyCodeForChar 可能返回 VK_UNDEFINED)if (keyCode != KeyEvent.VK_UNDEFINED) {robot.keyPress(keyCode);robot.delay(10); // 按下主键后短暂延迟robot.keyRelease(keyCode);} else {System.err.println("Warning: Cannot find exact VK code for character: '" + c + "'. Attempting simple press if possible.");// 对于无法精确映射的字符,可能需要更复杂的处理,或者跳过// 对于某些特殊字符,getExtendedKeyCodeForChar 可能会返回一个可以通过简单keyPress/keyRelease输入的码try {robot.keyPress(KeyEvent.getExtendedKeyCodeForChar(c));robot.delay(10);robot.keyRelease(KeyEvent.getExtendedKeyCodeForChar(c));} catch (IllegalArgumentException e) {System.err.println("Warning: Character '" + c + "' is not directly supported by KeyEvent or map.");}}if (modifier != 0) { // 松开修饰键robot.delay(10); // 松开前短暂延迟robot.keyRelease(modifier);}} else {System.err.println("Warning: Character '" + c + "' not found in keyEventMap and cannot be typed directly.");// 无法映射的字符,这里选择跳过或打印警告}}/*** 模拟输入文本 (简单字符)* @param text 要输入的文本*/public void type(String text) {for (char c : text.toCharArray()) {typeChar(c);robot.delay(typingDelay); // 每个字符之间等待}}// ... main 方法和粘贴方法稍后展示
}
核心要点:
keyEventMap
是将字符'a'
转换为KeyEvent.VK_A
等的桥梁。KeyEvent.getExtendedKeyCodeForChar(c)
是一个有用的辅助方法,但它不保证对所有字符都有效或跨平台一致。对于常用的字符,最好手动在keyEventMap
中明确指定。robot.delay()
至关重要,它能模拟人类的输入速度,并给操作系统和目标应用处理输入事件的时间,提高模拟的可靠性。setAutoWaitForIdle(true)
也可以帮助提高可靠性。- 需要 Shift 的字符(如大写字母、! 等)需要先按下 Shift,再按下主键,最后释放主键和 Shift。顺序和时机很重要。
3. 模拟复杂输入与中文:粘贴大法好!
前面提到,Robot
无法理解或控制输入法。所以,当需要输入中文、日文、韩文或其他需要复杂输入法才能产生的字符时,或者需要输入很长的文本时,模拟每一个按键变得不可行且不可靠。
这时,最常用的、跨平台的、可靠的方法是:将文本复制到系统剪贴板,然后模拟按下粘贴的快捷键。
标准的粘贴快捷键是:
- Windows/Linux:
Ctrl + V
- Mac OS:
Command + V
Java 提供了访问系统剪贴板的功能,配合 Robot
模拟粘贴快捷键,就能优雅地解决这个问题。
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.awt.datatransfer.StringSelection;
import java.awt.Toolkit;
import java.util.HashMap;
import java.util.Map;public class KeyboardTyper { // 类名改回KeyboardTyper,包含所有功能private Robot robot;private int typingDelay = 50;// ... (keyEventMap 和 typeChar 方法同上) ...private static final Map<Character, int[]> keyEventMap = new HashMap<>();static {// 完整的 keyEventMap 初始化,包括简单字符和符号for (char c = 'a'; c <= 'z'; c++) keyEventMap.put(c, new int[]{KeyEvent.getExtendedKeyCodeForChar(c), 0});for (char c = 'A'; c <= 'Z'; c++) keyEventMap.put(c, new int[]{KeyEvent.getExtendedKeyCodeForChar(c), KeyEvent.VK_SHIFT});for (char c = '0'; c <= '9'; c++) keyEventMap.put(c, new int[]{KeyEvent.getExtendedKeyCodeForChar(c), 0});keyEventMap.put(' ', new int[]{KeyEvent.VK_SPACE, 0});keyEventMap.put('.', new int[]{KeyEvent.VK_PERIOD, 0});keyEventMap.put(',', new int[]{KeyEvent.VK_COMMA, 0});keyEventMap.put(';', new int[]{KeyEvent.VK_SEMICOLON, 0});keyEventMap.put('\'', new int[]{KeyEvent.VK_QUOTE, 0});keyEventMap.put('/', new int[]{KeyEvent.VK_SLASH, 0});keyEventMap.put('\\', new int[]{KeyEvent.VK_BACK_SLASH, 0});keyEventMap.put('-', new int[]{KeyEvent.VK_MINUS, 0});keyEventMap.put('=', new int[]{KeyEvent.VK_EQUALS, 0});keyEventMap.put('[', new int[]{KeyEvent.VK_OPEN_BRACKET, 0});keyEventMap.put(']', new int[]{KeyEvent.VK_CLOSE_BRACKET, 0});keyEventMap.put('`', new int[]{KeyEvent.VK_BACK_QUOTE, 0});keyEventMap.put('\n', new int[]{KeyEvent.VK_ENTER, 0});keyEventMap.put('!', new int[]{KeyEvent.VK_1, KeyEvent.VK_SHIFT});keyEventMap.put('@', new int[]{KeyEvent.VK_2, KeyEvent.VK_SHIFT});keyEventMap.put('#', new int[]{KeyEvent.VK_3, KeyEvent.VK_SHIFT});keyEventMap.put('$', new int[]{KeyEvent.VK_4, KeyEvent.VK_SHIFT});keyEventMap.put('%', new int[]{KeyEvent.VK_5, KeyEvent.VK_SHIFT});keyEventMap.put('^', new int[]{KeyEvent.VK_6, KeyEvent.VK_SHIFT});keyEventMap.put('&', new int[]{KeyEvent.VK_7, KeyEvent.VK_SHIFT});keyEventMap.put('*', new int[]{KeyEvent.VK_8, KeyEvent.VK_SHIFT});keyEventMap.put('(', new int[]{KeyEvent.VK_9, KeyEvent.VK_SHIFT});keyEventMap.put(')', new int[]{KeyEvent.VK_0, KeyEvent.VK_SHIFT});keyEventMap.put('_', new int[]{KeyEvent.VK_MINUS, KeyEvent.VK_SHIFT});keyEventMap.put('+', new int[]{KeyEvent.VK_EQUALS, KeyEvent.VK_SHIFT});keyEventMap.put('{', new int[]{KeyEvent.VK_OPEN_BRACKET, KeyEvent.VK_SHIFT});keyEventMap.put('}', new int[]{KeyEvent.VK_CLOSE_BRACKET, KeyEvent.VK_SHIFT});keyEventMap.put('|', new int[]{KeyEvent.VK_BACK_SLASH, KeyEvent.VK_SHIFT});keyEventMap.put(':', new int[]{KeyEvent.VK_SEMICOLON, KeyEvent.VK_SHIFT});keyEventMap.put('"', new int[]{KeyEvent.VK_QUOTE, KeyEvent.VK_SHIFT});keyEventMap.put('<', new int[]{KeyEvent.VK_COMMA, KeyEvent.VK_SHIFT});keyEventMap.put('>', new int[]{KeyEvent.VK_PERIOD, KeyEvent.VK_SHIFT});keyEventMap.put('?', new int[]{KeyEvent.VK_SLASH, KeyEvent.VK_SHIFT});keyEventMap.put('~', new int[]{KeyEvent.VK_BACK_QUOTE, KeyEvent.VK_SHIFT});}public KeyboardTyper() throws AWTException {robot = new Robot();robot.setAutoWaitForIdle(true);}public void setTypingDelay(int delay) {this.typingDelay = delay;}/*** 模拟输入单个字符 (同上)* @param c 要输入的字符*/private void typeChar(char c) {int[] keyInfo = keyEventMap.get(c);if (keyInfo != null) {int keyCode = keyInfo[0];int modifier = keyInfo[1];if (modifier != 0) {robot.keyPress(modifier);robot.delay(10);}if (keyCode != KeyEvent.VK_UNDEFINED) {robot.keyPress(keyCode);robot.delay(10);robot.keyRelease(keyCode);} else {System.err.println("Warning: Cannot find exact VK code for character: '" + c + "'.");}if (modifier != 0) {robot.delay(10);robot.keyRelease(modifier);}} else {System.err.println("Warning: Character '" + c + "' not supported by typer (no map entry).");}}/*** 模拟输入文本 (简单字符,逐个按键)* @param text 要输入的文本*/public void type(String text) {for (char c : text.toCharArray()) {typeChar(c);robot.delay(typingDelay);}}/*** 使用复制粘贴方式输入文本 (更适合中文或复杂字符)* @param text 要输入的文本*/public void paste(String text) {try {// 1. 将文本放入系统剪贴板StringSelection stringSelection = new StringSelection(text);Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stringSelection, null);robot.delay(50); // 等待剪贴板内容设置完成// 2. 模拟按下粘贴快捷键String os = System.getProperty("os.name").toLowerCase();int pasteKey = KeyEvent.VK_V;int pasteModifier;if (os.contains("mac")) {pasteModifier = KeyEvent.VK_META; // Mac 上的 Command 键} else {pasteModifier = KeyEvent.VK_CONTROL; // Windows/Linux 上的 Ctrl 键}robot.keyPress(pasteModifier);robot.keyPress(pasteKey);robot.delay(50); // 按下组合键后短暂延迟robot.keyRelease(pasteKey);robot.keyRelease(pasteModifier);robot.delay(typingDelay); // 粘贴完成后等待一下} catch (Exception e) {System.err.println("Error during paste operation: " + e.getMessage());e.printStackTrace();}}// ... main 方法 ...public static void main(String[] args) {try {KeyboardTyper typer = new KeyboardTyper();typer.setTypingDelay(80); // 设置打字间隔System.out.println("请将光标移动到目标输入框,程序将在5秒后开始模拟输入...");// **重要步骤:给用户时间切换到目标窗口并将光标定位到输入框**Thread.sleep(5000); // 等待 5 秒System.out.println("开始模拟输入...");// 模拟打字英文和数字typer.type("Hello, Robot! This is a test.\n");typer.type("Typing some numbers: 12345.\n");typer.type("And symbols: !@#$%^&*()\n");// 模拟输入中文或其他复杂字符 (推荐使用粘贴)System.out.println("开始模拟粘贴中文...");// 先模拟一个回车,确保在下一行粘贴typer.type("\n");typer.paste("这是一个使用粘贴方式输入的中文段落。模拟打字对于简单的字符有效,但对于中文等复杂输入,粘贴更可靠。\n");typer.paste("再来一句:你好,世界!\n");System.out.println("模拟输入完成。");} catch (AWTException e) {e.printStackTrace();System.err.println("无法创建 Robot 实例。请确保运行环境允许创建 Robot (可能需要更高权限)。");} catch (InterruptedException e) {e.printStackTrace();}}
}
粘贴方法的代码说明:
StringSelection
和Toolkit.getDefaultToolkit().getSystemClipboard().setContents()
:这是 Java 标准库中用于操作系统剪贴板的 API。我们将要输入的文本内容封装成StringSelection
对象,然后设置到系统剪贴板中。- 判断操作系统:使用
System.getProperty("os.name")
获取操作系统名称,以便决定是模拟Ctrl
还是Command
键作为粘贴的修饰键。 - 模拟
Ctrl/Command + V
:同样使用robot.keyPress()
和robot.keyRelease()
来模拟按下修饰键 (VK_CONTROL
或VK_META
) 和VK_V
键,然后再依次释放它们。
重要提醒:
- 焦点问题:
Robot
发送的事件会作用于当前拥有输入焦点的窗口。运行程序后,一定要手动点击你想要输入的文本框,让光标在那里闪烁,确保它获得了焦点。代码中的Thread.sleep(5000)
就是为了给你留出切换窗口的时间。 - 权限问题: 在某些操作系统或安全配置下,Java 程序使用
Robot
可能需要特定的权限,否则可能会抛出AWTException
或模拟无效。 - 键盘布局:
keyEventMap
中的键码基于标准的 US 键盘布局。在其他键盘布局下,某些符号键对应的VK_
代码可能不同。粘贴方法则不受键盘布局影响。 - 可靠性:
Robot
是在操作系统层面模拟事件,其可靠性可能受到系统负载、窗口状态变化、目标应用响应速度等多种因素影响。使用robot.delay()
和robot.setAutoWaitForIdle(true)
可以提高稳定性,但不能保证在所有情况下都百分之百成功。
4. 运行和测试
- 将完整的代码保存为
KeyboardTyper.java
。 - 使用
javac KeyboardTyper.java
编译。 - 使用
java KeyboardTyper
运行。 - 关键一步: 看到控制台输出 “请将光标移动到目标输入框…” 后,迅速用鼠标点击你想要模拟输入的窗口(例如记事本、浏览器中的文本框等),确保光标在里面闪烁。
- 等待 5 秒后,程序将自动开始模拟输入和粘贴。
总结
通过 java.awt.Robot
,我们可以实现强大的键盘自动化功能。
- 对于简单的字符(英文字母、数字、基础标点等),可以通过模拟单个按键的按下和释放(可能需要配合 Shift 等修饰键)来实现,这需要建立字符到键码的映射并注意按键时序和延迟。
- 对于复杂字符、中文或长文本,由于
Robot
不理解输入法逻辑,最可靠和常用的方法是将文本复制到系统剪贴板,然后模拟按下系统的粘贴快捷键。
无论使用哪种方法,理解 Robot
的工作原理(模拟物理按键),处理好窗口焦点,并加入适当的延迟,是确保模拟输入成功的关键。虽然 Robot
提供了底层控制能力,但也意味着你需要处理好各种系统层面的细节和潜在的不可靠性。
希望本文能帮助你理解并使用 java.awt.Robot
在 Java 中实现键盘输入自动化!
相关文章:
用Java模拟打字:深入解析 java.awt.Robot 的键盘控制艺术
作为开发者,我们有时会遇到需要自动化用户界面交互的场景,比如自动化测试、脚本编写、或者制作一些辅助工具。而模拟键盘输入,尤其是“打字”,是这类自动化任务中非常基础且常见的一环。 在 Java 中,实现这一目标的利…...
基于STM32、HAL库的ATSHA204A安全验证及加密芯片驱动程序设计
一、简介: ATSHA204A是Microchip公司生产的一款高性能加密认证芯片,主要特性包括: 基于SHA-256哈希算法的安全认证 4.5KB EEPROM存储空间(可配置为密钥存储、OTP区域等) 唯一的72位序列号 支持I2C和单线接口 工作…...
2.2.1goweb内置的 HTTP 处理程序
net/http 使用源码分析 在 Go 语言的 HTTP 服务器里,HTTP handler 是实现了http.Handler接口的对象。该接口定义如下: type Handler interface {ServeHTTP(ResponseWriter, *Request) }ServeHTTP方法接收两个参数: http.ResponseWriter&am…...
vscode以管理员身份运行报错
1. 问题现象 对vscode设置了管理员权限,但是打开文件时报错或闪退。 2. 解决方法 可以看一下官方网址:[Visual Studio Code on Windows](https://code.visualstudio.com/docs/setup/windows#_unable-to-run-as-admin-when-applocker-is-enabled) 2.1 …...
【Unity】 Dropdown默认选择不选择任何选项
你需要新建一个text文本并将其拖入Placeholder里面,这样你就可以在代码里面设置value-1了,从而实现默认为空...
gem5教程 第七章 如何在 gem 5 中运行我自己的程序
首先,您必须决定是否运行完整系统(FS)或系统调用仿真(SE)。 在 gem5 仿真器中,“完整系统仿真(Full System Simulation, FS)”与“系统调用仿真(System Call Emulation, SE)”是两种不同的仿真模式,各自有其特点和适用场景。下面是对这两种模式的比较: 1. 完整系统仿…...
Java实现基数排序算法
1. 基数排序原理图解 基数排序是一种非比较的排序算法,其核心思想是通过将整数按位数切割成不同的数字,然后按每个位数分别比较。具体步骤如下: 1. 确定最大值:找到数组中的最大值,以确定需要处理的位数。 2. 分配到桶…...
Python项目-支持自然语言处理
研究生组-自然语言处理-第一章节 Python学习,数据挖掘基础 项目地址:pythonbook: 人工智能实战——从 Python 入门到机器学习...
科技助力防灾减灾:卫星电话走进应急救援队伍
在自然灾害与突发事件频发的当下,通信保障已成为应急救援的“生命线”。传统地面通信网络易受极端天气、地形环境等因素制约,而卫星通信技术的突破,尤其是国产天通卫星系统与北斗系统的成熟应用,正推动救援通信体系迈入全天候、无…...
Android adb 安装应用失败(安装次数限制)
adb安装应用失败 前言平台安装失败现象解决 前言 Android Debug Bridge (ADB) 是一个功能强大的命令行工具,用于与 Android 设备通信。 安装 APK 文件: 使用命令 adb install <apk文件路径> 可以将 APK 文件安装到设备上。如果需要覆盖安装&…...
100天精通Python挑战总览 | 零基础到应用实战!
目录 ✨ 为什么发起100天挑战?✨整体学习路线规划第一阶段|基础篇(第1天 - 第50天)第二阶段|应用篇(第51天 - 第100天)Web开发篇爬虫篇数据分析篇AI入门篇 🏆为什么这么划分…...
预训练大模型与元训练大模型在医疗AI项目中的选型对比分析
简要版: 以下是对预训练大模型与元训练大模型(基于元学习/Meta-Learning)在医疗AI项目中选型对比的总结表格: 对比维度预训练大模型元训练大模型(基于元学习)技术基础基于海量通用数据预训练,通过微调适配具体任务(如GPT-4、LLaMA)通过元学习框架训练,支持快速适应新…...
【JavaScript】相等运算符、条件运算符
1、相等运算符 (1)(相等) 相等运算符用来比较两个值是否相等,如果相等会返回true,否则返回false <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"…...
企业用电管理革新利器 —— Acrel-3000 电能管理系统应用解析
电能,以其方便传输、易于转换、便于控制等特性,早已成为广大企事业单位生产、办公的核心能量来源。在 “双碳” 战略目标的宏大背景下,能源结构转型加速推进,电能清洁、高效、零排放的特点愈发凸显。在能源消费侧,“以…...
学生管理系统审计
1.环境搭建 项目地址: https://gitee.com/huang-yk/student-manage 项目下载到本地后IDEA打开,等待项目加载 配置Maven,修改数据库配置文件 然后启动 访问 2.代码审计 1.垂直越权未授权敏感信息泄露 找到拦截器看看对登录做了什么校验 Override public b…...
OpenGL----OpenGL纹理与纹理缓存区
在现代计算机图形学中,纹理(Texture)是一个至关重要的概念。它不仅可以为几何体表面添加细节和真实感,还可以用于实现各种复杂的视觉效果和数据处理。在OpenGL中,纹理的应用范围非常广泛,从基本的颜色映射到高级的阴影映射、环境映射等。本文将深入探讨OpenGL纹理与纹理缓…...
QT开发技术【qcustomplot 曲线与鼠标十字功能】
一、效果 二、代码 #include "obsersingle.h" #include "ui_obsersingle.h" #pragma execution_character_set("utf-8")右键菜单acion回调 // 适应窗口大小 void ObserSingle::RescaleActionFun::fun(ObserSingle *form) {// 自适应y轴数据范围…...
[特殊字符] 大模型后训练指南:从毛坯引擎到智能助手的进化之路 [特殊字符]️
最近看了MIT 6.S191 2025这个讲座感觉讲的挺好的,然后写了一篇总结,大家感兴趣的话可以直接看视频,链接我放到文章最后。 🎯 讲座核心 这个讲座主要讲的是,当我们有了一个基础的大语言模型(就像刚出厂的毛…...
厚铜pcb生产厂家哪家好?
在为您的项目选择厚铜PCB供应商时,技术实力、生产经验与交付能力是决定产品可靠性的关键。随着新能源汽车、工业电源、5G通信等领域对高电流承载、高效散热的需求激增,厚铜PCB(铜厚3oz以上)的工艺门槛不断提升。本文结合行业头部企…...
【重走C++学习之路】22、C++11语法
目录 一、列表初始化 1.1 {}初始化 1.2 std::initializer_list 二、变量类型推导 2.1 auto 2.2 decltype 三、右值引用和移动语义 3.1 左值与左值引用 3.2 右值与右值引用 3.3 左值引用与右值引用比较 3.4 右值引用使用场景和意义 3.5 move 3.6 完美转发和万能引…...
Spring Security授权管理
授权是Spring Security的核心功能之一,是根据用户的权限来控制用户访问资源的过程,拥有资源的访问权限则可正常访问,没有访问的权限时则会被拒绝访问。认证是为了保证用户身份的合法性,而授权则是为了更细粒度地对隐私数据进行划分…...
2025A卷-正整数到Excel编号之间的转换
题目描述 用过 excel 的都知道excel的列编号是这样的: a b c … z aa ab ac … az ba bb bc … yz za zb zc … zz aaa aab aac … 分别代表以下编号: 1 2 3 … 26 27 28 29 … 52 53 54 55 … 676 677 678 679 … 702 703 704 705 … 请写个函数&…...
算法设计与分析(期末试卷)
目录 一、频度计算(15 分) 二、项目工期问题(20 分) 三、TSP 问题的贪心算法(15 分) 四、“秤心如意”(15 分) 五、工作指派问题(20 分) 六、计算复杂度…...
springboot(2.6.13)自定义用户授权管理
1.自定义用户访问控制 a.重写configure(HttpSecurity http)方法 在自定义配置类SecurityConfig中重写 Override protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/").permitAll().antMatchers("/deta…...
JavaWeb:vueaxios
一、简介 什么是vue? 快速入门 <!-- 3.准备视图元素 --><div id"app"><!-- 6.数据渲染 --><h1>{{ msg }}</h1></div><script type"module">// 1.引入vueimport { createApp, ref } from https://unpkg.com/vu…...
uniapp常用
1.下载文件带进度提示 <template> <view> <button click"startDownload">下载文件</button> <progress :percent"progress" stroke-width"3" /> </view> </template> <…...
etcd 的安装及使用
介绍 Etcd 是一个 golang 编写的分布式、高可用的一致性键值存储系统,用于配置共享和服务发现等。它使用 Raft 一致性算法来保持集群数据的一致性,且客户端通过长连接 watch 功能,能够及时收到数据变化通知,相较于 Zookeepe…...
uni-app vue3 实现72小时倒计时功能
功能介绍 ,数组项有一个下单时间 ,比如今天下单在72小时内可以继续支付,超过则默认取消订单 页面按钮处 加上倒计时 <!-- 倒计时 --> <text v-if"item.timeLeft > 0">{{ formatTime(item.remaining) }}</text&g…...
【C语言】初阶算法相关习题(二)
个人主页:夜晚中的人海 文章目录 ⭐一、两数之和🏠二、珠玑妙算🎡三、寻找奇数🚀四、截取字符串🎉五、寻找峰值 ⭐一、两数之和 题目描述:两数之和 解题思路: 1.先创建一个动态分配的数组ret&a…...
Flutter 学习之旅 之 Flutter 和 Android 原生 实现数据交互的MethodChanel和EventChannel方式的简单整理
Flutter 学习之旅 之 Flutter 和 Android 原生 实现数据交互的MethodChanel和EventChannel方式的简单整理 目录 Flutter 学习之旅 之 Flutter 和 Android 原生 实现数据交互的MethodChanel和EventChannel方式的简单整理 一、简单介绍 二、Flutter 和 Android 原生之间的数据…...
STM32的SysTick
SysTick介绍 定义:Systick,即滴答定时器,是内核中的一个特殊定时器,用于提供系统级的定时服务。该定时器是一个24位的递减计数器,具有自动重载值寄存器的功能。当计数器到达自动重载值时,它会自动重新加载…...
【JS事件循环机制event-loop】
目录 0、总结1、Event-Loop 概念2、宏任务-微任务3、事件循环执行机制4、调用栈5、示例 0、总结 Tasks execute in order, and the browser may render between them 【宏任务按序执行,浏览器可以在它们之间进行渲染】Microtasks execute in order, and are execut…...
对比N+1查询和关联聚合查询
通常我们管第一种模式叫 “N1 查询”,第二种叫 “关联聚合查询”。下面从几个角度来比较,帮助你做出选择。 1. 性能与资源消耗 方案SQL 语句数网络往返次数数据库负载Java 处理N1 查询(先查项目,再遍历项目查设备状态数ÿ…...
优化 Flutter 应用启动:从冷启动到就绪仅需 2 秒
冷启动序列剖析:冷启动时,Flutter 应用需经历引擎和 Dart VM 初始化、启动 Dart Isolate、渲染第一帧等步骤。Android 和 iOS 系统分别通过启动屏幕和 Storyboard 缓解启动延迟。应用大小、初始化工作、调试模式下的 JIT 编译等因素会影响冷启动时间。优…...
牟乃夏《ArcGIS Engine 地理信息系统开发教程》学习笔记 4-空间分析与高级功能开发
目录 一、核心组件与接口回顾 (一)空间分析基础架构 (二)网络分析模块 二、矢量数据空间分析实战 (一)缓冲区分析 (二)叠加分析(以裁剪为例) 三、栅格…...
UE 滚动提示条材质制作
需要两个贴图 先制作条纹屏闪 这里RGB输出连到alpha,0为白色,到1就为黑色了 因为这个图片是RGB输出代表三个图片,看贴图颜色就知道了,然后把这三个相加一下;链接自发光颜色, 这里设置速度变量 通过网盘分…...
金融业数字化转型——深入解读77页2024年中国金融体系指标大全【附全文阅读】
本文主要介绍了金融业通行宝典中国金融体系指标大全的内容,包括央行体系、商业银行体系、非银金融机构与地方金融组织的各项指标。文章详细分析了美联储资产负債表的结构,并概述了美日欧等主要经济体资产负债表状况。 重点内容: 1. 央行体系是金融分析的重点。 2. 美联储资产…...
研究:大模型输出一致性:确定性与随机性的场景化平衡
大模型在相同输入下的输出是否一致,本质上取决于其设计目标、任务性质以及技术实现方式。这一问题需要从技术原理、应用场景、用户需求三个维度进行深度分析: 一、技术实现:确定性与随机性的平衡 模型架构的确定性基础 大模型的核心参数(如权重矩阵)在训练完成后是固定的…...
数据分析1
一、常用数据处理模块Numpy Numpy常用于高性能计算,在机器学习常常作为传递数据的容器。提供了两种基本对象:ndarray、ufunc。 ndarray具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组。 ufunc提供了对数组快速运算的标准数学函数。 ndar…...
vmare pro安装报错用户在命令行上发出了EULAS_AGREED=1,表示不接受许可协议的错误解决方法
问题现状和原因 用户在命令行上发出了EULAS_AGREED1,表示不接受许可协议的错误。 以上错误主要原因是因为机器安装过了vmare 卸载时没有卸载干净导致的。 解决方法: 1、控制面板-程序和功能-卸载程序。找到vamre卸载掉。 2、打开开始菜单输入注册表 …...
《Linux篇》基础开发工具——vim详细介绍
文章目录 1.软件包管理1.1 什么是软件包1.2 Linux软件生态 2.编辑器vim2.1 vim的正常/命令模式2.2 vim的末行模式2.3 vim的插入模式 3.配置vim 1.软件包管理 我们先来看一下再Linux是那个如何安装软件? 源码安装:软件是存在相互依赖的关系的࿰…...
AI图片跳舞生成视频,animate X本地部署。
本期内容打包限时免费下载https://www.kdocs.cn/l/cnQ5lNU5DFZB 对比不同算法,使用同一组图片和舞蹈视频。animate X官网,下载项目解压。按照官方教程下载模型,项目包和命名好的模型包已上传网盘,放到解压目录下即可。 安装好cond…...
Web技术与Apache网站部署
一、Web 基础与 HTTP 协议 1.1 静态网页与动态网页 静态网页 定义:由纯 HTML、CSS、JavaScript 构成,文件扩展名为 .htm 或 .html。内容在服务器生成后固定不变,仅通过客户端脚本(如 JS)实现视觉动态效果(…...
第七章:Server/Client Communication
Chapter 7: Server/Client Communication 从工具集成到服务器通信:如何让AI“远程协作”? 在上一章的工具与LLM集成中,我们已经能让AI调用真实世界的工具。但你是否想过:如果多个用户同时请求天气查询,或者需要远程控…...
Linux调试器 - gdb使用指南
目录 一、背景知识 二、开始使用 gdb (一)查看源代码相关指令 (二)程序执行控制指令 (三)断点相关指令 (四)变量操作相关指令 (五)其他常用指令 在Li…...
C++面试常青客:LRUCache最近最少使用算法
C面试常青客:LRUCache最近最少使用算法 文章目录 C面试常青客:LRUCache最近最少使用算法1.背景🏆2.原理🚀2.1基本原理2.2核心特性 3.结构3.1为什么需要 list<pair<int,int>>(双向链表)…...
【含文档+PPT+源码】基于微信小程序的社交摄影约拍平台的设计与实现
项目介绍 本课程演示的是一款基于微信小程序的社交摄影约拍平台的设计与实现,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系…...
jetson nano上Ubuntu系统调用摄像头bug
今天在做一个比赛的时候,通过调用摄像头做检测并输出目标角度和距离。刚开始用的是 cv::VideoCapture cap; cap.open("/dev/video0");没有任何问题,使用pnp解算得到的角度和距离都是正确的,画面也是小画面。 后面加了一些功能&…...
用Python做有趣的AI项目5:AI 画画机器人(图像风格迁移)
这个项目将使用 PyTorch 实现图像风格迁移(Neural Style Transfer),让一张图片看起来具有另一张图片的“艺术风格”。 🔧 开发环境建议 Python 3.8 PyTorch(pip install torch torchvision) PIL&#x…...
一种用于从视网膜图像中识别疾病的 BERT 式自监督学习 CNN
大家读完觉得有帮助记得关注和点赞!!! 抽象 在医学成像领域,深度学习的出现,尤其是卷积神经网络 (CNN) 的应用,彻底改变了医学影像的分析和解释。然而,深度学习方法通常依…...