我正在尝试创建一个通用的图形导出工具,它通过实现Graphics接口来工作,并拦截和解释对其各种方法的调用。但是,虽然我可以成功地为单个组件执行此操作,但当我在包含其他组件的组件上使用它时,我的Graphics类正在被替换。奇怪的是,这只发生在Windows和Linux上。在OSX上它工作正常。
有人可以建议我如何确保它是传递给所有子组件的原始Graphics类吗?
我有一个简短的脚本,演示了根本问题。当我使用MyGraphics的实例显式调用paint时,我在JPanel中看不到MyGraphics - 只是sun.java2d.SunGraphics2D。
import java.awt.*;
import java.awt.image.*;
import java.text.AttributedCharacterIterator;
import javax.swing.*;
public class GraphicsTest {
public static void main(String[] args) {
new GraphicsTest();
}
public GraphicsTest () {
JFrame frame = new JFrame();
frame.getContentPane().add(new MyPanel());
frame.setSize(500,500);
frame.setVisible(true);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println("Using my graphics - expect to see 'MyGraphics' next");
frame.paint(new MyGraphics());
}
class MyPanel extends JPanel {
public void paint (Graphics g) {
super.paint(g);
System.out.println("Graphics is "+g);
g.fillRect(10, 10, 20, 20);
}
}
class MyGraphics extends Graphics {
public String toString () {
return "MyGraphics";
}
public Graphics create() {
return this;
}
// I've left out the huge list of abstract methods from the original script
// since they're unchanged from the defaults and don't really matter here.
}
在我的Windows系统上,输出为:
Graphics is sun.java2d.SunGraphics2D[font=javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=plain,size=12],color=sun.swing.PrintColorUIResource[r=51,g=51,b=51]] Using my graphics - expect to see 'MyGraphics' next Graphics is sun.java2d.SunGraphics2D[font=javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=plain,size=12],color=sun.swing.PrintColorUIResource[r=51,g=51,b=51]]
而在OSX下,我得到了我的预期,即:
Graphics is sun.java2d.SunGraphics2D[font=apple.laf.CUIAquaFonts$DerivedUIResourceFont[family=LucidaGrande,name=LucidaGrande,style=plain,size=13],color=javax.swing.plaf.ColorUIResource[r=0,g=0,b=0]] Using my graphics - expect to see 'MyGraphics' next Graphics is MyGraphics
那么我能做些什么来确保在所有情况下我都将'MyGraphics'传递给相应的子组件?
答案 0 :(得分:1)
我不确定,但我怀疑由于Windows上的Java(而不是OS X上的窗口管理器)对swing进行双缓冲,因此您不会绘制到图形,而是绘制到Graphics2D由屏幕外缓冲区提供,然后blt到您的图形。
答案 1 :(得分:1)
就是这样!如果我在调用paint之前禁用组件上的双缓冲,然后重新启用它,那么一切都按照我需要的方式工作。
RepaintManager.currentManager(frame).setDoubleBufferingEnabled(false);
frame.paint(new MyGraphics());
RepaintManager.currentManager(frame).setDoubleBufferingEnabled(true);
感谢。