ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java-可滚动(GridBagLayout)面板内的空JTables-列在调整大小时折叠

2019-10-27 00:03:21  阅读:249  来源: 互联网

标签:gridbaglayout swing jtable jtableheader java


我试图创建一个“分段”表,实际上是通过GridBagLayout在“可滚动” JPanel中布置的多个表.这些表共享相同的表模型(类),表头和列模型,将JTableHeader设置为包含所有内容的JScrollPane的列头视图.只有一个JScrollPane.

frame (BorderLayout)
    |- JScrollPane
        |- JPanel (GridBagLayout)
            |- Section title panel
            |- JTable 1
            |- Section title panel
            |- JTable 2
            |- JTable (fake)
            |- vertical filler

一切似乎都按预期工作,直到我尝试调整任一表中没有值的任意列的大小-如果表中至少有一行,则按预期工作.我考虑过在表中包含“空”行,但是这会干扰过滤,排序等操作.因此,我更改了代码以包含“模糊的”伪表,这是为了始终保持一行而使标题保持良好的状态.

但是,这不起作用.一旦其中一个表为空并尝试调整列大小,表头就会损坏(其中一列会收缩).

enter image description here

为什么会发生这种情况,我该怎么办?

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.Scrollable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

public class SectionTables extends JFrame {

    public SectionTables() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        GridBagConstraints gbc;

        JPanel tables = new ScrollableJPanel(new GridBagLayout());
        JScrollPane scrollPane = new JScrollPane(tables);

        JPanel section1Title = new JPanel(new BorderLayout());     
        section1Title.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, UIManager.getColor("controlShadow")));
        JLabel section1 = new JLabel("Section One", null, JLabel.CENTER);
        section1Title.add(section1);
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1.0d;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        tables.add(section1Title, gbc);

        MyTableModel model1 = new MyTableModel();
        JTable table1 = new MyTable(model1);
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.weightx = 1.0d;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        tables.add(table1, gbc);

        JPanel section2Title = new JPanel(new BorderLayout());     
        section2Title.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, UIManager.getColor("controlShadow")));
        JLabel section2 = new JLabel("Section Two", null, JLabel.CENTER);
        section2Title.add(section2);
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.weightx = 1.0d;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        tables.add(section2Title, gbc);

        MyTableModel model2 = new MyTableModel();
        JTable table2 = new MyTable(model2);   
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.weightx = 1.0d;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        tables.add(table2, gbc);

        MyTableModel modelFake = new MyTableModel();
        modelFake.addRow(new String[] {"", "", ""});
        JTable tableFake = new MyObscuredTable();   
        tableFake.setModel(modelFake);
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 4;
        gbc.weightx = 1.0d;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        tables.add(tableFake, gbc);

        Box.Filler filler1 = new Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(0, 32767));
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 5;
        gbc.weighty = 1.0d;
        gbc.fill = GridBagConstraints.VERTICAL;
        tables.add(filler1, gbc);

        add(scrollPane);

        TableColumnModel columnModel = table1.getColumnModel();
        table2.setColumnModel(columnModel);
        tableFake.setColumnModel(columnModel);

        JTableHeader tableHeader = new JTableHeader(columnModel);
        scrollPane.setColumnHeaderView(tableHeader);
        table1.setTableHeader(tableHeader);
        table2.setTableHeader(tableHeader);
        tableFake.setTableHeader(tableHeader);


        // if tables are filled, the issue does not occur
