JScrollPane中的JTable没有正确显示

时间:2014-03-07 09:29:29

标签: java swing user-interface jtable jscrollpane

我正在编写一段代码的GUI,我一直在修补它。我被困在程序的这一部分,我想要一个用户选择以预览方式在JTable中显示的数据文件(即用户不能编辑表格上的数据)。 / p>

单击“实验参数”选项卡中的按钮(参见下面的屏幕截图),我创建并运行“PreviewAction”,创建一个新选项卡,并用必要的组件填充它。以下是DataPreviewAction的代码。 编辑:我还发布了self-contained, minimal version这个模仿真实项目中的条件,并表现出相同的行为。

import java.awt.BorderLayout;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;

public class MyFrame extends JFrame {

private JPanel panel1;
private JTabbedPane tabs;
private JButton runButton;

public MyFrame() {
    tabs = new JTabbedPane();
    panel1 = new JPanel();
    runButton = new JButton("go!");
    runButton.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            runButtonActionPerformed(evt);
        }
    });
    panel1.add(runButton);
    tabs.addTab("first tab", panel1);
    this.add(tabs);
    pack();
}

public static void main(String args[]) {
    try {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager
                .getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException ex) {
        java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(
                java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
        java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(
                java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(
                java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(MyFrame.class.getName()).log(
                java.util.logging.Level.SEVERE, null, ex);
    }

    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {

        public void run() {
            MyFrame frame = new MyFrame();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    });
}

private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {
    /*
     * Normally there is more stuff happening here but this much will do for
     * the sake of example
     */
    List<String[]> data = new LinkedList<String[]>();
    for (int i = 1; i < 1000; i++)
        data.add(new String[] { "entry1", "value1", "value2", "value3" });

    SwingUtilities.invokeLater(new DataPreviewAction(data, tabs));
}

public class DataPreviewAction implements Runnable {

    private JTabbedPane contentHolder;
    private List<String[]> data;

    public DataPreviewAction(List<String[]> data, JTabbedPane comp) {
        this.contentHolder = comp;
        this.data = data;
    }

    @Override
    public void run() {
        DefaultTableModel previewModel = new DefaultTableModel() {
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };

        for (String[] datarow : data) {
            previewModel.addRow(Arrays.copyOf(datarow, datarow.length,
                    Object[].class));
        }

        JTable table = new JTable(previewModel);

        JPanel buttonPanel = new JPanel();
        buttonPanel.add(new JButton("A button"));
        buttonPanel.add(new JLabel(
                "Some description for the awesome table below "));
        buttonPanel.add(new JButton("another button"));

        JScrollPane tablePanel = new JScrollPane(table);
        JPanel container = new JPanel();
        container.setLayout(new BorderLayout());
        container.add(buttonPanel, BorderLayout.NORTH);
        container.add(tablePanel, BorderLayout.CENTER);
        contentHolder.addTab("Preview", container);
        contentHolder.validate();
        contentHolder.repaint();
    }
}
}

这里至少有两个问题:

  1. JTable(或JScrollPane)根本无法呈现
  2. JScrollPane没有框架本身那么宽,我不知道为什么
  3. 我在Swing中并不是那么好,所以我可能会遗漏一些基本的东西。我已检查数据文件是否正确读取,数据模型包含正确的行数(1000+)。所以桌子不应该是空的。

    建议?

    screenshot of the problem

2 个答案:

答案 0 :(得分:6)

JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton("A button"));
buttonPanel.add(new JLabel("Some description for the awesome table below "));
buttonPanel.add(new JButton("another button"));

JScrollPane tablePanel = new JScrollPane(table);
JPanel container = new JPanel();
container.add(buttonPanel,BorderLayout.NORTH);
container.add(tablePanel,BorderLayout.SOUTH);
contentHolder.addTab("Preview", container);
    //contentHolder.validate(); <- NO good
    //contentHolder.repaint();  <- --"---
}
  • JPanel使用FlowLayout(在API中实现,仅限于PreferredSize,默认情况下不可调整大小),正确的输出如在attn图像中所示,您必须更改默认值{ {3}} JPanelLayoutManager,然后是代码行

container.add(buttonPanel,BorderLayout.NORTH);
container.add(tablePanel,BorderLayout.SOUTH);
  • 会展开BorderLayout并且可以按预期工作,但我认为tablePanel应放在CENTER区域

编辑:

enter image description here

