Topic: JDesktopPane中如何设置背景图片?

  Print this page

1.JDesktopPane中如何设置背景图片? Copy to clipboard
Posted by: sogui
Posted on: 2005-02-13 22:48

我自己继承了一个JDesktopPane的MyJDesktopPane的类,可以实现设置背景图片,现在的问题是在一个MDI窗体中打开的子窗体沉在JDesktopPane下面,不可见!向各位请教有什么好的办法解决这个问题?
我的代码如下:
package jbtest;
import javax.swing.*;
import java.awt.*;
//import java.awt.Canvas;

/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright Coffee 2004</p>
* <p>Company: </p>
* @author not attributable
* @version 1.0
*/

public class MyJDesktopPane extends JDesktopPane {
Canvas mycanvas;
public MyJDesktopPane() {
}
public void paint(Graphics g){
ImageIcon myimage=new ImageIcon(jbtest.Frame1.class.getResource("Windows 2000.jpg"));
Image image=myimage.getImage();
g.drawImage(image,0,0,this.getSize().width,this.getSize().height,myimage.getImageObserver());

}
}

2.Re:JDesktopPane中如何设置背景图片? [Re: sogui] Copy to clipboard
Posted by: Theface
Posted on: 2005-02-18 20:40

我做的时候添加一个JLable;不过要记住这个要最后添加否则不能看到!

3.Re:JDesktopPane中如何设置背景图片? [Re: sogui] Copy to clipboard
Posted by: anticlockwise_6
Posted on: 2005-02-26 11:20

Try writing super.paint( g )

4.Re:JDesktopPane中如何设置背景图片? [Re: sogui] Copy to clipboard
Posted by: sogui
Posted on: 2005-03-08 18:42

Theface :
在上面加一个JLabel我试过了,原先我是在网上找过一些文章的,最先我就是加上一个JLabel,好像跟重写JDesktopPane的paint(Graphics g)一样,子窗体都沉在图片下面。我要实现的是一个MDI主窗体容纳子窗体,子窗体要用到JInterFrame类。不像其它的开发工具那么容易,以前用过.net,实现这个很容易。不知还有什么更好的方法呢,现在我还没有想到有什么更好的办法!

5.Re:JDesktopPane中如何设置背景图片? [Re: sogui] Copy to clipboard
Posted by: sogui
Posted on: 2005-03-08 18:47

anticlockwise_6:
“Try writing super.paint( g ) ”
具体应如何做?你的意思是不是要我不要重写父类的paint(Graphics g)?

6.Re:JDesktopPane中如何设置背景图片? [Re: sogui] Copy to clipboard
Posted by: Duncan
Posted on: 2005-03-09 00:33

sogui wrote:
我自己继承了一个JDesktopPane的MyJDesktopPane的类,可以实现设置背景图片,现在的问题是在一个MDI窗体中打开的子窗体沉在JDesktopPane下面,不可见!向各位请教有什么好的办法解决这个问题?
我的代码如下:

package jbtest;
import javax.swing.*;
import java.awt.*;
//import java.awt.Canvas;

/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: </p>
* @author not attributable
* @version 1.0
*/

public class MyJDesktopPane extends JDesktopPane {
Canvas mycanvas;
public MyJDesktopPane() {
}
public void paint(Graphics g){
ImageIcon myimage=new ImageIcon(jbtest.Frame1.class.getResource("Windows 2000.jpg"));
Image image=myimage.getImage();
g.drawImage(image,0,0,this.getSize().width,this.getSize().height,myimage.getImageObserver());

}
}



一個基本的觀念:Container - paint method 有責任畫完自身的外觀後,也讓其內的 child component 畫在自己身上,特別是當 child 是 lightweight component 時。Lightweight component 強烈依賴其 parent 提供 Graphics 來繪製元件外觀,若一個 Container 沒有盡到責任留個機會給 lightweight child component 繪製外觀,child component 則無法面對世人(invisible)。Heavy component(如 java.awt.Button etc.)則不在此限,因為 heavyweight component 會促使底層的 windowing system 建立 native component(以 peer 溝通),windowing system 會負責繪出 native component。

瞧瞧你寫的 MyJDesktopPane 壞了規矩,paint method 只顧著繪自己,不管 child component,根本稱不上是合格的 Container。

