JScrollPane Viewport 大于 Frame

JScrollPane Viewport bigger than Frame

我尝试制作一个具有动态布局的 JFrame,它应该如下所示

------------------------------------------| 
|                | Details                |
|                |                        |
|                |                        |
| list           |                        |
|                |                        |
|                |                        |
|                |     save               |
-------------------------------------------

其中list是一些树状结构,当我选择某个元素时,该元素的详细信息出现在Details中。现在详细信息由多个 JPanels 组成,我将其放入 JPanelBoxLayout 中。在这个 JPanel 下面我有一个保存按钮。

因为有很多细节,所以我把 JPanel 细节放到了 JScrollPane 中,但是这个 scrollPane 忽略了它的目的,结果是细节面板比 window 大小。这是它一直到隐藏保存按钮的底部,其余部分不可见。滚动条永远不会出现。

我不知道这是否与以下事实有关:当一个元素被 selected 时,我更新了 JScrollPane 中的 JPanel 或其他什么。

以下是我如何实例化所有内容。首先在右侧面板中,我在 firstPanel 中添加了所有 JPanel,然后在 JPanel 底部放置了一个按钮。然后

    setLayout(new BorderLayout());
    add(bottom, BorderLayout.SOUTH);

    scrollPane=new JScrollPane(firstPanel);
    JPanel conScroll = new JPanel(new GridLayout());
    conScroll.add(scrollPane);
    add(conScroll, BorderLayout.CENTER);

JFrame 级别上,我实例化了左侧和右侧,但是我只放置了左侧,右侧为空的 JPanel,称为 display

当我 select 一个元素时,我更新 firstPanel 内的所有元素,我在右侧面板上调用 revalidate()repaint()。然后在框架级别上,我删除了 displayer 的所有元素,然后将右侧添加到 displayer.

按照建议,我做了一个最小的工作示例(已更新)。

因此,对于这个最小的示例,我删除了左侧。剩下的是一个 JFrame EmpireEditor,里面有一个显示 JPanel,然后我在里面放了一个 unitEditor。 Uniteditor 包含两个 JPanel,一个在中间,一个在南面。中间的面板在 JScrollPane 中。

package main;

import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;



public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            // Set System L&F
            UIManager.setLookAndFeel(
                    UIManager.getSystemLookAndFeelClassName());
        }
        catch (UnsupportedLookAndFeelException e) {
            // handle exception
        }
        catch (ClassNotFoundException e) {
            // handle exception
        }
        catch (InstantiationException e) {
            // handle exception
        }
        catch (IllegalAccessException e) {
            // handle exception
        }

        @SuppressWarnings("unused")
        EmpireEditor r = new EmpireEditor();
    }
}

帝国编辑器

    package main;

import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class EmpireEditor extends JFrame {

    private JPanel display;
    private UnitEditor unitEditor;

    public EmpireEditor() {
        super("Editor");
        display = new JPanel();
        unitEditor = new UnitEditor();
        add(display);
        display.add(unitEditor);
        pack();
        setVisible(true);
    }
}

这里的 UnitEditor 是一个中心面板,我只是在其中填充了一个 PanelNumber 但这只是为了让里面有东西,我们可以看到滚动条没有出现。这个想法是底部总是在那里,其余的应该用 JScrollPane.

填充
package main;

import java.awt.BorderLayout;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;


@SuppressWarnings("serial")
public class UnitEditor extends JPanel {



    private PanelNumbers numbers = new PanelNumbers();

    private JScrollPane scrollPane;

    public UnitEditor() {
        super();

        JPanel firstPanel = new JPanel();
        firstPanel.setLayout(new BoxLayout(firstPanel, BoxLayout.Y_AXIS));
        firstPanel.add(numbers);

        JPanel bottom = new JPanel();
        JButton save = new JButton("save");

        bottom.add(save);

        scrollPane=new JScrollPane(firstPanel);

        setLayout(new BorderLayout());
        add(scrollPane, BorderLayout.CENTER);
        add(bottom,BorderLayout.SOUTH);
    }
}

终于 PanelNumber 但可以用任何东西交换它。

package main;

import java.awt.GridLayout;
import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


@SuppressWarnings("serial")
public class PanelNumbers extends JPanel{

    private Map<Value, JFormattedTextField> nums = new HashMap<>();



    public PanelNumbers(){
        super();

        setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));

        JFormattedTextField tmp;
        JPanel numbers;
        numbers = new JPanel();
        numbers.setBorder(BorderFactory.createTitledBorder("Numbers"));
        numbers.setLayout(new GridLayout(0, 6));
        for (Value s : Value.values()) {
            numbers.add(new JLabel(s.n()));
            tmp = new JFormattedTextField(NumberFormat.getInstance());
            setFocus(tmp);
            numbers.add(tmp);
            nums.put(s, tmp);
        }
        add(numbers);
    }

    public void setUnit(String name){
        for (Value key : nums.keySet())
            nums.get(key).setValue(0);
    }

    public void save(){

    }

    private int toNumber(String t) {
        int res = 0;
        try {
            res = Integer.parseInt(t);
        } catch (Exception e) {
        }
        return res;
    }

    private void setFocus(final JFormattedTextField num) {
        num.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        num.selectAll();
                    }
                });
            }
        });
        //num.setPreferredSize(new Dimension(20, 10));
        num.setMaximumSize(num.getPreferredSize());
    }

    public enum Value {
        // Kampf
        GROESSE("Groesse"),
        WAFFENFERTIGKEIT("Waffenfertigkeit"),
        FERNKAMPFFERTIGKEIT("Fernkampffertigkeit"),
        ANGRIFFSBONUS("Angriffs Bonus"),
        NAHKAMPFPANZERUNG("Panzerung nah"),
        FERNKAMPFPANZERUNG("Panzerung fern"),
        INITIATIVE("Initiative"),
        TP("Treffer"),
        // Mouvement
        FELDER("Felder"),
        BWS("Bewegungspunkte"),
        B("B Befehl"),
        A("A Befehl"),
        P("P Befehl"),
        H("H Befehl"),
        M("Manoever"),
        UEBERR("Ueberrenen"),
        //Moral
        FURCHTFAKTOR("Furchtfaktor"),
        MORALERST("Erster Moralwert"),
        MORALZWEIT("Zweiter Moralwert"),
        //Rest
        MAGIE("Magie"),
        KONTROL("Kontrollbereich"),
        STERNE("Sterne"),
        ELEMENTE("Elemente"),
        ELEMENTEPROFELD("Elemente pro Feld"),
        KOSTEN("Kosten");

        private String name;
        Value(String name){
            this.name = name;
        }

        public String n(){
            return name;
        }

    }
}

display 的布局设置为 GridLayout(1,1) 解决了问题,不知何故原始布局只是让内部面板变得尽可能大,因此 JScrollPane 没有有种想把它变小并有滚动条的冲动。