import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class MyFrame extends JFrame {

    private JPanel panel1;
    private JTabbedPane tabs;
    private JButton runButton;
    private JFrame frame = new JFrame();
    private String[] columnNames = {"Nama", "Nim", "IP", "Hapus Baris ke"};
    private Object[][] data = {
        {"igor", "B01_125-358", "1.124.01.125", true},
        {"lenka", "B21_002-242", "21.124.01.002", true},
        {"peter", "B99_001-358", "99.124.01.001", false},
        {"zuza", "B12_100-242", "12.124.01.100", true},
        {"jozo", "BUS_011-358", "99.124.01.011", false},
        {"nora", "B09_154-358", "9.124.01.154", false},
        {"xantipa", "B01_001-358", "1.124.01.001", false},};
    private DefaultTableModel model = new DefaultTableModel(data, columnNames) {
        private static final long serialVersionUID = 1L;

        @Override
        public boolean isCellEditable(int row, int column) {
            switch (column) {
                case 3:
                    return true;
                default:
                    return false;
            }
        }

        @Override
        public Class getColumnClass(int column) {
            return getValueAt(0, column).getClass();
        }
    };

    public MyFrame() {
        tabs = new JTabbedPane();
        panel1 = new JPanel();
        runButton = new JButton("go!");
        runButton.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                //
            }
        });
        panel1.add(runButton);
        tabs.addTab("first tab", panel1);
        JTable table = new JTable(model);
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(new JButton("A button"));
        buttonPanel.add(new JLabel("Some description for the awesome table below "));
        buttonPanel.add(new JButton("another button"));
        JScrollPane tablePanel = new JScrollPane(table);
        JPanel container = new JPanel();
        container.setLayout(new BorderLayout());
        container.add(buttonPanel, BorderLayout.NORTH);
        container.add(tablePanel, BorderLayout.CENTER);
        tabs.addTab("Preview", container);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(tabs);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MyFrame frame = new MyFrame();

            }
        });
    }
}

编辑第二。例如

enter image description here

来自代码(包括您将数据填充到模型中的想法)

import java.awt.BorderLayout;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class MyFrame extends JFrame {

    private JPanel panel1;
    private JTabbedPane tabs;
    private JButton runButton;
    private JFrame frame = new JFrame();
    private String[] columnNames = {"Nama", "Nim", "IP", "Hapus Baris ke"};
    private Object[][] data = {
        {"igor", "B01_125-358", "1.124.01.125", "true"},
        {"lenka", "B21_002-242", "21.124.01.002", "true"},
        {"peter", "B99_001-358", "99.124.01.001", "false"},
        {"zuza", "B12_100-242", "12.124.01.100", "true"},
        {"jozo", "BUS_011-358", "99.124.01.011", "false"},
        {"nora", "B09_154-358", "9.124.01.154", "false"},
        {"xantipa", "B01_001-358", "1.124.01.001", "false"},};
    private DefaultTableModel model = new DefaultTableModel(data, columnNames) {
        private static final long serialVersionUID = 1L;

        @Override
        public boolean isCellEditable(int row, int column) {
            switch (column) {
                case 3:
                    return true;
                default:
                    return false;
            }
        }

        @Override
        public Class getColumnClass(int column) {
            return getValueAt(0, column).getClass();
        }
    };

    public MyFrame() {
        tabs = new JTabbedPane();
        panel1 = new JPanel();
        runButton = new JButton("go!");
        runButton.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                List<String[]> data = new LinkedList<String[]>();
                for (int i = 1; i < 10; i++) {
                    data.add(new String[]{"entry1", "value1", "value2", "value3"});
                }
                for (String[] datarow : data) {
                    model.addRow(Arrays.copyOf(datarow, datarow.length, Object[].class));
                }
            }
        });
        panel1.add(runButton);
        tabs.addTab("first tab", panel1);
        JTable table = new JTable(model);
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(new JButton("A button"));
        buttonPanel.add(new JLabel("Some description for the awesome table below "));
        buttonPanel.add(new JButton("another button"));
        JScrollPane tablePanel = new JScrollPane(table);
        JPanel container = new JPanel();
        container.setLayout(new BorderLayout());
        container.add(buttonPanel, BorderLayout.NORTH);
        container.add(tablePanel, BorderLayout.CENTER);
        tabs.addTab("Preview", container);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(tabs);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MyFrame frame = new MyFrame();

            }
        });
    }
}

答案 1 :(得分:2)

跟随mKorbel的脚步,我最终做了一些调试。我在这里提供它,以防其他人遇到同样的问题。

当初始化时为基础DataModel提供数据矩阵时,表格看起来很奇怪

private DefaultTableModel model = new DefaultTableModel(data, columnNames)

但使用空构造函数

创建时无法正常显示
private DefaultTableModel model = new DefaultTableModel()

稍后使用model.addRow(Object[] row);

添加行

我开始浏览source code,结果是空构造函数,模型的行数和列数(私有字段)被启动为0而未正确更新然后。我在调试时注意到了这一点,因为我的表的尺寸为1370 x 0,这当然无法正常显示。

由于我不想事先对行/列的数量进行硬编码,最好的做法是将我的“行”转换为矩阵,并通过构造函数将数据提供给model(很像mKorbel所做的那样)。这是有趣的部分,如果您想提供数据,那么您还需要提供列名称。事实上,你必须有列名称是违反直觉的(恕我直言),如果你没有/需要标题会发生什么?数据已经是表格形式,所以我不明白为什么列名这么重要。

无论如何,以下代码至少呈现该表:

String[] colNames = new String[data[1].length];
for(int i=0; i<colNames.length; i++)
    colNames[i] = "C" + i;

DefaultTableModel model = new DefaultTableModel(data,colNames){
    @Override
    public boolean isCellEditable(int row, int column){
        return false;
    }};

我接受这个是因为它指出了问题的根源,但如果没有mKorbel的回答我就无法查明问题,所以请给予他/她的回答: