Двойная буферизация с JWindow

Я пытаюсь дважды буферизовать прозрачный JWindow, однако кажется, что используемый метод не действует (разные значения цикла рисуются друг над другом).

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);
    }

}

person Jire    schedule 20.08.2015    source источник


Ответы (1)


Почему!?!? Компоненты Swing уже имеют двойную буферизацию? Просто создайте пользовательский компонент, расширяющийся от чего-то вроде JPanel, переопределите его paintComponent и выполните там свою пользовательскую прорисовку. Убедитесь, что вы сделали компонент прозрачным (setOpaque(false)) и добавьте его в экземпляр JWindow.

См. Рисование в AWT и Swing и Выполнение пользовательского рисования для получения более подробной информации.

Одной из непосредственных проблем, с которыми вы сталкиваетесь, является тот факт, что окна Swing имеют ряд уже прикрепленных к ним составных компонентов (JRootPane, contentPane и т. д.), каждый из которых может быть прорисован независимо от вашего окна, что означает, что они могут закрывать то, что все, что вы пытались нарисовать прямо в окне. Вместо этого избегайте рисования непосредственно в окне и вместо этого используйте пользовательский компонент.

person MadProgrammer    schedule 20.08.2015
comment
Это не казалось двойной буферизацией. Текст изменяющегося цикла проходит сам по себе следующим образом: i.imgur.com/HSPLJ1v.png - person Jire; 20.08.2015
comment
Скорее всего, вы нарушили цепочку рисования и не смогли вызвать один или несколько методов супер-краски (как в вашем примере). - person MadProgrammer; 20.08.2015
comment
Спасибо, я создал JPanel и переопределил в нем paintComponent, а затем сделал его непрозрачным, а также установил его фон на TRANSPARENT. Работает отлично! - person Jire; 20.08.2015
comment
К вашему сведению: Swing умеет рисовать только полностью прозрачные или полностью непрозрачные компоненты (окна являются исключением), поэтому вы ДОЛЖНЫ использовать setOpaque, а не цвет фона на основе альфа-канала! - person MadProgrammer; 20.08.2015