2010-04-23 2 views
3

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

FYI Я использую javax.swing.Timer для пересчета и перерисовки панели смены 24 раза в секунду.

ответ

7

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

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

+0

да, я согласен, так что не поймите меня – phunehehe

3

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

Даже если у вас есть движущаяся часть, SWING все равно нужно «очистить» последнюю позицию compnent, что означает, что она должна хотя бы перекрасить эту область фоновой панели, прежде чем перерисовать перемещенный компонент.

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

+0

Он, вероятно, установил непрозрачную ложность, потому что он хочет нарисовать непрямоугольные фигуры на компоненте позже ... – Nate

2

Очень простой способ - использовать jxlayer. Внесите AbstractLayerUI и добавьте это через свой компонент. См. here.

+0

спасибо, что рассказали мне о jxlayer, но когда я попробовал нижний слой по-прежнему перекрашивается каждый раз :( – phunehehe

+0

Вы ничего не можете сделать. JPanel.paintComponent() получает имя eveytime, когда вы изменяете размер кадра или прокручиваете его, как в JScrollPane. Вы можете свести к минимуму время, потраченное в paintComponent(), имея backbuffer. В вашей paintComponents() только краска backbufer и ничего больше. –