Skip to content

Java - Swing设计与MVC模式

Swing 0364caec8ceb01cc0ca0c3200dd494da_MD5

组件: 最外层的窗体叫做JFrame: 4b08fa02d1233822ad16484bfe8ab378_MD5 可以下拉的菜单: 12b00bb7eff5a91a351f681a5f276ccb_MD5 JLable:呈现文字/图像的容器,带有背景. 2261501646fa2ce2e6db8100fb2a74d0_MD5


df301f868417629d6c5060cdd2bd97d0_MD5 f193a236ac8b3b3e62ae429f1dde41dd_MD5 1. 大致了解一下项目结构; 2. 界面默认是隐藏的,因此需要设置可见性. 7ee053562874c5c45a0be67303d17ae0_MD5 这样可以一下子弹出来三个界面.


我们需要解耦合. 主界面: 0aaad4abc1f1bf694e8bb2fe1bef304b_MD5 这个继承非常巧妙. 其余两个界面也是同理. 创建: 847f23933343153f41208febd336f7de_MD5 一些设置: 0d212d71f5c798966321002162fcf506_MD5 AlwaysOnTop主要是使得界面一直在最上面,即使鼠标移出窗口,也是如此. 26a9c1c320271b60946301ccf8c34dc5_MD5 这样窗口弹出的时候就会出现在屏幕中间. 669fd25442e9934975dcb6576a3457f2_MD5 这样点击右上角的× 后,程序也会一同结束.否则,即使退出了窗口,虚拟机还在运行. 3是什么? a17059607e67dd5b1a710513c666d942_MD5 可以发现,这也是接口的作用之一. 0:点x会没有任何效果. 2:所有的界面都这么设置才有效果.当所有界面都x掉之后,会关掉进程. 3.x掉一个,会关闭掉进程.

为什么是3?因为我们的界面是不会同时出现的.x掉一个就要全关了.

菜单创建: 40b35e938b2ca0b5080c50210d4583ec_MD5 5db950a93486bd4fa4f162b7a465aee5_MD5 3a11a3795f69cd5ecb0c4c6373977d14_MD5 fe23ac02c6adc59d082f6df7b3e2c797_MD5 f000184400225f807ad5c96527ae4156_MD5 当然,这也是可以抽取出来的 7c8714267a16b681aac4c1e2cf306e31_MD5


游戏界面图片:ImageIcon 我们需要管理15张图片的结构:设置JLabel来托管. 抽出方法 458e6a86f1082155eb69bcab2f9fd9fe_MD5 9767bc4724c59b4f2ae22ad43b28c7ad_MD5 图片都是默认在最中间的.因此想要依次排放,就需要坐标. 18aacb6149863787c8fead1b93999cbe_MD5 图片由于是105x105的.我们直接设置会发现还是中间. 因此,需要修改一下隐藏容器.隐藏容器是Jframe创建时默认创建的隐藏根容器. b08ad5f5506c7e416963bd14a2066187_MD5 注意,setBound是设置JLabel相对于父控件的位置.x,y是左上角的位置. 隐藏容器是会自动添加的. 我们如果想把"默认最中间"取消,就需要setLayout(null); 65636916c635995774734835bd2c8c2f_MD5 dbd5cf7748d0018d2811042c20a51458_MD5

这样就成功创建一个图片了.同样的,循环加图片 : b774550cd1e764659eadb4af77ab4af4_MD5 由于我们只有1-15的图片,因此右下角的图片加载不出来.成为一个空白.这是正常的.

打乱图片: 929a295305827d2250988b3755f2d73e_MD5 省略不写了.思路不难.


事件: 10015a6ecda09df8c6382d9a6bb571c4_MD5

动作监听:监听鼠标的时候只能监听点击,监听键盘的时候只能监听空格.

按钮: c21460c5ca8aa5acdf9f0b2a9431d53c_MD5 这是一个动作监听 传递的参数必须是个接口实现类的对象. 5a47b13c21f638feda1807c415e962d4_MD5 4fbd051715e2013c915411babf58a3f2_MD5 当然可以用匿名内部类: be94d6f2d69d6d3836e89d25598f4e2c_MD5

  • 当然,这样写还是太麻烦了.可以让当前界面重写: 2875661310ccc3b899816c9b5ad75ee3_MD5 传递this就行: de7e3a8678cb495812a5f3f96a3d474b_MD5 重写的触发的函数可以统一写成这样: 62202ff0593bc03ebce0cd6d5d24bb9b_MD5 别忘了添加: 4a4216f7ca841bdeab68fe21b8920fc6_MD5

事件: 鼠标实际上有四个动作: 363a4e0a00a3281ea2b4d6a0569f3459_MD5

其中还有单击动作 一般认为"按下并释放"鼠标按钮 会触发单击动作.

一共有五种回调函数. 8f793034ae5df135333ae0340df3482e_MD5 注意要给按钮添加绑定才有效果


3b4e0138585cfab50fdffd58f1e72c02_MD5 第三个方法基本不用. 需要重写这三个: 67ae6dfce977b9788e5864225adf23ac_MD5 如果我们一直按着不送,那么会刷屏: 2bb7c1124dc3813aedee46b85f798f1f_MD5 如何区分按键? 2827e256b9c996db613de36c9b5a4dcd_MD5 按下a的效果: 144f20e6803c01400b45b884d5725d2f_MD5 这其实和acill码并不是一一对应,只是巧合罢了.因此我们需要知道对应关系.


