Java Swing实现窗体添加背景图片的2种方法详解
本篇章节讲解Java Swing实现窗体添加背景图片的2种方法。分享给大家供大家参考,具体如下: 在美化程序时,常常需要在窗体上添加背景图片。通过搜索和测试,发现了2种有效方式。下面分别介绍。 1. 利用JLabel加载图片 利用JLabel自带的 JLabel lbBg = new JLabel(imageIcon); lbBg.setBounds(0,frameSize.width,frameSize.height); this.getContentPane().add(lbBg); 然而这种方法有几个要注意的点: (1)不能使用布局管理器 此时你需要将布局管理器设置为null,然后精确控制所有控件的大小和位置。否则,JLabel无法完整覆盖窗体。 (2)应当先添加背景JLabel,再添加其它控件。否则其它控件将被JLabel所遮挡(为什么不是后添加的遮挡先添加的?)。 (3)由于控件及窗体的尺寸需要手动控制,因此无法对背景图片进行缩放。 2. 重载JPanel的 通过重载该方法,在JPanel的绘制阶段将指定图片绘制上去即可。由于背景是绘制出来的,因此不会对布局有任何影响。 示例代码如下: @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(image,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,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,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
如果此组件是轻量组件,则此方法会尽快调用此组件的 paint 方法。否则此方法会尽快调用此组件的 update 方法。 注:有关 AWT 和 Swing 所用绘制机制的更多信息,包括如何编写最高效的绘制代码的信息 。 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重绘主要有四个关键方法: 而进行绘制时后它会依次调用update(),paint(),paintComponent(),paintBorder(),paintChildren()进行绘制; 那么repaint()方法为什么会延时呢? 调用repaint()会导致一个区域被增加到重绘列表队列中,且被预定重绘。产生一个防止到系统事件队列中的请求, 也就是说通常情况下repaint()它是不会立即执行的,调用它后会有一个等待处理的过程。但repaint比较高效,会推迟实际的绘制并将多余的请求压缩到单个 paint 调用中。 所以如何解决它的repaint()延时问题呢? 1.让它立即执行:使用 2.使用SwingUtilities工具类中的 更多关于java相关内容感兴趣的读者可查看本站专题:《Java数据结构与算法教程》、《Java字符与字符串操作技巧总结》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》 希望本文所述对大家java程序设计有所帮助。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |