JLayeredPane не рисует низкий компонент, если оба компонента имеют одинаковый размер и полный экран - PullRequest
0 голосов
/ 26 октября 2018

JLayeredPane не рисует низкий компонент, если оба компонента имеют одинаковый размер и полноэкранный режим

Как работает программное обеспечение:

JFrame <- APanel <- JLayeredPane <- (Слоистые подкомпоненты) </p>

  • Мое программное обеспечение - полноэкранное программное обеспечение.
  • APanel - это компонент BorderLayout.
  • JLayeredPane - это BorderLayout.CENTER в APanel
Panel1 gp = new Panel1(); //Panel1 extends JPanel
gp.setSize(jlp.getSize());
jlp.add(gp);
gp.initializeDisplay(); //starts repaint() loop
jlp.setLayer(gp, 90);

Panel2 lp = new Panel2(); //Panel2 extends JPanel
lp.setSize(jlp.getSize());
lp.initializeDisplay();  //starts repaint() loop
lp.initializeComponents(); //Adds and moves components
jlp.add(lp);
jlp.setLayer(lp, 110);

Когда я делаю так, отображается только Panel2.Panel1 s paintComponent() выглядит следующим образом (Просто нарисуйте изображение):

g.drawImage(myImage, 0, 0, getWidth(), getHeight(), null);

Panel2 содержит множество кнопок и меток.Этот метод решает проблему.

Panel1 gp = new Panel1();
gp.setSize(jlp.getSize());
jlp.add(gp);
gp.initializeDisplay();
jlp.setLayer(gp, 90);

Panel2 lp = new Panel2();
lp.setSize(jlp.getWidth() - 1, jlp.getHeight() - 1); //Changed here
lp.initializeDisplay();
lp.initializeComponents();
jlp.add(lp);
jlp.setLayer(lp, 110);

Но этот метод вызывает проблему снова:

Dimension cs = new Dimension(jlp.getWidth() - 1, jlp.getHeight() - 1);
GrassPane gp = new GrassPane();
gp.setSize(cs);
jlp.add(gp);
gp.initializeDisplay();
jlp.setLayer(gp, 90);

LobbyPane lp = new LobbyPane(this);
lp.setSize(cs);
lp.initializeDisplay();
lp.initializeComponents();
jlp.add(lp);
jlp.setLayer(lp, 110);

Пожалуйста, добавьте комментарий, если вам нужна дополнительная информация, такая как коды.

1 Ответ

0 голосов
/ 26 октября 2018

Когда непрозрачный компонент перекрывает другой, намеренно пропустить рисование полностью затемненных компонентов. Это может стать проблемой только тогда, когда компонент ошибочно объявлен непрозрачным. Поэтому, когда вы реализуете свои собственные компоненты, рисующие прозрачное изображение, они должны реализовать метод isOpaque(), возвращающий false.

Интересно, что я все еще мог воспроизвести проблему перерисовки с прозрачными компонентами, используя следующий код:

JFrame f = new JFrame("Test");
JLayeredPane pane = f.getLayeredPane();
JButton b = new JButton("Normal Text");
b.setHorizontalTextPosition(SwingConstants.LEFT);
b.setBounds(20, 20, 300, 100);
JLabel l = new JLabel("Overlay");
l.setHorizontalTextPosition(SwingConstants.RIGHT);
l.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
l.setBounds(20, 20, 300, 100);
l.setOpaque(false);
pane.add(l);
pane.add(b);
f.setSize(350, 200);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);

Здесь текст «Наложение» может отображаться или не отображаться изначально, но как только изменяется одно из свойств кнопки (например, получение фокуса или нажатие), текст исчезает.

Проблема заключается в следующем свойстве:

System.out.println(pane.isOptimizedDrawingEnabled());

напечатает true. А «оптимизированный рисунок» означает, что некоторые дети могут не отображаться в определенных ситуациях. Как документация гласит:

Возвращает true, если этот компонент размещает свои дочерние элементы, то есть, если он может гарантировать, что дочерние элементы не будут перекрываться.

Конечно, JLayeredPane никогда не будет помещать детей в плитки, но укладывать их друг на друга и никогда не сможет гарантировать, что они не будут перекрываться. Однако по какой-то причине разработчики Swing решили реализовать следующую логику:

private void validateOptimizedDrawing() {
    boolean layeredComponentFound = false;
    synchronized(getTreeLock()) {
        Integer layer;

        for (Component c : getComponents()) {
            layer = null;

            if(SunToolkit.isInstanceOf(c, "javax.swing.JInternalFrame") ||
                   (c instanceof JComponent &&
                    (layer = (Integer)((JComponent)c).
                                 getClientProperty(LAYER_PROPERTY)) != null))
            {
                if(layer != null && layer.equals(FRAME_CONTENT_LAYER))
                    continue;
                layeredComponentFound = true;
                break;
            }
        }
    }

    if(layeredComponentFound)
        optimizedDrawingPossible = false;
    else
        optimizedDrawingPossible = true;
}

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

Итак, когда мы меняемся

pane.add(l);
pane.add(b);

до

Object myLayer = JLayeredPane.DEFAULT_LAYER+1;
pane.add(l, myLayer);
pane.add(b, myLayer);

проблема исчезнет, ​​так как System.out.println(pane.isOptimizedDrawingEnabled()); выведет false сейчас.

Остерегайтесь автобокса. Когда вы используете pane.add(l, JLayeredPane.DEFAULT_LAYER+1); или просто pane.add(l, 1);, он будет вызывать add(Component comp, int index) вместо желаемого add(Component comp, Object constraints).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...