【问题标题】:TableColumnModelListener. JPanel revalidate() method ruins swing elements composition表列模型侦听器。 JPanel revalidate() 方法破坏了摇摆元素的组合
【发布时间】:2015-01-09 12:36:54
【问题描述】:

问题描述:

原来有两张表:

在左表的顶部有两个元素:JTextField 和 JComboBox,它们被放在一个单独的 JPanel 中。表格过滤需要这两个元素,即更改选定的组合框元素或在左侧的 JTextField 获取表格中输入内容被过滤掉。

我尝试实现 TableColumnModelListener 接口以便将 JTextField 和 JComboBox 元素连接到表格。结果不如我预期的那么好:在 JPanel 容器对象上调用的 revalidate() 方法破坏了整个摇摆元素的组合。该实验的结果如下图所示:


源代码:

TablesTest 类:

import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class TablesTest {
    private JFrame frame = new JFrame();

    private javax.swing.JPanel commonTablesPanel;
    private javax.swing.JPanel dataTable1Panel;
    private javax.swing.JPanel dataTable2Panel;
    private javax.swing.JTable datatable1Table;
    private javax.swing.JTable datatable2Table;
    private javax.swing.JComboBox filterComboBox;
    private javax.swing.JPanel filterPanel;
    private javax.swing.JTextField filterTextField;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;

    private TableResizeListener tableResizeListener1;

    public TablesTest() {
        java.awt.GridBagConstraints gridBagConstraints;

        commonTablesPanel = new javax.swing.JPanel();
        dataTable1Panel = new javax.swing.JPanel();
        filterPanel = new javax.swing.JPanel();
        filterTextField = new javax.swing.JTextField();
        filterComboBox = new javax.swing.JComboBox();
        jScrollPane3 = new javax.swing.JScrollPane();
        datatable1Table = new javax.swing.JTable();
        dataTable2Panel = new javax.swing.JPanel();
        jScrollPane4 = new javax.swing.JScrollPane();
        datatable2Table = new javax.swing.JTable();

        frame.setLayout(new java.awt.GridBagLayout());

        commonTablesPanel.setMinimumSize(new java.awt.Dimension(30, 30));
        commonTablesPanel.setPreferredSize(new java.awt.Dimension(30, 30));
        commonTablesPanel.setLayout(new java.awt.GridBagLayout());

        dataTable1Panel.setLayout(new java.awt.GridBagLayout());

        filterPanel.setLayout(new java.awt.GridBagLayout());

        filterTextField.setPreferredSize(new java.awt.Dimension(30, 20));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        filterPanel.add(filterTextField, gridBagConstraints);

        filterComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        filterComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                //TODO
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        filterPanel.add(filterComboBox, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        dataTable1Panel.add(filterPanel, gridBagConstraints);

        jScrollPane3.setPreferredSize(new java.awt.Dimension(30, 30));

        datatable1Table.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null}
            },
            new String [] {
                "Title 1", "Titile 2"
            }
        ));
        datatable1Table.setMinimumSize(new java.awt.Dimension(30, 30));
        jScrollPane3.setViewportView(datatable1Table);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.weighty = 0.1;
        dataTable1Panel.add(jScrollPane3, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.weighty = 0.1;
        commonTablesPanel.add(dataTable1Panel, gridBagConstraints);

        dataTable2Panel.setLayout(new java.awt.GridBagLayout());

        jScrollPane4.setPreferredSize(new java.awt.Dimension(30, 30));

        datatable2Table.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null},
                {null, null}
            },
            new String [] {
                "Titile 1", "Title 2"
            }
        ) {
            boolean[] canEdit = new boolean [] {
                false, false
            };

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        datatable2Table.setMinimumSize(new java.awt.Dimension(30, 30));
        jScrollPane4.setViewportView(datatable2Table);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.weighty = 0.1;
        dataTable2Panel.add(jScrollPane4, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.weighty = 0.1;
        commonTablesPanel.add(dataTable2Panel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.weighty = 0.1;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 4);
        frame.add(commonTablesPanel, gridBagConstraints);

        tableResizeListener1 = new TableResizeListener(datatable1Table, filterPanel);

        frame.setPreferredSize(new Dimension(400,150));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                TablesTest tableTest = new TablesTest();
            }
        });
    }
}

通知

tableResizeListener1 = new TableResizeListener(datatable1Table, filterPanel);

部分。这是所有表格列都连接到相应的 JPanel 元素(本示例中为 JTextField 和 JComboBox)的地方。如果您想观察没有连接元素的合成看起来如何,可以将这一行注释掉。


TableResizeListener 类。这就是问题所在。

import java.awt.Component;
import java.awt.Dimension;

import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableColumnModelListener;
import javax.swing.table.TableColumnModel;

public class TableResizeListener implements TableColumnModelListener {
    private static final long serialVersionUID = 1L;
    private JTable table = null;

    private JPanel filterRow = null;



    public TableResizeListener(JTable table, JPanel filterRow) {
        this.table = table;
        this.filterRow = filterRow;

        this.table.getColumnModel().addColumnModelListener(this);

        columnMarginChanged(new ChangeEvent(table.getColumnModel()));
    }

    //  Implement TableColumnModelListener methods
    //  (Note: instead of implementing a listener you should be able to
    //  override the columnMarginChanged and columMoved methods of JTable)
    @Override
    public void columnMarginChanged(ChangeEvent e) {
        TableColumnModel tcm = table.getColumnModel();
        int columns = tcm.getColumnCount();

        if(columns == filterRow.getComponentCount()) {
            for (int i = 0; i < columns; i++) {
                Component comp = filterRow.getComponent(i);
                Dimension d = comp.getPreferredSize();
                d.width = tcm.getColumn(i).getWidth();
                comp.setPreferredSize(d);
            }

            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    filterRow.revalidate();
                }
            });
        }
    }

    @Override
    public void columnMoved(TableColumnModelEvent e) {
        Component moved = filterRow.getComponent(e.getFromIndex());
        filterRow.remove(e.getFromIndex());
        filterRow.add(moved, e.getToIndex());
        filterRow.validate();
    }

    @Override
    public void columnAdded(TableColumnModelEvent e) {
    }

    @Override
    public void columnRemoved(TableColumnModelEvent e) {
    }

    @Override
    public void columnSelectionChanged(ListSelectionEvent e) {
    }
}

线

filterRow.revalidate();

对这个错误负责。我尝试调用 repaint()、validate(),但是它导致视觉体验不那么流畅。

如何在不破坏视觉构图的情况下将元素连接到 JTable 外部?

【问题讨论】:

    标签: java swing jtable listener


    【解决方案1】:

    将此行注释掉以解决您的问题。

    jScrollPane4.setPreferredSize(new java.awt.Dimension(30, 30));

    【讨论】:

    • @trashgod 我已经阅读了您的链接帖子,但是如果我删除行 jScrollPane3.setPreferredSize(new java.awt.Dimension(30, 30));从左表(答案建议从右表中删除类似的行),然后表头调整大小不再起作用。我会说这很奇怪,因为链接帖子中的答案建议根本不要使用 setPreferredSize 类型的方法。
    • @Benas:您可以在JTableScrollable 实现中覆盖getPreferredScrollableViewportSize();更多here.
    猜你喜欢
    • 2016-11-16
    • 1970-01-01
    • 2012-06-30
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 2015-09-20
    相关资源
    最近更新 更多