Java Swing实现窗体添加背景图片的2种方法详解
作者:pzy4447 发布时间:2021-10-26 19:01:18
本文实例讲述了Java Swing实现窗体添加背景图片的2种方法。分享给大家供大家参考,具体如下:
在美化程序时,常常需要在窗体上添加背景图片。通过搜索和测试,发现了2种有效方式。下面分别介绍。
1. 利用JLabel加载图片
利用JLabel自带的setIcon(Icon icon)
加载icon,并设置JLabel对象的位置和大小使其完全覆盖窗体。这是一个很取巧的办法,代码非常简单,如下所示。
JLabel lbBg = new JLabel(imageIcon);
lbBg.setBounds(0, 0, frameSize.width, frameSize.height);
this.getContentPane().add(lbBg);
然而这种方法有几个要注意的点:
(1)不能使用布局管理器
此时你需要将布局管理器设置为null,然后精确控制所有控件的大小和位置。否则,JLabel无法完整覆盖窗体。
(2)应当先添加背景JLabel,再添加其它控件。否则其它控件将被JLabel所遮挡(为什么不是后添加的遮挡先添加的?)。
(3)由于控件及窗体的尺寸需要手动控制,因此无法对背景图片进行缩放。
2. 重载JPanel的paintComponent(Graphics g)
方法
通过重载该方法,在JPanel的绘制阶段将指定图片绘制上去即可。由于背景是绘制出来的,因此不会对布局有任何影响。
示例代码如下:
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, d.width, d.height, this);
MainFrame.instance().repaint();
}
下面是一个完整的demo。
package frame;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class ImageFrame extends JFrame {
class ImagePanel extends JPanel {
Dimension d;
Image image;
public ImagePanel(Dimension d, Image image) {
super();
this.d = d;
this.image = image;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, d.width, d.height, this);
MainFrame.instance().repaint();
}
}
Dimension frameSize = new Dimension(500, 300);
ImageIcon imageIcon = new ImageIcon(this.getClass().getResource(
"/images/bg.jpg"));
public ImageFrame() {
// 设置窗体属性
setSize(frameSize);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setIconImage(imageIcon.getImage());
setUndecorated(true);
}
public void addImageByJLable() {
setLayout(null);
// 设置背景
JLabel lbBg = new JLabel(imageIcon);
lbBg.setBounds(0, 0, frameSize.width, frameSize.height);
this.getContentPane().add(lbBg);
addComponents();
setVisible(true);
}
public void addImageByRepaint() {
ImagePanel imagePanel = new ImagePanel(frameSize, imageIcon.getImage());
setContentPane(imagePanel);
addComponents();
setVisible(true);
}
private void addComponents() {
JButton btn1 = new JButton("haha");
btn1.setBounds(10, 20, 60, 30);
this.getContentPane().add(btn1);
JTextField jtf = new JTextField("22222222222");
jtf.setBounds(200, 100, 80, 30);
this.getContentPane().add(jtf);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ImageFrame imageFrame = new ImageFrame();
// imageFrame.addImageByJLable();
imageFrame.addImageByRepaint();
}
}
运行效果如下:
图1 使用JLabel加载图片效果
图1可见,使用JLabel时,由于未图片尺寸与窗体尺寸不一致,导致图片只显示出一部分;且有一个控件被遮挡了。注意:通过精细设置尺寸和添加控件顺序,可以达到较为满意的效果的。
图2 使用重绘方式加载图片
图2可见,不需要可以设置匹配尺寸和控件的添加顺序,即可得到比较满意的效果。
补充说明:Swing 重绘 repaint,updateUI区别
repaint
public void repaint()
重绘此组件。
如果此组件是轻量组件,则此方法会尽快调用此组件的 paint 方法。否则此方法会尽快调用此组件的 update 方法。
注:有关 AWT 和 Swing 所用绘制机制的更多信息,包括如何编写最高效的绘制代码的信息 。
updateUI
public void updateUI()
UIManager 发出的关于 L&F 已经更改的通知。用 UIManager 的最新版本替换当前的 UI 对象。覆盖: 类 JComponent 中的 updateUI另请参见: JComponent.updateUI()
可能大家都试过在swing的事件监听中动态添加组件,但是JFrame却不会动态显示,只有变大变小(实际是重画了)才会显示。repaint,updateUI可以,用validate发现也可以。
API中对repaint()方法是这样描述的,调度完当前所有未完成的事件后重新绘制该组件,所以repaint方法不总是马上执行。
package awtDemo;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class Ss extends JFrame {
Container con = this.getContentPane();
JButton jb1 = new JButton("jb1");
JButton jb2 = new JButton("jb2");
JLabel jl1 = new JLabel("jl1");
FlowLayout gly = new FlowLayout();
JPanel jp = new JPanel(gly);
public Ss() {
con.add(jp);
jp.add(jb1);
jp.add(jb2);
MyListener ml = new MyListener();
jb1.addMouseListener(ml);
this.setSize(300, 200);
this.setVisible(true);
}
private class MyListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
try {
JButton jb3 = new JButton("jb3");
jp.add(jb3);
// jp.updateUI();//可以正常显示
jp.repaint();//API中对repaint()方法是这样描述的,调度完当前所有未完成的事件后重新绘制该组件,repaint方法不总是马上执行,所以只有调整大小才可以显示。
//主要就是下面的invalidate和validate
//当然,用jp来invalidate和validatae也是可以的
// jp.invalidate();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public static void main(String s[]) {
Ss sss = new Ss();
sss.setVisible(true);
}
}
swing重绘主要有四个关键方法:paint()
,repaint()
,revalidate()
,paintImmediately()
;
而进行绘制时后它会依次调用update(),paint(),paintComponent(),paintBorder(),paintChildren()进行绘制;
那么repaint()方法为什么会延时呢?
调用repaint()会导致一个区域被增加到重绘列表队列中,且被预定重绘。产生一个防止到系统事件队列中的请求,
一旦该请求被处理,内部工具自动毁掉组件的paintImmediately()方法。然后该方法立即执行绘制;
也就是说通常情况下repaint()它是不会立即执行的,调用它后会有一个等待处理的过程。但repaint比较高效,会推迟实际的绘制并将多余的请求压缩到单个 paint 调用中。
所以如何解决它的repaint()延时问题呢?
1.让它立即执行:使用paintImmediately()
。
2.使用SwingUtilities工具类中的invokeLater(Runnable doRun)
方法;把你要在repaint()
后执行的操作写在要执行的线程中;(它会把这个方法也加入到java内部事件队列中,它排在repaint()之后,所以一般情况下,它是等repaint()执行完之后才会执行,虽然这样达到效果,但并不理想);
希望本文所述对大家java程序设计有所帮助。
来源:http://www.cnblogs.com/pzy4447/p/5995145.html


