java - 尝试使用正确的行标题创建 JTable

标签 java swing header jtable look-and-feel

我正在尝试创建一个 JTable,它有一个看起来像列标题的行标题,我在上面花了太多时间:/ 我的情况类似于这个问题:JTable Row Header Implementation 也许这个: customizing jtable cellrenderer with table's cell header color

他们似乎还没有把我带到那里。我已经搜索并尝试了很多示例,但都缺乏。 Oracle/Sun 甚至没有任何带有行标题的表示例。看来这种 table 应该不多见。

这只是格式化第一列,但它看起来或不像列标题: http://java-swing-tips.blogspot.com/2011/01/jtable-rowheader.html

这似乎对行标题使用了 JList,它存在对齐问题(每行偏移 +1 像素),并且当我设置外观时看起来并不好。 http://www.java2s.com/Code/Java/Swing-Components/TableRowHeaderExample.htm

这似乎是我需要使用的想法(行标题是一个单独的 JTable,但随后作为行标题加载到 JScrollPane),但我需要使其适应我的代码,然后确保行标题获取 header 的正确外观。
http://www.chka.de/swing/table/row-headers/JTable.html

这就是我所做的减去最后一点。我尝试让表头的渲染器也成为行头的渲染器。行标题/第一列现在是灰色而不是白色,因为它只是另一个数据列,但看起来仍然不像列标题。这是正确的吗?还是我应该坚持将其作为主表中的常规列并对其进行其他操作?

这是我更新表格的代码。此方法只是采用一个字符串数组作为列标题,一个字符串数组作为行标题,一个二维字符串数组作为主要数据。我有一个用于行标题的 JTable dispTableRowHeader 和一个用于主数据表的 JTable dispTable

    private void updateDispTable(String[][] graphicalTable, String[] graphicalTableColumnHeader, String[] graphicalTableRowHeader) {

    //set model for the main data table, put in data. Also prevent editing cells
    dispTable.setModel(new javax.swing.table.DefaultTableModel(
        graphicalTable,
        graphicalTableColumnHeader
    ){
        @Override
        public boolean isCellEditable(int rowIndex, int mColIndex) {
            return false;
        }
    });

    //some mods for main data table
    dispTable.getTableHeader().setReorderingAllowed(false);//Was also able to do this within NetBeans GUI Builder by doing Table Contents from Jtable inspector item
    dispTable.getTableHeader().setResizingAllowed(false);

    //load main table to scrollpane
    jScrollPane2.setViewportView(dispTable);

    //get model for JTable that will be used as the row header, fill in values
    DefaultTableModel rowHeaderTableModel = new DefaultTableModel(0, 1);//one column
    for (int i = 0; i < graphicalTable.length; i++)
        rowHeaderTableModel.addRow(new Object[] { graphicalTableRowHeader[i] } );

    //set model for row header, put in data. Alter renderer to make it like col header
    dispTableRowHeader.setModel(rowHeaderTableModel);
    dispTableRowHeader.setDefaultRenderer(Object.class, dispTableRowHeader.getTableHeader().getDefaultRenderer());//makes it gray but not like the header :/
    //dispTableRowHeader.setDefaultRenderer(Object.class, jScrollPane2.getColumnHeader().getDefaultRenderer());

    //load row header to scrollpane's row header
    jScrollPane2.setRowHeaderView(dispTableRowHeader);

    //set the table corner and disallow reordering and resizing
    JTableHeader corner = dispTableRowHeader.getTableHeader();
    corner.setReorderingAllowed(false);
    corner.setResizingAllowed(false);
    jScrollPane2.setCorner(JScrollPane.UPPER_LEFT_CORNER, corner);//load to scrollpane
}

非常感谢任何帮助!

编辑下方编辑下方 我创建了一个全新的项目来进行实验并尝试了 trashgod 的方法(尽管它是针对行标题而不是第二行),我发现它给了我相同的结果,只是单元格样式为灰色而不是像标题一样。然后我尝试删除我的外观调整

        // Set System L&F
        UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );

然后行标题看起来和列标题一样! .. 但那是在 Nimbus 或任何默认的外观和感觉中。请参见下图。第一个是我的外观设置为系统的如上(在 Win7 中),第二个是默认设置。

系统外观 (Win7)- I adjusted look and feel, set to system look and feel

Java 的 Nimbus 外观和感觉- default look and feel

果然我的程序也发生了同样的情况。所以现在看来​​我的问题是外观。我希望它看起来像第一张图片(系统的外观和感觉),但左侧也有样式。

顺便说一句,这是 MySQL Workbench Win7 中的一个示例,它具有样式正确的行标题和列标题,它们甚至在鼠标悬停时将单元格涂成蓝色。太糟糕了,它不是用 Java 制作的,所以我可以尝试检查他们是如何制作的。

MySQL Workbench 截图- MySQL Workbench screenshot

编辑下方编辑下方 SSCCE代码

package mytableexample2;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;

public class MyTableExample2 extends javax.swing.JFrame {

    public MyTableExample2() {
        initComponents();
    }

    @SuppressWarnings("unchecked")
    private void initComponents() {
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable(){
            @Override
            public Component prepareRenderer(
                    TableCellRenderer renderer, int row, int col) {
                if (col == 0) {
                    return this.getTableHeader().getDefaultRenderer()
                        .getTableCellRendererComponent(this,
                        this.getValueAt(row, col), false, false, row, col);
                } else {
                    return super.prepareRenderer(renderer, row, col);
                }
            }
        };
        jTable1.setAutoCreateRowSorter(false);
        final JTableHeader header = jTable1.getTableHeader();
        header.setDefaultRenderer(new HeaderRenderer(jTable1));

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jTable1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {"Row 1", "Data 2", "Data 3", "Data 4", "Data 5"},
                {"Row 2", "Data 6", "Data 7", "Data 8", "Data 9"},
                {"Row 3", "Data 10", "Data 11", "Data 12", "Data 13"}
            },
            new String [] {
                "", "Col 1", "Col 2", "Col 3", "Col 4"
            }
        ));
        jScrollPane1.setViewportView(jTable1);


        //Netbeans generated layout
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 278, Short.MAX_VALUE)
                .addContainerGap())
        );
        pack();
    }


    public static void main(String args[]) {
        try {
            //THIS SETS TO SYSTEM'S LOOK AND FEEL
            UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );

            //THIS SETS TO OTHER JAVA LOOK AND FEEL
            //UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
            //UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");

        } catch (ClassNotFoundException ex) {
                java.util.logging.Logger.getLogger(MyTableExample2.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
        java.util.logging.Logger.getLogger(MyTableExample2.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
        java.util.logging.Logger.getLogger(MyTableExample2.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(MyTableExample2.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MyTableExample2().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;
}

class HeaderRenderer implements TableCellRenderer {
TableCellRenderer renderer;
    public HeaderRenderer(JTable jTable1) {
        renderer = jTable1.getTableHeader().getDefaultRenderer();
    }
    @Override
    public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected,
        boolean hasFocus, int row, int col) {
        return renderer.getTableCellRendererComponent(
            table, value, isSelected, hasFocus, row, col);
    }
}

最佳答案

使用这个 HeaderRenderer作为第一个 row 列渲染器可能会产生您想要的效果:

附录:我更新了示例以反射(reflect)您的手动布局的 sscce。我平台的 getSystemLookAndFeelClassName()com.apple.laf.AquaLookAndFeel,所以我没有看到相同的结果。两个观察结果:您已经setAutoCreateRowSorter(false) 以防止排序小部件激增,并且 Nimbus 保留它交替行突出显示。

enter image description here

import java.awt.Component;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;

public class MyTableExample3 extends JFrame {

    private JScrollPane scrollPane;
    private JTable table;

    public MyTableExample3() {
        initComponents();
    }

    @SuppressWarnings("unchecked")
    private void initComponents() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        table = new javax.swing.JTable() {

            @Override
            public Component prepareRenderer(
                TableCellRenderer renderer, int row, int col) {
                if (col == 0) {
                    return this.getTableHeader().getDefaultRenderer()
                        .getTableCellRendererComponent(this, this.getValueAt(
                            row, col), false, false, row, col);
                } else {
                    return super.prepareRenderer(renderer, row, col);
                }
            }
        };
        table.setAutoCreateRowSorter(false);
        final JTableHeader header = table.getTableHeader();
        header.setDefaultRenderer(new HeaderRenderer(table));

        table.setModel(new javax.swing.table.DefaultTableModel(
            new Object[][]{
                {"Row 1", "Data 2", "Data 3", "Data 4", "Data 5"},
                {"Row 2", "Data 6", "Data 7", "Data 8", "Data 9"},
                {"Row 3", "Data 10", "Data 11", "Data 12", "Data 13"}
            },
            new String[]{
                "", "Col 1", "Col 2", "Col 3", "Col 4"
            }));
        scrollPane = new JScrollPane(table);
        this.add(scrollPane);
        pack();
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new MyTableExample3().setVisible(true);
            }
        });
    }

    private static class HeaderRenderer implements TableCellRenderer {

        TableCellRenderer renderer;

        public HeaderRenderer(JTable table) {
            renderer = table.getTableHeader().getDefaultRenderer();
        }

        @Override
        public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int col) {
            return renderer.getTableCellRendererComponent(
                table, value, isSelected, hasFocus, row, col);
        }
    }
}

关于java - 尝试使用正确的行标题创建 JTable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8002445/

相关文章:

java - 从静态方法获取 Application 实例

java - 如何取消特定的Kotlinc/Javac编译器警告?

java - JPanel 不在 JScrollPane 中滚动

c - mpi.h : Using a type w/o defining it?

css - 如何强制我的标题在顶部?

java - ListView 单元格变得比它们包含的节点更大

java - 为什么它没有显示我的标签?

java - 当嵌套 JPanel 与 GridBagLayout 一起使用时,布局权重会发生变化

http - 404 header - HTTP 1.0 还是 1.1?

java - 将字符串 "30-MAR-07"转换为日期对象