Java 学习笔记(进阶篇3)

1. 美化界面

关键逻辑 1:

// 相对路径:直接从项目的 src 目录开始写,不包含 D:\ 和个人名字
ImageIcon bg = new ImageIcon("src/image/background.png");
JLabel background = new JLabel(bg);

这两行代码是 Swing 中加载并显示图片的经典组合,核心是通过两个类的协作完成 “读取图片→展示图片” 的过程。

第一行:ImageIcon bg = new ImageIcon("src/image/background.png");

(1) ImageIcon 类
它是 Swing 专门用于处理图像的工具类,主要功能是加载图像文件(支持 png、jpg、gif 等格式)并存储图像数据。你可以把它理解为 “图像的容器”—— 它会帮你完成读取文件、解析图像数据的底层工作,最终提供一个可供 Swing 组件直接使用的图像对象。

(2) new ImageIcon(路径)
这是调用 ImageIcon 的构造方法,参数是图片的路径(这里用的是相对路径 src/image/background.png)。执行这行代码时:

  • 程序会根据路径找到 background.png 图片文件;
  • 读取图片的像素、色彩等数据;
  • 创建一个 ImageIcon 对象 bg,这个对象内部就 “装着” 这张图片的所有数据。
第二行:JLabel background = new JLabel(bg);

作用:创建一个标签组件,将前面加载好的图片设置为标签的内容,让图片能在界面上显示。

(1) JLabel 类
它是 Swing 中的 “标签” 组件,本质是一个 “小型容器”,可以用来显示文本图像(或两者同时显示)。它的作用类似网页中的 <img> 标签 —— 本身不存储图像数据,而是作为 “展示载体”。

(2) new JLabel(bg)
这是调用 JLabel 的构造方法,参数是前面创建的 ImageIcon 对象 bg(装着图片数据)。执行这行代码时:

  • 创建一个 JLabel 对象 background
  • 告诉这个标签:“你的显示内容是 bg 里的图片”;
  • 此时标签已经 “绑定” 了图片,但还不会直接显示在窗口上(需要后续步骤)。

关键逻辑 2:

  this.getContentPane().add(background);  

(1) this:指当前的 JFrame 对象(假设这句代码写在继承自 JFrame 的类中,比如之前的 MyJFrame3)。

(2) this.getContentPane()

  • getContentPane() 是 JFrame 类的一个方法,作用是获取当前窗口的 “内容面板”(ContentPane 对象)
  • 这个方法返回的 ContentPane 才是真正能存放组件的容器。

(3) .add(background)

  • 调用 ContentPane 的 add() 方法,将组件(这里是 background 标签,也就是包含图片的标签)添加到内容面板中。
  • 只有添加到内容面板后,background 标签(以及它包含的图片)才能在窗口中显示出来。

关键逻辑 3:

jLabel.setBorder(new BevelBorder(1));

这句话的作用是给 JLabel 组件添加一个 “凹陷” 效果的立体边框,让组件(比如显示图片的标签)看起来有 “凹下去” 的视觉层次感。

  • jLabel:要添加边框的目标组件(比如显示图片的标签、文本标签等)。
  • setBorder(...)JLabel 继承的方法(来自父类 JComponent),作用是给组件设置边框(参数是一个边框对象)。
  • new BevelBorder(1):创建一个 “斜面边框” 对象,参数 1 对应 BevelBorder.LOWERED,即凹陷效果

2. 移动图片

关键逻辑 1:为什么需要 else ?

for (int i = 0; i < tempArr.length; i++) {  // 遍历一维数组tempArr的每个元素if (tempArr[i] == 0) {  // 如果当前元素是0(特殊值)x = i / 4;          // 计算0在二维数组中的行索引xy = i % 4;          // 计算0在二维数组中的列索引y} else {  // 如果当前元素不是0(普通值)data[i / 4][i % 4] = tempArr[i];  // 将值存入二维数组的对应位置}
}

(1) 在拼图游戏中,0 通常代表 “空白块”(没有数字的空位),它的作用和其他带数字的拼图块完全不同 —— 其他数字块需要被显示在界面上,而空白块的核心作用是作为 “可移动的空位”,让周围的数字块可以移动到这里。因此,0 不需要像普通数字那样被 “记录到数据数组 data 中”,而是需要单独记录它的位置x,y),这是由拼图游戏的核心逻辑决定的。

(2) 功能定位:0 是 “空位”,而非 “拼图块”

拼图游戏的本质是:通过移动数字块填补空白,最终让所有数字块回到正确位置。

  • 普通数字(如 1,2,3...)是 “需要被显示和移动的拼图块”,它们的位置需要被 data 数组记录(data[x][y] = 数字),用于在界面上显示对应的数字图片。
  • 0 代表 “空白区域”(没有拼图块的位置),它不需要被显示(界面上这里是空的),因此不需要存入 data 数组
关键逻辑 2:关于 x-- 的理解、关于 initImage( ); 的理解
System.out.println("向下移动");
data[x][y] = data[x - 1][y];
data[x - 1][y] = 0;
x--;  //更新元素当前位置的行索引,记录移动后的新位置
initImage();  //根据修改后的数据重新绘制界面,刷新显示效果

(1) 这里的 x、y 表示空白方块,假设 data 数组中,0 代表空白方块,其他数字代表有内容的方块。现在有一个空白方块在 (x=2, y=1) 位置,它上方(x-1=1, y=1)有一个值为 5 的方块,我们要让 5 向下移动到空白位置。

(2) 代码逻辑就变成了:

① System.out.println("向下移动");
提示:有元素要移动到下方的空白位置。

② data[x][y] = data[x - 1][y];
这里 x=2, y=1 是空白位置,x-1=1, y=1 是上方的有值元素(5)。
意思是:把上方的 5 放到空白位置 (2,1) 上。
执行后,空白位置被 5 填充,原来的 5 位置还没清空。

③ data[x - 1][y] = 0;
把原来 5 所在的位置 (1,1) 设为 0(变成新的空白位置)。
现在,5 成功移动到了下方的空白位置,而原来的位置变成了新的空白。

④ x--;
空白位置原本在 x=2,现在移动到了上方的 x=1(原来 5 的位置)。
用 x-- 更新空白位置的坐标(从 2 变成 1),这样如果还要继续移动(比如 5 还能再往下移),程序就知道 “现在的空白位置在 x=1”,可以继续判断下方是否还有空白。

⑤ initImage();
刷新界面,让你看到 “5 移动到了下方,原来的位置变成了空白” 的效果。

3. 查看完整图片、作弊码和判断胜利

关键逻辑 1:整体逻辑铺垫
int code = e.getKeyCode();
  • e 是一个键盘事件对象(比如KeyEvent),当用户按下键盘时会触发这个事件。
  • getKeyCode() 是事件对象的方法,用于获取用户按下的按键对应的 “键码”(每个按键有唯一的数字编码,比如 65 对应字母 A,40 对应下箭头等)。
  • 这行代码的作用是:把用户按下的按键编码存到变量code中,方便后续判断按的是哪个键。
