源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

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

  • 时间:2020-05-14 06:43 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Java Swing实现窗体添加背景图片的2种方法详解
本文实例讲述了Java Swing实现窗体添加背景图片的2种方法。分享给大家供大家参考,具体如下: 在美化程序时,常常需要在窗体上添加背景图片。通过搜索和测试,发现了2种有效方式。下面分别介绍。 [b]1. 利用JLabel加载图片[/b] 利用JLabel自带的[code]setIcon(Icon icon)[/code]加载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)由于控件及窗体的尺寸需要手动控制,因此无法对背景图片进行缩放。 [b]2. 重载JPanel的[/b][code]paintComponent(Graphics g)[/code][b]方法[/b] 通过重载该方法,在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();
  }
}

运行效果如下: [img]http://files.jb51.net/file_images/article/201711/20171114113804709.jpg?20171014113930[/img] 图1 使用JLabel加载图片效果 图1可见,使用JLabel时,由于未图片尺寸与窗体尺寸不一致,导致图片只显示出一部分;且有一个控件被遮挡了。注意:通过精细设置尺寸和添加控件顺序,可以达到较为满意的效果的。 [img]http://files.jb51.net/file_images/article/201711/20171114113932766.jpg?20171014114021[/img] 图2 使用重绘方式加载图片 图2可见,不需要可以设置匹配尺寸和控件的添加顺序,即可得到比较满意的效果。 [b]补充说明:Swing 重绘 repaint,updateUI区别[/b] [b]repaint[/b] [code]public void repaint()[/code]重绘此组件。 如果此组件是轻量组件,则此方法会尽快调用此组件的 paint 方法。否则此方法会尽快调用此组件的 update 方法。 注:有关 AWT 和 Swing 所用绘制机制的更多信息,包括如何编写最高效的绘制代码的信息 。 [b]updateUI[/b] [code]public void updateUI()[/code]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);
  }
}

[b]swing重绘主要有四个关键方法[/b]:[code]paint()[/code],[code]repaint()[/code],[code]revalidate()[/code],[code]paintImmediately()[/code]; 而进行绘制时后它会依次调用update(),paint(),paintComponent(),paintBorder(),paintChildren()进行绘制; [b]那么repaint()方法为什么会延时呢?[/b] 调用repaint()会导致一个区域被增加到重绘列表队列中,且被预定重绘。产生一个防止到系统事件队列中的请求, 一旦该请求被处理,内部工具自动毁掉组件的paintImmediately()方法。然后该方法立即执行绘制; 也就是说通常情况下repaint()它是不会立即执行的,调用它后会有一个等待处理的过程。但repaint比较高效,会推迟实际的绘制并将多余的请求压缩到单个 paint 调用中。 [b]所以如何解决它的repaint()延时问题呢?[/b] 1.让它立即执行:使用[code]paintImmediately()[/code]。 2.使用SwingUtilities工具类中的[code]invokeLater(Runnable doRun)[/code]方法;把你要在[code]repaint()[/code]后执行的操作写在要执行的线程中;(它会把这个方法也加入到java内部事件队列中,它排在repaint()之后,所以一般情况下,它是等repaint()执行完之后才会执行,虽然这样达到效果,但并不理想); 更多关于java相关内容感兴趣的读者可查看本站专题:《[url=http://www.1sucai.cn/Special/632.htm]Java数据结构与算法教程[/url]》、《[url=http://www.1sucai.cn/Special/947.htm]Java字符与字符串操作技巧总结[/url]》、《[url=http://www.1sucai.cn/Special/830.htm]Java操作DOM节点技巧总结[/url]》、《[url=http://www.1sucai.cn/Special/687.htm]Java文件与目录操作技巧汇总[/url]》和《[url=http://www.1sucai.cn/Special/682.htm]Java缓存操作技巧汇总[/url]》 希望本文所述对大家java程序设计有所帮助。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部