java - 调整 JFrame 大小后 JScrollPane 崩溃

标签 java jtable jframe jscrollpane layout-manager

我遇到了一些 LayoutManager 问题(我相信)。我正在为自己做一个小项目,我在下面复制了我的问题。问题是,当我使窗口比原始大小小一个像素(在 x 或 y 方向上,无关紧要)时,整个 JScrollPane 就会崩溃,以至于表格不存在更长可见。

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

我查了各种问题来解决这个问题,但答案相差很大,我没有找到适合我的问题的解决方案。我对布局管理器有一个大致的了解,但显然还不够广泛,无法弄清楚这一点。感谢您提前提供的任何帮助。

帧正常:

Frame normal

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

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

}

最佳答案

对于滚动 Pane ,更改

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 是框架内容 Pane 的默认布局。

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

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

最后,我会使用 MigLayoutGroupLayout 管理器 GridBagLayout 管理器的。它们更强大、更灵活。

关于java - 调整 JFrame 大小后 JScrollPane 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25018084/

相关文章:

java - Java EE 7 的核心接口(interface)(EntityManager 等)能否扩展 AutoCloseable?

java - JodaTime PeriodFormat,只有 1 个字段的耗时

java - 比较大量字符串的最有效算法是什么?

java: JTable DefaultTableModel addRow(Object[] rowData)

java - 列太小的 TableCellRenderer 没有点后缀

java - 在 JFrame 上用图形对象绘制文本

java - 使用 Java 的 Pdf 页数

java - JTable 列中 Toedter 的 JDateChooser

Java ArrayList 帮助!

java - 单击 jbutton 后如何更改其颜色?