0

I am trying to double buffer a transparent JWindow however it seems like the technique used takes no effect (different cycle values are drawn over each other).

public final class Overlay extends JWindow {

    public static final Color TRANSPARENT = new Color(0, true);
    public static Font standardFont = null;

    public static Overlay open() {
        return new Overlay();
    }

    private Overlay() {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setAlwaysOnTop(true);
        setBounds(0, 0, screenSize.width, screenSize.height);
        setBackground(TRANSPARENT);
    }

    @Override
    public void paint(Graphics g) {
        BufferedImage bufferedImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D g2d = bufferedImage.createGraphics();
        paintUs(g2d);

        Graphics2D g2dComponent = (Graphics2D) g;
        g2dComponent.drawImage(bufferedImage, null, 0, 0);
    }

    private void paintUs(Graphics2D g) {
        int height = 420;
        int x = 20;
        g.setColor(TRANSPARENT);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setFont(standardFont == null ? standardFont = g.getFont().deriveFont(17f) : standardFont);
        for (Plugin plugin : Abendigo.plugins()) {
            g.setColor(Abendigo.plugins().isEnabled(plugin) ? Color.GREEN : Color.RED);
            g.drawString(plugin.toString(), x + 5, getHeight() - height);
            height += 20;
        }
        height += 20;
        g.setColor(Color.YELLOW);
        g.drawString("Cycle: " + Abendigo.elapsed + "ms", x, getHeight() - height);
    }

    @Override
    public void update(Graphics g) {
        paint(g);
    }

}
Jire
  • 9,680
  • 14
  • 52
  • 87

1 Answers1

1

Why!?!? Swing components are already double buffered? Simple create a custom component, extending from something like JPanel, override it's paintComponent and perform your custom painting there. Make sure you set the component to be transparent (setOpaque(false)) and add this to an instance of JWindow

See Painting in AWT and Swing and Performing Custom Painting for more details.

One of the immediate issues you are facing is the fact the Swing windows have a series of compound components already attached to them (JRootPane, contentPane, etc), all of which can be painted independently of you window, meaning that they can cover over what every you've been attempting to paint directly to the window. Instead, avoid painting directly to the window and use a custom component instead.

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • It did not seem double buffered. The changing cycle text goes over itself like this: http://i.imgur.com/HSPLJ1v.png – Jire Aug 20 '15 at 07:44
  • Likely, you've broken the paint chain and failed to call one or more of the super paint methods (like in your example) – MadProgrammer Aug 20 '15 at 07:45
  • Thanks, I created a `JPanel` and overridden the `paintComponent` in that and then set it to opaque as well as setting its background to `TRANSPARENT`. Works great! – Jire Aug 20 '15 at 08:03
  • 1
    FYI: Swing only knows how to paint fully transparent or fully opaque components (windows are the exception), so you MUST use `setOpaque` and not a alpha based background color! – MadProgrammer Aug 20 '15 at 08:05