美化: 9686b4adf1cf87f1ecf9243c907968f9_MD5 先移动到中间:直接给每个图片都添加一个偏移量就行: 2268e4b8ca25fe3601a66313f9448a5d_MD5 当然,这个偏移量需要自己调.

添加背景图片也需要调参数. 470487d17fa556081911f338f752fbb1_MD5 但是这添加之后,图长这样: 385cab32e7fe3a85f67461e2bf9a1bdd_MD5 因此是添加顺序不对.应该先添加循环,再添加图片.

结论:先加载的图片在上方,后加载的图片在下方. 怎么记?改需求的时候,新加的代码往往在原先代码的后面.为了不影响原先的呈现效果,因此会被放在下面.

添加边框:给Label添加就行: 04c48e17970a9175544dbfaa7503caef_MD5 注意,添加边框之后根本不需要调整原先图片的位置.


回过头来,发现路径太长了,不好看,怎么办?写成相对路径.相对路径是相对于当前项目的. 如: c77509cc17f1e14e575ddfaff17283e2_MD5


向上移动:把空白方块下方的图片上移 先实现监听: fbf2b5500878aa8d0f98f50dd1b17ff7_MD5 9f83419071fc884dc62df647743fecdc_MD5 怎么获得上下左右? c69d1d334633530eee8345efd1b6aeb3_MD5 打印就行.不过也可以记一下 左上右下. 为什么要release时触发?因为长按时会导致连续触发Pressed.

怎么重写改变图片呢?我们刚刚对图片的绘制进行了封装,因此直接调用就行了. bde51acb5f1c9e233712363ea5bda3b9_MD5 但是似乎没有效果?这是因为,initImage方法里需要先清空原来的图片. ce3d531fe0f82bd6e2ee8c28c5031379_MD5 末尾需要刷新界面: d4f80bdd2f54c0c923fd3cbf146b9bf5_MD5

总结:绘制先封装,开头先清空,末尾需刷新 二维数组是"数据",绘制是"界面".每次绘制时,通过数据来进行绘制.这就是MVC


f38bae67fef94fa168d054b6475bf6cd_MD5 c0f3471a149f3fab43a0d9544bf77329_MD5 当然,这样写其实耦合性太强了.可以抽取出公共部分的.

松开:只需要在release函数里添加: 32f29ddb455df7b1de19dc5124856cee_MD5 即可.


更改图片: 我们发现initImage当中加载的图片是写死的.但是实际上,图片路径应该是"数据",在MVC中应该抽取出来的. 8c076fc1c5e50271455c861c3e7594c0_MD5 017a859b70d0c4fa3b20f3b6d79a03f2_MD5


如果我们想设置:按下W会使得图片全部归位. 那么只需要控制release时,如果是w,那么就修改二维数组的数据,使得归位即可.然后调用initImage. 这里,MVC模式就显现出来了.


024eda2e47c676d8c2c8138fe7cf32ef_MD5 e13f3d78963e74ed5354e6701fd9fbff_MD5 b8891f11c655c1d07623013b922b1e92_MD5 不过显示胜利的图片时,还能上下左右,如何解决? 21b48ac6c6afa7c02462c514c1876e42_MD5


a7dce458deb033696a12f4a2fb130b1b_MD5 e0237393cb99be281edd2154f303abef_MD5


624591329efaae2de88c6b2ba008cfde_MD5 1.继承 12c698cf9cb59bbc361260a189dd91a7_MD5 867e44373538ad34f594b5e1a25845cc_MD5 但其实感觉匿名内部类应该比较好.但这样也能写.在我们处理点击事件的时候: 0d95d6646bf535971828a9070c7c1d50_MD5 当然,这样就需要把这些Item抽取出来,放到成员变量里了. 44c12fbb4e2a1f14d6d14c6eebb8e67b_MD5


重新登录: a3ae34e9e3d3e300542e46c0733eef2d_MD5 退出: 2d9945a6103cd36fef3ff73f59bc9dfd_MD5

弹窗对象jDialog: 4b52706a897fb720911d6a251e1aeead_MD5


嵌套菜单: dccc93b248fe2faaa385b8bed39acd1f_MD5 登录页面: 4d8789e2c6ff07bd0904d513f55a4fd7_MD5 注意,button是有默认边框的,我们可以去掉.

这里面所有组件都是通过直接设置像素位置做到的,没有使用布局管理器.

一个细节: 4b7276a8f422015ef150b82dfcc6cbcc_MD5


打包成exe 377c7b198f582a721396c3c6e5f4a78c_MD5

jar文件其实是包含了.class文件的压缩包.它当中可以不包含.java代码,也可以包含,取决于打包的方式.

注意,在IDEA当中图片资源是相对于项目的路径.但是打包成exe后是这样的: 634f1eb64dcc64efc8279dd498e1c1dd_MD5 图片的路径则是相对于exe的路径了. 注:上图就是打包后的结果.


补充一些API: 设置任务栏图标: 0f64df1f8ad001b200ccf5afc13ee68b_MD5 也就是Windows任务栏当中的图标,如这些: 130c4be27a063ecf500b1136a272b704_MD5