简体   繁体   English

调用`setVisible(true)`后如何让JComponent调整大小?

[英]How do I get a JComponent to resize after calling `setVisible(true)`?

Our application displays a 2D view of our data (mainly maps) and then allows the user to change to a 3D view. 我们的应用程序显示我们数据的2D视图(主要是地图),然后允许用户更改为3D视图。 The 2D and 3D views are generated by custom C++ code that is SWIG'ed into our Swing GUI and wrapped within a JComponent . 2D和3D视图由自定义C ++代码生成,这些代码SWIG进入我们的Swing GUI并包装在JComponent These JComponent s are then displayed within another parent JComponent. 然后,这些JComponent将显示在另一个父JComponent中。

Our problem is that when we change from the 2D to the 3D view and then back to the 2D view, when we resize the window the 2D view does not get resized. 我们的问题是,当我们从2D视图更改为3D视图然后再返回到2D视图时,当我们调整窗口大小时,2D视图不会调整大小。 The resize events don't get sent to the 2D view. 调整大小事件不会发送到2D视图。

Our application runs under Linux (Fedora 11). 我们的应用程序在Linux(Fedora 11)下运行。 We're running Java version 1.6.0_12. 我们正在运行Java版本1.6.0_12。

Here is some sample code in which I've replaced the 2D view and 3D view with two 2 JButton s, that produces the same behaviour. 下面是一些示例代码,其中我用两个2 JButton替换了2D视图和3D视图,它们产生了相同的行为。 Once you go to 3D and then back to 2D, resizing the window does not cause the 2D view to be resized. 进入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();
    }
}

( My apologies for the Netbeans generated GUI code ) 我为Netbeans生成的GUI代码道歉

I should mention that when we call parent.remove(view2D) and parent.add(view3D) to change the views the X Windows ID of our 3D view changes and we're unable to get our 3D view back. 我应该提一下,当我们调用parent.remove(view2D)parent.add(view3D)来更改视图时,我们的3D视图的X Windows ID会发生变化,我们无法恢复3D视图。 Therefore parent.remove(view2D) and parent.add(view3D) is not really a solution and we have to call setVisible(false) and setVisible(true) on the JComponent s that contain our 2D and 3D views in order to hide and show them. 因此, parent.remove(view2D)parent.add(view3D)实际上不是一个解决方案,我们必须在包含我们的2D和3D视图的JComponent上调用setVisible(false)setVisible(true)才能隐藏和显示他们。

Any help will be greatly appreciated. 任何帮助将不胜感激。

Why don't you use a CardLayout to switch from the 2D to 3D component? 为什么不使用CardLayout从2D切换到3D组件? CardLayout is exactly done for this kind of purpose in my understanding. 在我的理解中,CardLayout正是为了这种目的而完成的。 Another benefit would be that it will simplify your code. 另一个好处是它将简化您的代码。

After your remove() and add() methods to change the component, you should call: 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 for JComponent#revalidate() : JComponent的Javadoc#revalidate()

Supports deferred automatic layout. 支持延迟自动布局。

Calls invalidate and then adds this component's validateRoot to a list of components that need to be validated. 调用无效,然后将此组件的validateRoot添加到需要验证的组件列表中。 Validation will occur after all currently pending events have been dispatched. 在调度所有当前挂起的事件之后将进行验证。 In other words after this method is called, the first validateRoot (if any) found when walking up the containment hierarchy of this component will be validated. 换句话说,在调用此方法之后,将验证在向上遍历此组件的包含层次结构时找到的第一个validateRoot(如果有)。 By default, JRootPane, JScrollPane, and JTextField return true from isValidateRoot. 默认情况下,JRootPane,JScrollPane和JTextField从isValidateRoot返回true。

This method will automatically be called on this component when a property value changes such that size, location, or internal layout of this component has been affected. 当属性值发生更改以使此组件的大小,位置或内部布局受到影响时,将自动在此组件上调用此方法。 This automatic updating differs from the AWT because programs generally no longer need to invoke validate to get the contents of the GUI to update. 这种自动更新与AWT不同,因为程序通常不再需要调用validate来获取GUI的内容以进行更新。

I've found a solution. 我找到了解决方案。 You need to add/remove the components from the layout manager: 您需要在布局管理器中添加/删除组件:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我的JComponent仅在手动调整窗口大小后才会重绘(),如何使其正常工作? - My JComponent will only repaint() once I manually resize the window, how do I get it to work as it should? 我如何setVisible(true)来自另一个类的JLabel - how do i setVisible(true) a JLabel from another class 如何在重绘时调整JComponent的大小? - how to resize a JComponent on repaint? 在调用setVisible(false)后调用set Visible(true)时,我的JFrame内容消失了 - After calling setVisible(false) my JFrame contents are gone when calling set Visible(true) 加载其他jframe类时,如何设置setvisible(true)我有setvisible(false)的JFrame? - how to setvisible(true) a JFrame which i had setvisible(false) when loading other jframe class? 在已经可见的框架上调用setVisible(true) - Calling setVisible(true) on an already visible frame Java如何获取JComponent以根据帧宽度调整大小 - Java How to get JComponent to resize based on frame width 如何将 ActionListener 添加到特定的 JComponent? - How do I add an ActionListener to a specific JComponent? 为什么在JFrame.setVisible(true)之后调用JFrame.pack()影响JFrame的显示位置? - Why calling JFrame.pack() after JFrame.setVisible(true) affect the location where JFrame is displayed? 如何在JFrame或任何JComponent上绘制? - How do I draw on a JFrame, or any JComponent?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM