Как получить JComponent для изменения размера после вызова `setVisible (true)`? - PullRequest
1 голос
/ 22 апреля 2010

Наше приложение отображает 2D-представление наших данных (в основном карты), а затем позволяет пользователю перейти к 3D-просмотру. 2D и 3D виды генерируются с помощью пользовательского кода C ++, который SWIG вставлен в наш графический интерфейс Swing и помещен в JComponent. Эти JComponent затем отображаются в другом родительском JComponent.

Наша проблема в том, что при изменении размера с 2D на 3D-вид и затем обратно на 2D-вид, когда мы изменяем размер окна, 2D-вид не изменяется. События изменения размера не отправляются в 2D-просмотр.

Наше приложение работает под Linux (Fedora 11). Мы используем Java версии 1.6.0_12.

Вот пример кода, в котором я заменил 2D-вид и 3D-вид двумя 2 JButton s, что приводит к одинаковому поведению. После перехода в 3D, а затем обратно в 2D изменение размера окна не приводит к изменению размера 2D-вида.

/* TestFrame.java
 * Compile with: $ javac TestFrame.java
 * Run with: $ java TestFrame
 */

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.JButton;

public class TestFrame extends javax.swing.JFrame {

    private boolean mode2D = true;
    private JButton view2D = null;
    private JButton view3D = null;
    private Container parent = null;

    public TestFrame() {
        initComponents();
        containerPanel.setLayout(new BorderLayout());
        view2D = new JButton("2D View");
        view2D.addComponentListener(new MyListener("2D VIEW"));
        containerPanel.add(view2D);
    }

    private void changerButtonActionPerformed(java.awt.event.ActionEvent evt) {        
        if (parent == null) {
            parent = view2D.getParent();
        }
        if (mode2D) {
            System.out.println("Going from 2D to 3D");

            view2D.setVisible(false);

            if (view3D != null) {
                view3D.setVisible(true);
            } else {
                view3D = new JButton("3D View");
                view3D.addComponentListener(new MyListener("3D VIEW"));   
                parent.add(view3D);
            }

            ((JButton) evt.getSource()).setText("Change to 2D");
            mode2D = false;
        } else {
            System.out.println("Going from 3D to 2D");
            view3D.setVisible(false);
            view2D.setVisible(true);
            ((JButton) evt.getSource()).setText("Change to 3D");
            mode2D = true;
        }
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new TestFrame().setVisible(true);
            }
        });
    }
    private javax.swing.JPanel containerPanel;
    private javax.swing.JButton changerButton;

    private class MyListener implements ComponentListener {
        private String name;
        public MyListener(String name) {
            this.name = name;
        }
        @Override
        public void componentHidden(ComponentEvent event) {
            System.out.println("@@@ [" + name + "] component Hidden");
        }
        @Override
        public void componentResized(ComponentEvent event) {
            System.out.println("@@@ [" + name + "] component Resized");
        }
        @Override
        public void componentShown(ComponentEvent event) {
            System.out.println("@@@ [" + name + "] component Shown");
        }
        @Override
        public void componentMoved(ComponentEvent event) {
            System.out.println("@@@ [" + name + "] component Moved");
        }
    };

    @SuppressWarnings("unchecked")
    private void initComponents() {
        containerPanel = new javax.swing.JPanel();
        changerButton = new javax.swing.JButton();
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        containerPanel.setBorder(new javax.swing.border.MatteBorder(null));
        javax.swing.GroupLayout containerPanelLayout = new javax.swing.GroupLayout(containerPanel);
        containerPanel.setLayout(containerPanelLayout);
        containerPanelLayout.setHorizontalGroup(
            containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 374, Short.MAX_VALUE)
        );
        containerPanelLayout.setVerticalGroup(
            containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 239, Short.MAX_VALUE)
        );
        changerButton.setText("Change to 3D");
        changerButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                changerButtonActionPerformed(evt);
            }
        });
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(containerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(changerButton))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(containerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(changerButton)
                .addContainerGap())
        );
        pack();
    }
}

( Мои извинения за сгенерированный Netbeans код GUI )

Я должен упомянуть, что когда мы вызываем parent.remove(view2D) и parent.add(view3D), чтобы изменить виды, X Windows ID нашего 3D-вида изменяется, и мы не можем вернуть наш 3D-вид назад. Поэтому parent.remove(view2D) и parent.add(view3D) на самом деле не являются решением, и мы должны вызвать setVisible(false) и setVisible(true) на JComponent s, которые содержат наши 2D и 3D виды, чтобы скрыть и показать их.

Любая помощь будет принята с благодарностью.

Ответы [ 3 ]

2 голосов
/ 22 апреля 2010

Почему вы не используете CardLayout для переключения с 2D на 3D компонент? В моем понимании, CardLayout сделан именно для этой цели. Еще одним преимуществом будет то, что это упростит ваш код.

2 голосов
/ 22 апреля 2010

После того, как ваши remove() и add() методы изменили компонент, вы должны вызвать:

parent.revalidate(); //To make the layout manager do its work.
parent.repaint(); //This could be necessary, to suggest a repaint of the panel

Javadoc для JComponent # revalidate () :

Поддерживает отложенное автоматическое размещение.

Звонки делают недействительными, а затем добавляет это validateRoot компонента к списку компоненты, которые должны быть проверены. Валидация произойдет в конце концов в настоящее время ожидающие события были посланный. Другими словами, после этого метод называется, первый validateRoot (если есть) найден, когда поднимаясь по иерархии сдерживания этого компонента будет проверен. По умолчанию JRootPane, JScrollPane, и JTextField возвращают true из isValidateRoot.

Этот метод будет автоматически называется этот компонент, когда значение свойства изменяется так, что размер, расположение или внутреннее расположение этого компонент был затронут. это автоматическое обновление отличается от AWT потому что программ вообще нет больше нужно вызвать validate, чтобы получить содержимое графического интерфейса для обновления.

0 голосов
/ 22 апреля 2010

Я нашел решение.Вам нужно добавить / удалить компоненты из менеджера макета:

private void changerButtonActionPerformed(java.awt.event.ActionEvent evt) {        
        if (parent == null) {
            parent = view2D.getParent();
        }

        LayoutManager layoutMgr = parent.getLayout();

        if (mode2D) {
            System.out.println("Going from 2D to 3D");

            view2D.setVisible(false);
            layoutMgr.removeLayoutComponent(view2D);

            if (view3D != null) {
                view3D.setVisible(true);                
                if (layoutMgr != null && layoutMgr instanceof LayoutManager2) {
                    ((LayoutManager2) layoutMgr).addLayoutComponent(view3D, null);
                }

            } else {
                view3D = new JButton("3D View");
                view3D.addComponentListener(new MyListener("3D VIEW"));   
                parent.add(view3D);
            }

            ((JButton) evt.getSource()).setText("Change to 2D");
            mode2D = false;
        } else {
            System.out.println("Going from 3D to 2D");
            view3D.setVisible(false);
            layoutMgr.removeLayoutComponent(view3D);

            view2D.setVisible(true);            
            if (layoutMgr != null && layoutMgr instanceof LayoutManager2) {
                ((LayoutManager2) layoutMgr).addLayoutComponent(view2D, null);
            }

            ((JButton) evt.getSource()).setText("Change to 3D");
            mode2D = true;
        }
    }
...