请问swing中的双缓冲怎么用啊?

javarat 2005-04-01 11:06:32
请问swing中的双缓冲怎么用啊?能给个简单的例子吗?
...全文
715 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
Preamble 2005-06-27
  • 打赏
  • 举报
回复
DanielYWoo(绿色毒汁) ( )

是不是最近刚升星了,也不散分?

佩服上面的解说,虽然还没有太明白,学习。
stefant2003 2005-06-27
  • 打赏
  • 举报
回复
试试Swing Component中的:

setDoubleBuffer(boolean) ?
DanielYWoo 2005-04-05
  • 打赏
  • 举报
回复
你可以看出来,明显我自己实现的double buffer更快。
但是这是有代价的,这个自己实现版本的不能够再添加新的子组件
这就是我为什么一开始不想让你自己实现off screen的原因
(因为你问我问的是swing的双缓冲怎么用,问法)
你看看http://java.sun.com/products/jfc/tsc/articles/painting/index.html
我觉得会对你很有帮助
DanielYWoo 2005-04-05
  • 打赏
  • 举报
回复
这个使用了double buffer,你看控制台输出一般都是
Render consumed 0 milliseconds
Render consumed 0 milliseconds
Render consumed 0 milliseconds
Render consumed 0 milliseconds
Render consumed 0 milliseconds

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;


public class MyPanel extends JPanel {

Image doubleBuffer;
int clickCount;
private static final Dimension pSize = new Dimension(512, 512);

public void paint(Graphics g) {
long t1 = System.currentTimeMillis();
if (doubleBuffer == null) {
doubleBuffer = createImage(this.getWidth(), this.getHeight());
}
g.drawImage(doubleBuffer, 0, 0, null);
long t2 = System.currentTimeMillis();
System.out.println("Render consumed " + (t2 - t1) + " milliseconds");

}

public Dimension getPreferredSize()
{
return pSize;
}

public void changeInternalStatus()
{
Graphics g = doubleBuffer.getGraphics();
//更改绘图......;
g.drawLine(0, clickCount, doubleBuffer.getWidth(null), clickCount);
clickCount += 5;

for (int i = 0; i < 256; i ++) {
g.setColor(new Color(i, i / 2, i / 3));
g.drawRoundRect(i, i, this.getWidth() - i * 2, this.getHeight() - i * 2, i / 5, i / 10);
}
g.dispose();
repaint();
}

public static void main(String[] args) {
final MyPanel p = new MyPanel();
JFrame f = new JFrame();
JMenuBar mb = new JMenuBar();
JMenu m = new JMenu("Test");
mb.add(m);
JMenuItem mi = new JMenuItem("Draw in off screen");
m.add(mi);
mi.addActionListener(new ActionListener(){
public void actionPerformed(java.awt.event.ActionEvent e) {
p.changeInternalStatus();
}

});

f.setJMenuBar(mb);
f.setContentPane(p);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.show();
}

}

这个是不用double buffer的,控制台输出为
Render consumed 16 milliseconds
Render consumed 47 milliseconds
Render consumed 15 milliseconds
Render consumed 31 milliseconds
Render consumed 16 milliseconds
Render consumed 47 milliseconds
Render consumed 16 milliseconds

程序:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;


public class MyPanel extends JPanel {


int clickCount;
private static final Dimension pSize = new Dimension(512, 512);

public void paint(Graphics g) {
long t1 = System.currentTimeMillis();

//更改绘图......;
g.drawLine(0, clickCount, this.getWidth(), clickCount);

for (int i = 0; i < 256; i ++) {
g.setColor(new Color(i, i / 2, i / 3));
g.drawRoundRect(i, i, this.getWidth() - i * 2, this.getHeight() - i * 2, i / 5, i / 10);
}

long t2 = System.currentTimeMillis();
System.out.println("Render consumed " + (t2 - t1) + " milliseconds");

}

public Dimension getPreferredSize()
{
return pSize;
}

public void changeInternalStatus()
{
clickCount += 5;
repaint();
}

public static void main(String[] args) {
final MyPanel p = new MyPanel();
JFrame f = new JFrame();
JMenuBar mb = new JMenuBar();
JMenu m = new JMenu("Test");
mb.add(m);
JMenuItem mi = new JMenuItem("Draw in off screen");
m.add(mi);
mi.addActionListener(new ActionListener(){
public void actionPerformed(java.awt.event.ActionEvent e) {
p.changeInternalStatus();
}

});

f.setJMenuBar(mb);
f.setContentPane(p);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.show();
}

}
DanielYWoo 2005-04-05
  • 打赏
  • 举报
回复
>>楼上的大哥还是说的双缓冲嘛。。。可是在swing里不是默认实现了双缓冲了吗?

Swing是实现了双缓冲,但是如果你想自己做,你可以参靠下面的例子

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;


public class MyPanel extends JPanel {

Image doubleBuffer;
int clickCount;
private static final Dimension pSize = new Dimension(300, 300);

public void paint(Graphics g) {
long t1 = System.currentTimeMillis();
if (doubleBuffer == null) {
doubleBuffer = createImage(this.getWidth(), this.getHeight());
}
g.drawImage(doubleBuffer, 0, 0, null);
long t2 = System.currentTimeMillis();
System.out.println("Render consumed " + (t2 - t1) + " milliseconds");

}

public Dimension getPreferredSize()
{
return pSize;
}

public void changeInternalStatus()
{
Graphics g2 = doubleBuffer.getGraphics();
//更改绘图......;
g2.drawLine(0, clickCount, doubleBuffer.getWidth(null), clickCount);
clickCount += 5;
g2.dispose();
repaint();
}

public static void main(String[] args) {
final MyPanel p = new MyPanel();
JFrame f = new JFrame();
JMenuBar mb = new JMenuBar();
JMenu m = new JMenu("Test");
mb.add(m);
JMenuItem mi = new JMenuItem("Draw in off screen");
m.add(mi);
mi.addActionListener(new ActionListener(){
public void actionPerformed(java.awt.event.ActionEvent e) {
p.changeInternalStatus();
}

});

f.setJMenuBar(mb);
f.setContentPane(p);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.show();
}

}

建议你看看http://java.sun.com/products/jfc/tsc/articles/painting/index.html
javarat 2005-04-04
  • 打赏
  • 举报
回复
恩,是的。。。
就是想做个小的画图板。。。
现在不知道在swing中怎么将画出的东西保存下来。。。
请大哥介绍个方法给我。。。。
不胜感激。。。
DanielYWoo 2005-04-04
  • 打赏
  • 举报
回复
你要保存的是图形还是包含其他Swing组件的Panel之类的?
如果是前者,你可以用背景的off screen,对于包含Swing子组件的,你最好别这样做(其实差不多是没法做)

我猜你是在做什么画图的东西才这么问的吧???
javarat 2005-04-04
  • 打赏
  • 举报
回复
可是我想在swing中保存已经画好的图象,并能够在窗口重新获得焦点时,还能显示。。。
所以我想调用swing的off screen
如果我不想把已经做好的程序保存在一个图象中,我该如何做?
javarat 2005-04-04
  • 打赏
  • 举报
回复
楼上的大哥还是说的双缓冲嘛。。。
可是在swing里不是默认实现了双缓冲了吗?
上面的方法我试过,但是
doubleBuffer = createImage(size.width, size.height);
g.drawImage(doubleBuffer, 0, 0, null);
第二句总是提醒我找不到源image。而且抛出空指针异常。
是不是createImage的调用者不对啊?我这里是一个JInternerFrame
DanielYWoo 2005-04-04
  • 打赏
  • 举报
回复
我猜你是不是在paint里面有几何计算之类的,导致每次你的窗体哪怕是很小一部分被其它窗体挡住了,然后都需要对整个客户区计算并重绘,所以很慢?

那样的话可以放Image里,你创建一个Image:
doubleBuffer = createImage(size.width, size.height);

当你的程序的内部数据变化的时候,比如用户新画了一条线,在事件响应函数里你向Image绘图:
Graphics g2 = doubleBuffer.getGraphics();
//更改绘图......;
g2.dispose();

然后你通知Swing准备重绘:
repaint();

在paint方法里,你就不用再去绘图了,直接把画好的image拿出来
g.drawImage(doubleBuffer, 0, 0, null);

如果你的绘图可以把计算限定在某一个区域,那么用update方法更好,因为update并不擦除背景(如果它本身是轻量级组件),你可以增量重绘,这是最好的方法,但是不幸的是,大多数情况很难对某一个特定的区域重新计算,所以JComponent的update方法默认实现直接就调用paint()。
javarat 2005-04-02
  • 打赏
  • 举报
回复
晕,三楼的大哥能帮我说下,swing中的双缓冲怎么用吗?我必须用它保存图形啊。。。。
全粘架构师 2005-04-02
  • 打赏
  • 举报
回复
今天才听说这个名词,请求详解
killme2008 2005-04-02
  • 打赏
  • 举报
回复
双缓冲是为了解决重绘的闪烁问题
JComponet默认实现了双缓冲的,其他组件继承这个类
如果没有必要,不用自己实现双缓冲
javarat 2005-04-02
  • 打赏
  • 举报
回复
大家帮帮忙啊。。。。
DanielYWoo 2005-04-02
  • 打赏
  • 举报
回复
怎么这么死心眼呢,呵呵,你参考哪个方法重写paintComponent阿,你的paint方法默认实现会调用你的paintComponent, paintBorder和paintChildren,其中paintChildren会递归调用子组件的paint方法。所以,不要重写paint,那样可能导致你的子组件无法正确显示,如果你对paintComponent方法重写,就不会影响Swing的机制。

不过我是在不太清楚你为什么要重新实现Swing的double buffering,看看下面的内容,估计你就不会打算自己在swing里做double buffering了

One of the most notable features of Swing is that it builds support for double-buffering right into the toolkit. It does the by providing a "doubleBuffered" property on javax.swing.JComponent:

public boolean isDoubleBuffered()
public void setDoubleBuffered(boolean o)
Swing's double buffer mechanism uses a single offscreen buffer per containment hierarchy (usually per top-level window) where double-buffering has been enabled. And although this property can be set on a per-component basis, the result of setting it on a particular container will have the effect of causing all lightweight components underneath that container to be rendered into the offscreen buffer, regardless of their individual "doubleBuffered" property values.

By default, this property is set to true for all Swing components. But the setting that really matters is on JRootPane, because that setting effectively turns on double-buffering for everything underneath the top-level Swing component. For the most part, Swing programs don't need to do anything special to deal with double-buffering, except to decide whether it should be on or off (and for smooth GUI rendering, you'll want it on!). Swing ensures that the appropriate type of Graphics object (offscreen image Graphics for double-buffering, regular Graphics otherwise) is passed to the component's paint callback, so all the component needs to do is draw with it. This mechanism is explained in greater detail later in this article, in the section on Paint Processing.

javarat 2005-04-02
  • 打赏
  • 举报
回复
JComponent的paintDoubleBuffered方法怎么都是private的啊?
有没有提供什么可以操作后台图象的方法呢?
大家帮帮忙啊,我找了好久了。。。。
DanielYWoo 2005-04-02
  • 打赏
  • 举报
回复
JComponent默认实现了double buffering,如果你觉得不满意,你可以参考一下JComponent的paintDoubleBuffered方法。
javarat 2005-04-02
  • 打赏
  • 举报
回复
楼上的这不是自己实现双缓冲吗???
AWT中的双缓冲我会。。。。
请帮帮忙,给我说下swing中所谓的自带双缓冲怎么用?
lEFTmOON 2005-04-02
  • 打赏
  • 举报
回复
private Image doubleBuffer;
...
public void update(Graphics g) {
Dimension size = getSize();
if (doubleBuffer == null ||
doubleBuffer.getWidth(this) != size.width ||
doubleBuffer.getHeight(this) != size.height)
{
doubleBuffer = createImage(size.width, size.height);
}


if (doubleBuffer != null) {
//向双缓冲中绘图
Graphics g2 = doubleBuffer.getGraphics();
paint(g2);
g2.dispose();

//显示双缓冲中的内容
g.drawImage(doubleBuffer, 0, 0, null);
}
else {
paint(g);
}
}

public void paint(Graphics g) {
// do drawing here
...
}

loo_la_la 2005-04-01
  • 打赏
  • 举报
回复
没用过,帮顶

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