猜你喜欢
- 判断字符串是否为IP地址通常都是基于正则表达式实现的,无论是引入外部的依赖包亦或是自己写正则实现,基本都是基于正则表达式实现的判断。然而比较
- 今天遇到文件上传的问题,使用Ajax方式进行提交,服务器一直报错The current request is not a multipart
- 在android 6.0开始,部分的权限需要我们动态申请,也就是说当我们的打开app的时候系统不会主动像您申请app所需要的部分权限,需要客
- 前提最近发现各个频道推荐了很多ULID相关文章,这里对ULID的规范文件进行解读,并且基于Java语言自行实现ULID,通过此实现过程展示U
- Thread生命周期生命周期概述Java的线程状态描述放在Thread类里面的枚举类State中.总共包含了6中状态(从出生到死亡)。pub
- 一、项目简述功能包括: 该系统不错分为学生,教师,管理员,教导主任四种角 色,包括学生管理,教师管理,学生选题,教师选题,主 任审核,管理员
- 前言代码生成器,也叫逆向工程,是根据数据库里的表结构,自动生成对应的实体类、映射文件和接口。看到很多小伙伴在为数据库生成实体类发愁,现分享给
- 启用URL参数在解决方案资源管理器中右键点击你的ClickOnce工程,点击属性进入发布选项卡,点击“选项”按钮,在弹出的界面中选中“允许给
- Java序列化JSON时long型数值,会出现精度丢失的问题。原因:java中得long能表示的范围比js中number大,也就意味着部分数
- 如今,企业级应用程序的常见场景是同时支持HTTP和HTTPS两种协议,这篇文章考虑如何让Spring Boot应用程序同时支持HTTP和HT
- 在.Net中,对文件(File)和文件夹(Folder)的操作可以使用File类和Directory类,也可以使用FileInfo类和Dir
- 用过ios的都知道ios上输入法关闭的同时会自动关闭输入框,那么在android上如何实现监听输入法弹出和关闭呢?本篇文章就为你提供了一种可
- 1.概述在本教程中,我们将讨论如何使用Spring Security OAuth和Spring Boot实现SSO - 单点登录。我们将使用
- 1、需要引入依赖<dependency> &l
- BeanPostProcessor接口作用:如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处
- 这篇文章主要介绍了Java二分查找算法实现代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可
- ResultSet 动态获取列名和值仅供自己方便查阅,无其他用途ResultSet result = null; //前边SQL查询结果,这
- 引言当我们通过@ConfigurationProperties注解实现配置 bean的时候,如果默认的配置属性转换无法满足我们的需求的时候,
- 目录一、C# 多态性二、静态多态性三、函数重载四、C# 运算符重载1、运算符重载的实现2、可重载和不可重载运算符五、动态多态性前言:👻🎄学过
- 本文实例为大家分享了android通过usb读取U盘的具体代码,供大家参考,具体内容如下1.关联 compile ‘com.github.m