调整JFrame大小后,JScrollPane会崩溃

时间:2014-07-29 14:38:37

标签: java jtable jframe jscrollpane layout-manager

我遇到了一些LayoutManager问题(我相信)。我为自己做了一个小项目,我在下面复制了我的问题。问题在于,当我使窗口甚至比原始尺寸更小(在x或y方向上,并不重要)时,整个JScrollPane会崩溃,直到桌子不再是可见。

我希望JPanel根据JFrame重新调整大小,而JScrollPane不会崩溃。我已经在边框上添加了颜色来说明问题。

我已经查找了各种问题来解决这个问题,但答案变化很大,我找不到适合我问题的解决方案。我对LayoutManagers有一个大致的了解,但显然还不够广泛,无法解决这个问题。感谢您提前提供任何帮助。

帧正常:

Frame normal

框架较小(折叠/消失表):

Frame smaller

框架更大(没问题):

Frame larger

代码(SSCCE):

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;


public class MainWindow extends JFrame {

    private JPanel EmployeePanel;
    private JButton add, remove, edit;
    private JTable EmployeeTable;
    private JScrollPane EmployeeTableScrollPane;

    private JMenuBar menu;
    private JMenu file;
    private JMenuItem exit;

    private String[] columns = {"First Name", "Last Name", "Initials"};
    private String[][] data = {
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"}
            };



    public MainWindow(){
        //Set title
        super("Scheduler");

        //Set LaF
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException
                | IllegalAccessException | UnsupportedLookAndFeelException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        //Set JFrame properties
        this.setSize(new Dimension(800,600));
        this.setMinimumSize(new Dimension(300,300));
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
        this.setLayout(new BorderLayout());

        //Initialize JComponents
        EmployeeTable = new JTable(data, columns){
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
        EmployeeTableScrollPane = new JScrollPane(EmployeeTable);

        add = new JButton("Add");
        remove = new JButton("Remove");
        edit = new JButton("Edit");

        menu = new JMenuBar();
        file = new JMenu("File");
        exit = new JMenuItem("Exit");

        //Set MenuBar
        file.add(exit);
        menu.add(file);
        this.setJMenuBar(menu);

        exit.addActionListener(new ActionListener(){
            //Don't mind the method i use for now to close the application
            @Override
            public void actionPerformed(ActionEvent arg0) {
                System.exit(0);
            }

        });

        GridBagConstraints constraints = new GridBagConstraints();
        EmployeePanel = new JPanel(new GridBagLayout());
        //Add JScrollPane
        constraints.weightx = 1;
        constraints.weighty = 1;
        constraints.gridx = 0;
        constraints.gridy = 0;
        constraints.gridwidth = 3;
        constraints.gridheight = 1;
        constraints.anchor = constraints.NORTH;
        constraints.fill = constraints.HORIZONTAL;
        EmployeePanel.add(EmployeeTableScrollPane, constraints);

        //Add Buttons
        constraints.gridx = 0;
        constraints.gridy = 1;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.anchor = constraints.SOUTH;
        constraints.fill = constraints.HORIZONTAL;
        EmployeePanel.add(add, constraints);

        constraints.gridx = 1;
        constraints.gridy = 1;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.anchor = constraints.SOUTH;
        constraints.fill = constraints.HORIZONTAL;
        EmployeePanel.add(edit, constraints);

        constraints.gridx = 2;
        constraints.gridy = 1;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.anchor = constraints.SOUTH;
        constraints.fill = constraints.HORIZONTAL;
        EmployeePanel.add(remove, constraints);

        //Add EmployeePanel
        this.add(EmployeePanel, BorderLayout.CENTER);

        EmployeeTableScrollPane.setBorder(BorderFactory.createLineBorder(Color.YELLOW));
        EmployeeTable.setBorder(BorderFactory.createLineBorder(Color.BLUE));

        this.validate();
        this.pack();

    }

    public static void main(String[] args){
        new MainWindow();
    }

}

3 个答案:

答案 0 :(得分:1)

在元素周围使用BorderLayout

还要确保在滚动窗格上设置“首选尺寸”属性。当没有设置此属性时,框架和面板调整大小时,我有奇怪的行为(窗格/字段折叠/消失)。

答案 1 :(得分:1)

对于滚动窗格,请更改

constraints.fill = constraints.HORIZONTAL;

constraints.fill = constraints.BOTH;

评论中提到的第二个问题是固定的 通过添加

constraints.weighty = 0;

按钮。

完整的固定示例:

package com.zetcode;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;


public class MainWindow extends JFrame {

    private JPanel EmployeePanel;
    private JButton add, remove, edit;
    private JTable EmployeeTable;
    private JScrollPane EmployeeTableScrollPane;

    private JMenuBar menu;
    private JMenu file;
    private JMenuItem exit;

    private final String[] columns = {"First Name", "Last Name", "Initials"};
    private String[][] data = {
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"},
            {"First Name", "Last Name", "Initials"}
            };



    public MainWindow(){
        //Set title
        super("Scheduler");

        initUI();

    }

    private void initUI() {

        createMenuBar();

        //Set JFrame properties
        //setSize(new Dimension(800,600));
        //setMinimumSize(new Dimension(300,300));

        //setLayout(new BorderLayout());

        //Initialize JComponents
        EmployeeTable = new JTable(data, columns){
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };

        EmployeeTableScrollPane = new JScrollPane(EmployeeTable);

        add = new JButton("Add");
        remove = new JButton("Remove");
        edit = new JButton("Edit");


        GridBagConstraints constraints = new GridBagConstraints();
        EmployeePanel = new JPanel(new GridBagLayout());
        //Add JScrollPane
        constraints.weightx = 1;
        constraints.weighty = 1;
        constraints.gridx = 0;
        constraints.gridy = 0;
        constraints.gridwidth = 3;
        constraints.gridheight = 1;
        constraints.anchor = GridBagConstraints.NORTH;
        constraints.fill = GridBagConstraints.BOTH;
        EmployeePanel.add(EmployeeTableScrollPane, constraints);

        //Add Buttons
        constraints.gridx = 0;
        constraints.gridy = 1;
        constraints.weighty = 0;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.anchor = GridBagConstraints.SOUTH;
        constraints.fill = GridBagConstraints.HORIZONTAL;
        EmployeePanel.add(add, constraints);

        constraints.gridx = 1;
        constraints.gridy = 1;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.anchor = GridBagConstraints.SOUTH;
        constraints.fill = GridBagConstraints.HORIZONTAL;
        EmployeePanel.add(edit, constraints);

        constraints.gridx = 2;
        constraints.gridy = 1;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.anchor = GridBagConstraints.SOUTH;
        constraints.fill = GridBagConstraints.HORIZONTAL;
        EmployeePanel.add(remove, constraints);

        //Add EmployeePanel
        this.add(EmployeePanel, BorderLayout.CENTER);

        EmployeeTableScrollPane.setBorder(BorderFactory.createLineBorder(Color.YELLOW));
        EmployeeTable.setBorder(BorderFactory.createLineBorder(Color.BLUE));

        //this.validate();
        pack();

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    private void createMenuBar() {

        menu = new JMenuBar();
        file = new JMenu("File");
        exit = new JMenuItem("Exit");

        //Set MenuBar
        file.add(exit);
        menu.add(file);
        setJMenuBar(menu);        
    }

    public static void main(String[] args){

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MainWindow ex = new MainWindow();
                ex.setVisible(true);
            }
        });
    }
}

已解决的问题:

无需致电this.validate();

您同时打电话

setSize(new Dimension(800,600));

pack();

无论是打电话给另一方,pack()都是首选方式。

无需致电

setLayout(new BorderLayout());

BorderLayout是框架内容窗格的默认布局。

应该在EDT(事件调度线程)上启动应用程序:

EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        MigLayoutMainWindow ex = new MigLayoutMainWindow();
        ex.setVisible(true);
    }
});

最后,我会选择MigLayoutGroupLayout经理 GridBagLayout经理。它们更强大,更灵活。

答案 2 :(得分:0)

我有一个与滚动窗格类似的东西,我发现让它工作的方法是手动计算高度,然后覆盖高度属性。我采用这种方法,因为我想要构建的部分内容保持相同的高度,无论窗口如何调整大小。滚动窗格很有趣。