JFrame, который имеет несколько слоев

У меня есть окно, которое имеет два слоя: статический фон и передний план, который содержит движущиеся объекты. Моя идея - нарисовать фон только один раз (потому что он не изменится), поэтому я делаю изменяющуюся панель прозрачной и добавляю ее поверх статического фона. Вот код для этого:

public static void main(String[] args) {
    JPanel changingPanel = new JPanel() {

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.fillRect(100, 100, 100, 100);
        }
    };
    changingPanel.setOpaque(false);

    JPanel staticPanel = new JPanel();
    staticPanel.setBackground(Color.BLUE);
    staticPanel.setLayout(new BorderLayout());
    staticPanel.add(changingPanel);

    JFrame frame = new JFrame();
    frame.add(staticPanel);
    frame.setSize(800, 600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}

Этот кусок кода дает мне правильное изображение, которое я хочу, но каждый раз, когда я перекрашиваю changingPanel, staticPanel также перекрашивается (что явно противоречит идее покраски статической панели только один раз). Может кто-нибудь показать мне, что не так?

К вашему сведению, я использую javax.swing.Timer для пересчета и перекрашивания изменяющейся панели 24 раза каждую секунду.

3 ответа

Решение

Когда вы перекрашиваете прозрачный компонент поверх другого, вы все равно "пачкаете" нижний компонент, вызывая его перекрашивание. Если вы не перекрасите нижний слой, вы получите эффект смазывания изображения поверх него.

Единственная доступная оптимизация - не восстановление изображения, используемого на нижнем уровне. Растр все еще должен быть закрашен в графический буфер каждый раз, когда изменяется слой выше.

Именно так работает картина. Swing должен искать первый компонент с непрозрачным фоном. Затем он рисует этот компонент и детей, чтобы убедиться, что все рисование сделано правильно.

Даже если у вас есть движущийся компонент, SWing все равно нужно "очистить" последнюю позицию компонента, что означает, что он должен по крайней мере перекрасить эту область фоновой панели, прежде чем перекрашивать перемещенный компонент.

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

Действительно простой способ - использовать jxlayer. Реализуйте AbstractLayerUI и добавьте это к вашему компоненту. Смотрите здесь, чтобы начать.

Другие вопросы по тегам