关键逻辑 2:二维数组的 “静态初始化”
else if (code == 87) {data = new int[][]{{1, 2, 3, 4},    // 拼图第1行(数组索引0行):对应1、2、3、4号拼图块{5, 6, 7, 8},    // 拼图第2行(数组索引1行):对应5、6、7、8号拼图块{9, 10, 11, 12}, // 拼图第3行(数组索引2行):对应9、10、11、12号拼图块{13, 14, 15, 0}  // 拼图第4行(数组索引3行):13、14、15号块 + 0(空白块)};initImage(); // 重新绘制界面,让正确的拼图布局和胜利图片显示出来
}

① 首先,这段代码的本质是 创建一个 4 行 4 列的 int 类型二维数组,并直接给每个位置赋值,然后把这个 “正确排列的数组” 赋值给data变量(覆盖原来打乱的拼图数据)。

② 二维数组的 “行” 和 “列”

  • 里面的每一组{}代表 “一行”,比如{1,2,3,4}是第 1 行;每行里的数字(1、2、3、4)是 “列”,分别对应第 1 列、第 2 列、第 3 列、第 4 列。
  • 整个数组是 4 行 4 列,正好对应你游戏里的 “4x4 拼图格子”。

4. 计步和菜单业务实现

关键逻辑 1:应用场景和定位事件源头

Object obj = e.getSource();

① 先铺垫:这行代码的 “上下文”—— 事件处理:

  • 当用户做了某个交互操作(比如点击按钮、选择菜单、输入文本),程序会生成一个 “事件对象”(通常用变量e表示,比如ActionEvent eMouseEvent e),这个e里包含了 “这个事件的所有信息”—— 而 e.getSource() 就是从这些信息里,找到 “触发这个事件的源头组件”
  • 你的拼图游戏有 “重新游戏”“关闭游戏” 两个菜单按钮(JMenuItem),如果给这两个按钮共用一个事件处理器(比如都绑定到同一个 ActionListener),当用户点击其中一个时,程序需要知道 “到底点的是哪个按钮”—— 这时候就需要 e.getSource() 来定位 “点击的源头”。

② Object obj:用 Object 类型接收源头,因为 “事件的触发源头” 可能是任何组件(比如 JButton 按钮、JTextField 文本框、JMenuItem 菜单、JLabel 标签等),这些组件都是不同的类,但它们有一个共同的父类 ——Object

假设没有多态,我们要接收 e.getSource() 的返回值会面临什么问题?

  • 如果源头是 JMenuItem,就需要写 JMenuItem obj = e.getSource();
  • 如果源头是 JButton,又需要写 JButton obj = e.getSource();
  • 如果有 10 种不同的组件触发事件,就要写 10 种不同类型的接收代码 —— 这会导致代码极度冗余,无法兼容多种场景。

关键逻辑 2:模态窗口(Modal Window)

jDialog.setModal(true); 

它是 Swing 界面开发中控制 “用户操作流程” 的关键设置,尤其适合像 “登录弹窗”“确认提示框” 这类需要用户 “先处理完当前窗口,才能操作其他窗口” 的场景。反之,如果设置为 setModal(false)(非模态),弹窗弹出后,用户可以随意切换到其他窗口操作,不用管这个弹窗。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

BFD 概述

BFD简介1.BFD:Bidirectional Forwarding Detection,双向转发检查概述&#xff1a;毫秒级链路故障检查&#xff0c;通常结合三层协议&#xff08;如静态路由、vrrp、 ospf、 BGP等&#xff09;实现链路故障快速切换。作用&#xff1a;① 检测二层非直连故障② 加快三层协议收敛底…

【嵌入式DIY实例-ESP32篇】-Flappy Bird游戏

Flappy Bird游戏 文章目录 Flappy Bird游戏 1、游戏介绍 2、硬件准备与接线 3、代码实现 《Flappy Bird》游戏以其引人入胜的玩法和简约的设计风靡全球。本文将探讨如何使用 OLED SSD1306 显示屏和 ESP32 微控制器重现这款经典游戏。这个 DIY 项目不仅充满乐趣,也是学习编程和…

[数据结构——lesson2.顺序表]

目录 学习目标 引言 1.什么是线性表&#xff1f; 2.什么是顺序表&#xff1f; 2.1概念及结构 2.2 接口实现 2.2.1顺序表的功能 1.顺序表的初始化 2.打印数据 3.尾插数据 (1)检查空间 (2)插入数据 4.尾删数据 5.头插数据 6.头删数据 7.数据查找 8.指定位置数据…

ChatGPT大模型训练指南:如何借助动态代理IP提高训练效率

随着人工智能技术的飞速发展&#xff0c;ChatGPT等大型语言模型&#xff08;LLM&#xff09;已成为科技界和产业界关注的焦点。模型的训练过程耗时、耗资源且对网络环境要求极高。尤其是在需要模拟真实用户行为、进行大规模数据爬取或分布式训练的场景下&#xff0c;单一IP地址…

Docker 学习笔记(六):多容器管理与集群部署实践

Docker Docker-compose 单个 Dockerfile 可定义单容器应用&#xff0c;但日常工作中&#xff0c;Web 项目等常需 Web 服务、数据库、负载均衡等多容器配合&#xff0c;手动按序启停容器会导致维护量大、效率低。 Docker Compose 是高效的多容器管理工具&#xff0c;通过单个 do…

C++类和对象初识

面向过程 1.1 面向过程特点 1.2 通俗解释&#xff1a;煮方便面 1.3 面向过程实现代码 1.4 特点总结面向对象 2.1 面向对象特点 2.2 通俗解释&#xff1a;对象协作思维 2.3 面向对象实现代码 2.4 特点总结面向对象和面向过程总结C 面向对象介绍 4.1 面向对象三大基本特征封装&am…

C++ Int128 —— 128位有符号整数类实现剖析

&#x1f9e0; C Int128 —— 128位有符号整数类实现剖析 引用&#xff1a;openppp2/ppp/Int128.h &#x1f3d7;️ 1. 存储结构设计 #mermaid-svg-2JDFsdz6MTbX253D {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-sv…

【C 语言生成指定范围随机数(整数 + 小数):原理、实现与避坑指南】

概述 在 C 语言开发中&#xff0c;生成指定范围的随机数是高频需求&#xff08;如游戏随机道具、数据模拟、测试用例生成等&#xff09;。但很多新手会卡在 “范围控制”“随机数重复”“小数生成” 等问题上。本文结合实战场景&#xff0c;从原理到代码详细讲解如何生成 1100、…

一个简单的langgraph agent系统

本文基于langgraph的预制件 Agent Chat UI和《搭建一个本地langgraph服务》中的本地服务构建一个简单的agent系统。 说明&#xff1a;Agent Chat UI需要nodejs版本18及以上&#xff0c;而nodejs18需要的glibc版本为2.28&#xff0c;本人使用操作系统为ubuntu18.04&#xff0c;g…

通过SSH来推送本地文件夹到Github

配置SSH git使用SSH配置&#xff0c; 初始需要以下三个步骤 使用秘钥生成工具生成rsa秘钥和公钥 将rsa公钥添加到代码托管平台 将rsa秘钥添加到ssh-agent中&#xff0c;为ssh client指定使用的秘钥文件 具体操作如下&#xff1a; 第一步&#xff1a;检查本地主机是否已经存在…

视频转webp批量处理工具哪个好?这里有答案

你是不是也遇到过这样的困扰&#xff1a;手机里存满了精彩的短视频&#xff0c;想做成动图分享到社交媒体&#xff0c;却发现转换后的GIF文件巨大无比&#xff0c;画质还惨不忍睹&#xff1f;要怎么把手机视频转webp&#xff0c;才能既保持高清画质&#xff0c;又能大幅减小文件…

【Fastjson】Fastjson2 在不同 Modules 模块包下,@JSONField name映射无法反序列化的 BUG 及解决

问题&#xff1a;在使用 alibaba fastjson2 做 JSONField 字段名映射时&#xff0c;在同模块包下 Flink Jar 任务正常映射&#xff0c;本地测试正常映射&#xff0c;但是将两个模块包上传至 Flink Cluster 之后&#xff0c;出现反序列化异常&#xff0c;子模块无法反序列化父模…

Go语言基础---数据类型间的故事

Go语言基础—数据类型间的故事 目录 前言基本数据类型 整形字节特殊整形unsafe.Sizeof数字字面量语法浮点型布尔值字符串byte和rune类型 运算符 算术运算符关系运算符逻辑运算符位运算符赋值运算符 前言 Go语言是Google开发的一种静态强类型、编译型语言。Go语言语法与C相近…

dedecms软件等级★号改成图片图标显示的办法

我们在用到dedecms织梦的软件模型&#xff0c;在调用软件星级的时候&#xff0c;要把默认的星号改为图片&#xff0c;这个要怎么操作呢&#xff1f;1、软件模型管理里面-字段管理-字段配置softrankislink一行改为&#xff1a;<field:softrank itemname软件等级 typeint isnu…

windows下安装claude code+国产大模型glm4.5接入(无需科学上网)

下载安装node.js https://nodejs.org/en/download 安装版.msi 直接下载安装即可 免安装版.zip 1.解压下载的压缩包 2.创建数据缓存存储目录cache和全局安装工具目录global 3.配置环境变量 【我的电脑】右键选中【属性】-> 找到【高级系统设置】-> 右下角【环境变量…

嵌入式 - ARM4

裸机实现LED闪烁一、启动代码1. 异常向量表配置1. .global汇编器指令&#xff0c;全局定义标签_start&#xff0c;作为汇编程序的默认起点2. 配置标签配置标签时可以前置加_ &#xff0c;以便和普通标签或系统标签做区分3. 异常向量表ARM架构规定异常向量表位置固定&#xff0c…

《C++ 108好库》之2 多线程库thread,mutex,condition_variable,this_thread

《C 108好库》之之2 多线程库thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_thread《C 108好库》之2 多线程库thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_threadstd::thread类​​互斥量&#xff08;Mutex&#xff09;…

Android系统框架知识系列(二十):专题延伸:JVM vs ART/Dalvik - Android运行时演进深度解析

​关键词​&#xff1a;运行时优化、AOT编译、JIT编译、内存管理、电池效率、性能分析一、Android运行时演进背景1. 移动环境的特殊挑战Android运行时环境的演进源于移动设备的独特限制&#xff1a;​移动设备约束条件​&#xff1a;​有限的内存资源​&#xff1a;早期设备仅1…

ubuntu 22 安装轻量级桌面Xfce并使用xrdp远程桌面连接

1.安装Xfce:sudo apt install xubuntu-desktop -y2.安装xrdp:sudo apt install xrdp -y3.配置xrdp&#xff0c;nano /etc/xrdp/xrdp.ini:[Globals] ... port3389 ; 远程连接端口&#xff0c;默认是3389&#xff0c;可以改成自己喜欢的端口... ; ; Session types ;; Some sess…

【Flask】测试平台开发,数据看板开发-第二十一篇

概述&#xff1a;在前面我们已经实现了我们的产品创建管理&#xff0c;应用管理管理&#xff0c;需求提测管理但是每周提测了多少需求&#xff0c;创建了哪些产品&#xff0c;我们是不是看着不是很直观&#xff0c;接下来我们就需要开发一个数据看板功能&#xff0c;实现能够看…