Java setBackgrounds在Windows中引发异常(但不在MacOSX中)

Java setBackgrounds在Windows中引发异常(但不在MacOSX中),java,swing,cross-platform,Java,Swing,Cross Platform,我尝试使用图像背景,因此在JFrame中创建了以下代码: @Override public void paint(Graphics g) { super.paint(g); try { final Image image = ImageIO.read(getClass().getResource("/images/login/gentlenoise100.png")); int iw = 256; int ih = 256;

我尝试使用图像背景,因此在JFrame中创建了以下代码:

@Override
public void paint(Graphics g) {
    super.paint(g);
    try {
        final Image image = ImageIO.read(getClass().getResource("/images/login/gentlenoise100.png"));
        int iw = 256;
        int ih = 256;
        for (int x = 0; x < getWidth(); x += iw) {
            for (int y = 0; y < getHeight(); y += ih) {
                g.drawImage(image, x, y, iw, ih, this);
            }
        }
    } catch (IOException ex) {
        Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
    }
    for(Component componente:getComponents()){
        componente.repaint();
    }

}
它在Mac OS X(java 1.6)中运行良好,我必须在Windows中探测它,如果我删除setBackground调用,它不会显示我的背景,如果我保持背景颜色不可见,它会抛出一个异常,并说框架已装饰

我试图使用
setUndecorate(true)
,但在macosx中,它松开了标题栏(当然),在Windows中,它为我提供了一个透明的窗口


我怎样才能解决这个问题呢?

有三种方法可以使用

  • JComponent#setOpaque()
    如果您不想在后台喘气

  • 在Win上,OSX有几个***unix

  • 为了



  • 不要把
    paint()
    任何东西放到
    JFrame
    ,放在那里
    JPanel
    并重写
    paintComponent()
    如果可以避免,不要重写顶级容器(如
    JFrame
    )的
    paint
    方法,它们对许多重要的事情都有作用

    在这种情况下,最好使用
    JPanel
    并将框架内容窗格设置为它

    类似于

    public class BackgroundPane extends JPanel {
    
        private Image background;
        public BackgroundPane() {
            try {
                background = ImageIO.read(getClass().getResource("/images/login/gentlenoise100.png"));
            } catch (IOException ex) {
                Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            int iw = 256;
            int ih = 256;
            for (int x = 0; x < getWidth(); x += iw) {
                for (int y = 0; y < getHeight(); y += ih) {
                    g.drawImage(background, x, y, iw, ih, this);
                }
            }
        }
    }
    
    //...
    
    JFrame frame = new JFrame();
    frame.setContentPane(new BackgroundPane());
    //...
    

    在你的内心,绘画方法是一个非常糟糕的主意

    第二种情况可能会导致重绘管理器决定父容器(您的帧)需要重绘,一次又一次,一次又一次…最终消耗您的CPU

    注意,从Java 7开始,在
    Window
    上使用包含小于255的alpha值的颜色调用
    setBackground
    将导致窗口变得透明

    将新颜色(0,0,0,alpha)传递到此 方法(其中alpha小于255)安装每像素半透明

    如果窗口已装饰,这也会引发异常…

    可能有助于解释为什么使用alpha值来避免setBackground的问题
    public class BackgroundPane extends JPanel {
    
        private Image background;
        public BackgroundPane() {
            try {
                background = ImageIO.read(getClass().getResource("/images/login/gentlenoise100.png"));
            } catch (IOException ex) {
                Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            int iw = 256;
            int ih = 256;
            for (int x = 0; x < getWidth(); x += iw) {
                for (int y = 0; y < getHeight(); y += ih) {
                    g.drawImage(background, x, y, iw, ih, this);
                }
            }
        }
    }
    
    //...
    
    JFrame frame = new JFrame();
    frame.setContentPane(new BackgroundPane());
    //...
    
    final Image image = ImageIO.read(getClass().getResource("/images/login/gentlenoise100.png"));
    
    for(Component componente:getComponents()){
        componente.repaint();
    }