简体   繁体   中英

JScrollPane Viewport bigger than Frame

I try to make a JFrame with a dynamical layout which should look like this

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

Where list is some tree structure where when I chose some element, the details of the element appear in Details. Now the Details consist of multiple JPanels which I put into a JPanel with BoxLayout . Below this JPanel I have a save button.

Since there are a lot of details I put the JPanel Details into a JScrollPane however, this scrollPane ignores its purpos and the result is that the Details panel is bigger than the window size. This is it goes till the bottom hiding the save button and the rest of it is not visible. The scrollbar never appears.

I don't know if it has todo with the fact that when an element is selected I update the JPanel 's inside the JScrollPane or whatever.

Here is how I instantiate everything. First inside the right panel I add all JPanel 's in firstPanel and I put a button inside the JPanel bottom. Then

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

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

On the JFrame level I instantiate the left and right side however I only put the left hand side and an empty JPanel for the right side called display .

When I select an element I update all elements inside firstPanel I call revalidate() and repaint() on the right side panel. Then on the Frame level I remove all elements of displayer and then add the right side to displayer .

As suggested I made a minimal working example (updated).

So for this minimal example I removed the left side. What is left is a JFrame EmpireEditor with a display JPanel inside, inside which I then put a unitEditor . Uniteditor contains two JPanel one in the center and one south. The panel in the center is in a 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();
    }
}

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

and here the UnitEditor a center Pannel where I just fill with a PanelNumber but that's just so that there is something inside and that we can see that the scrollbars don't appear. The Idea is that the bottom is always there and the rest should be filled with the 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);
    }
}

finally the PanelNumber but one could exchange this with anything.

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并没有让其自身变小并具有滚动条的冲动。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM