Java Swing实现窗体添加背景图片的2种方法详解

网友投稿 2366 2023-03-16


Java Swing实现窗体添加背景图片的2种方法详解

本文实例讲述了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, thimmSDBxNJqQs);

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相关内容感兴趣的读者可查看本站专题:《Java数据结构与算法教程》、《Java字符与字符串操作技巧总结》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》

希望本文所述对大家java程序设计有所帮助。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:api接口文档框架(api接口的简单编写方式)
下一篇:接口测试用例自动生成背景(接口测试用例设计案例)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~