本來你是可以在 paint method block 最後頭加上 super.paint(g); 來使用原來的 JDesktopPane 的功能(就會盡到 container 的責任),但是因為 JDesktopPane paint method 會先抹掉背景,這麼一來你繪製在先的 image 就被抹掉了;若是把 super.paint(g); 放在最前頭則變成 image 蓋在 child component 上(因為 child components 先繪,"背景" image 後繪)。

JComponent 把 paint method 拆成三個步驟,依序是 paintComponent, paintBorder, paintChildren,負責的任務顧名思義。要加入繪製背景圖的功能在 paintComponent method 裡實做比較適合。請見下面的 demo:

Demo1

/*
* Created on 2005/3/8
*/
package com.jsptw.j2se;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;

import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;

public class WPDesktop extends JDesktopPane {
private Image wallPaper;

public static void main(String[] args)
{
Image bg = Toolkit.getDefaultToolkit().createImage(
WPDesktop.class.getResource("images/risako.jpg"));
JDesktopPane desktop = new WPDesktop(bg);

JInternalFrame childFrame = new JInternalFrame("MDI child frame", true);
childFrame.setBounds(100, 100, 200, 200);
desktop.add(childFrame, new Integer(10));
childFrame.show();

JFrame mainFrame = new JFrame("Application main frame");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.getContentPane().add(desktop);
mainFrame.pack();
mainFrame.show();
}
public WPDesktop(Image wallPaper)
{
this.wallPaper = wallPaper;
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(wallPaper, 0);
try {
tracker.waitForAll();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}

protected void paintComponent(Graphics g)
{
super.paintComponent(g);

int width = wallPaper.getWidth(this);
int height = wallPaper.getHeight(this);
Dimension size = getSize();

// paint tiled wall paper
for (int x = 0; x < size.width; x += width)
for (int y = 0; y < size.height; y += height)
g.drawImage(wallPaper, x, y, this);
}

public Dimension getPreferredSize()
{
return new Dimension(wallPaper.getWidth(this), wallPaper.getHeight(this));
}
}


另外一種作法可以不要 customize JDesktopPane,如同前幾篇文章提到,把一張顯示 image 的 JLabel 放置於 JDesktoPane 最下層(JDesktopPane 就是 JLayeredPane)。如下:

package com.jsptw.j2se;

import java.awt.Container;
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.ImageIcon;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class DesktopDemo extends JFrame {

public static void main(String[] args)
{
Image bgImage = Toolkit.getDefaultToolkit().createImage(DesktopDemo.class.getResource(
"images/lavigne_avril_005.jpg"));
JFrame frm = new DesktopDemo(bgImage);
frm.setTitle("A MDI Frame with a image as background.");
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.pack();
frm.show();
}

public DesktopDemo(Image image) throws HeadlessException
{
super(image.toString());

_bgImage = image;
initComponsnts();
}

public Container getContentPane()
{
return _content;
}

private void initComponsnts()
{
JDesktopPane desk = new JDesktopPane() {
public Dimension getPreferredSize()
{
return _bgView.getPreferredSize();
}
};
_bgView = new JLabel(new ImageIcon(_bgImage), JLabel.CENTER);
_bgView.setOpaque(true);

_content = (JPanel) super.getContentPane();
_content.setOpaque(false);
desk.add(_content, JDesktopPane.FRAME_CONTENT_LAYER);

desk.add(
_bgView,
new Integer(JDesktopPane.FRAME_CONTENT_LAYER.intValue() - 1));

desk.addComponentListener(new ComponentAdapter(){
public void componentResized(ComponentEvent e)
{
Dimension size = e.getComponent().getSize();
_bgView.setSize(size);
_content.setSize(size);
_content.revalidate();
}
});
setContentPane(desk);

JInternalFrame dummy1 =
new JInternalFrame("Dummy frame A", true, true, true, true);
dummy1.setBounds(100, 100, 300, 200);
desk.add(dummy1, JDesktopPane.DEFAULT_LAYER);
dummy1.show();

JInternalFrame dummy2 = new JInternalFrame("Dummy frame B", true, true);
dummy2.setBounds(200, 200, 400, 300);
desk.add(dummy2, JDesktopPane.DEFAULT_LAYER);
dummy2.show();
}

private Image _bgImage;
private JLabel _bgView;
private JPanel _content;
}


附件 zip 中有此二 demo 的 executable jar。

Demos.zip (119.56k)

7.Re:JDesktopPane中如何设置背景图片? [Re: sogui] Copy to clipboard
Posted by: tzutolin
Posted on: 2005-03-09 17:12

Great! Thanks!!


   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923