//        model1.addRow(new String[] {"", "", ""});
//        model2.addRow(new String[] {"", "", ""});

        pack();
        setLocationRelativeTo(null);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new SectionTables().setVisible(true);
            }
        });
    }

    private class MyTableModel extends DefaultTableModel {
        private String[] columnNames = new String[] {"First", "Second", "Third"};
        private Class[] columnClasses = new Class[] {String.class, String.class, String.class};

        @Override
        public int getColumnCount() {
            return columnNames.length;
        }

        @Override
        public String getColumnName(int column) {
            return columnNames[column];
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return columnClasses[columnIndex];
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }        

    }

    private class ScrollableJPanel extends JPanel implements Scrollable {

        public ScrollableJPanel(LayoutManager layout) {
            super(layout);
        }

        public ScrollableJPanel() {
            super();
        }

        @Override
        public Dimension getPreferredScrollableViewportSize() {
            return getPreferredSize();
        }

        @Override
        public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
            return 16;
        }

        @Override
        public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
            return 16;
        }

        @Override
        public boolean getScrollableTracksViewportWidth() {
            return true;
        }

        @Override
        public boolean getScrollableTracksViewportHeight() {
            return false;
        }

    }

    private class MyObscuredTable extends JTable {

        @Override
        public Dimension getPreferredSize() {
            int height; 
            height = 1; // obscure null row           
            Container ancestorOfClass = SwingUtilities.getAncestorOfClass(JPanel.class, this);
            int width = ancestorOfClass.getWidth();
            return new Dimension(width, height);
        }

    }

    private class MyTable extends JTable {

        public MyTable(TableModel model) {
            super(model);
        }

        @Override
        public Dimension getPreferredSize() {
            int height; 
            height = getRowHeight() * getRowCount();
            Container ancestorOfClass = SwingUtilities.getAncestorOfClass(JPanel.class, this);
            int width = ancestorOfClass.getWidth();
            return new Dimension(width, height);
        }

    }
}

解决方法:

也许您可以修改这种方法,该方法在使用多个表时使用TableColumnModelListener来使列宽保持同步:

import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

public class TableColumnsShared implements Runnable
{
  JTable table1, table2;
  TableColumnModelListener columnListener1, columnListener2;
  Map<JTable, TableColumnModelListener> map;

  public static void main(String[] args)
  {
    SwingUtilities.invokeLater(new TableColumnsShared());
  }

  public void run()
  {
    Vector<String> names = new Vector<String>();
    names.add("One");
    names.add("Two");
    names.add("Three");

    table1 = new JTable(null, names);
    table2 = new JTable(null, names);

    columnListener1 = new ColumnChangeListener(table1, table2);
    columnListener2 = new ColumnChangeListener(table2, table1);

    table1.getColumnModel().addColumnModelListener(columnListener1);
    table2.getColumnModel().addColumnModelListener(columnListener2);

    map = new HashMap<JTable, TableColumnModelListener>();
    map.put(table1, columnListener1);
    map.put(table2, columnListener2);

    JPanel p = new JPanel(new GridLayout(2,1));
    p.add(new JScrollPane(table1));
    p.add(new JScrollPane(table2));

    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(p);
    frame.setSize(300, 200);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }

  class ColumnChangeListener implements TableColumnModelListener
  {
    JTable sourceTable;
    JTable targetTable;

    public ColumnChangeListener(JTable source, JTable target)
    {
      this.sourceTable = source;
      this.targetTable = target;
    }

    public void columnAdded(TableColumnModelEvent e) {}
    public void columnSelectionChanged(ListSelectionEvent e) {}
    public void columnRemoved(TableColumnModelEvent e) {}
    public void columnMoved(TableColumnModelEvent e) {}

    public void columnMarginChanged(ChangeEvent e)
    {
      TableColumnModel sourceModel = sourceTable.getColumnModel();
      TableColumnModel targetModel = targetTable.getColumnModel();
      TableColumnModelListener listener = map.get(targetTable);

      targetModel.removeColumnModelListener(listener);

      for (int i = 0; i < sourceModel.getColumnCount(); i++)
      {
        targetModel.getColumn(i).setPreferredWidth(sourceModel.getColumn(i).getWidth());
      }

      targetModel.addColumnModelListener(listener);
    }
  }
}

标签:gridbaglayout,swing,jtable,jtableheader,java
来源: https://codeday.me/bug/20191026/1940322.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有