JTable 右对齐标题

发布于 2024-12-06 04:41:33 字数 90 浏览 1 评论 0 原文

基本上,我有一个 JTable,其中包含带有右对齐单元格但左对齐标题的列,这看起来非常糟糕。我想右对齐这些列的标题而不改变标题的“外观和感觉”。

谢谢

Basically, I have a JTable containing columns with right-aligned cells but left-aligned headers which looks really bad. I would like to right-align the headers of these columns without altering the "Look and Feel" of the headers.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

黑凤梨 2024-12-13 04:41:34
DefaultTableCellRenderer defaultHeaderRenderer = (DefaultTableCellRenderer) getTableHeader().getDefaultRenderer();
defaultHeaderRenderer.setHorizontalAlignment(JLabel.CENTER);         
getTableHeader().setDefaultRenderer(defaultHeaderRenderer);

我在JAVA8下测试过。工作正常。

DefaultTableCellRenderer defaultHeaderRenderer = (DefaultTableCellRenderer) getTableHeader().getDefaultRenderer();
defaultHeaderRenderer.setHorizontalAlignment(JLabel.CENTER);         
getTableHeader().setDefaultRenderer(defaultHeaderRenderer);

I have tested in JAVA8. working fine.

泪之魂 2024-12-13 04:41:34

试试这个代码,

JTableHeader jtableHeader = jtable.getTableHeader();
DefaultTableCellRenderer rend = (DefaultTableCellRenderer) jtable.getTableHeader().getDefaultRenderer();
rend.setHorizontalAlignment(JLabel.CENTER);
jtableHeader.setDefaultRenderer(rend);

Try this code,

JTableHeader jtableHeader = jtable.getTableHeader();
DefaultTableCellRenderer rend = (DefaultTableCellRenderer) jtable.getTableHeader().getDefaultRenderer();
rend.setHorizontalAlignment(JLabel.CENTER);
jtableHeader.setDefaultRenderer(rend);
樱花细雨 2024-12-13 04:41:34

我已经根据 pvbemmelen62 的解决方案创建了一个类,可以非常轻松地使用它,例如:

AlignHeaderRenderer.install(myTable, new int[] { SwingConstants.RIGHT,
                        SwingConstants.RIGHT, SwingConstants.LEFT });

AlignHeaderRenderer.install(myTable, 0, SwingConstants.RIGHT);
AlignHeaderRenderer.install(myTable, 1, SwingConstants.RIGHT);

代码如下:

public class AlignHeaderRenderer implements TableCellRenderer {

private final TableCellRenderer renderer;
private final int alignment;

public static void install(final JTable table, final int[] alignments) {
    for (int i = 0; i < alignments.length; ++i)
        install(table, i, alignments[i]);
}

public static void install(final JTable table, final int row,
        final int alignment) {
    table.getTableHeader().getColumnModel().getColumn(row)
            .setHeaderRenderer(new AlignHeaderRenderer(table, alignment));
}

private AlignHeaderRenderer(final JTable table, final int alignment) {
    renderer = table.getTableHeader().getDefaultRenderer();
    this.alignment = alignment;
}

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

}

I have created a class based on the solution of pvbemmelen62, that can be used very easily, for example:

AlignHeaderRenderer.install(myTable, new int[] { SwingConstants.RIGHT,
                        SwingConstants.RIGHT, SwingConstants.LEFT });

or

AlignHeaderRenderer.install(myTable, 0, SwingConstants.RIGHT);
AlignHeaderRenderer.install(myTable, 1, SwingConstants.RIGHT);

Here's the code:

public class AlignHeaderRenderer implements TableCellRenderer {

private final TableCellRenderer renderer;
private final int alignment;

public static void install(final JTable table, final int[] alignments) {
    for (int i = 0; i < alignments.length; ++i)
        install(table, i, alignments[i]);
}

public static void install(final JTable table, final int row,
        final int alignment) {
    table.getTableHeader().getColumnModel().getColumn(row)
            .setHeaderRenderer(new AlignHeaderRenderer(table, alignment));
}

private AlignHeaderRenderer(final JTable table, final int alignment) {
    renderer = table.getTableHeader().getDefaultRenderer();
    this.alignment = alignment;
}

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

}
芸娘子的小脾气 2024-12-13 04:41:34

秘诀是使用虚拟表中的渲染器来获取正确的 L&F,并从真实表的行渲染器中复制对齐方式。这样每一列就分别对齐。代码如下:

table.getTableHeader().setDefaultRenderer(new DefaultTableCellRenderer() {
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
        Component c2 = dummy.getTableHeader().getDefaultRenderer().getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
        if (table.getRowCount() > 0) {
            Component c3 = table.getCellRenderer(0, col).getTableCellRendererComponent(table, value, isSelected, hasFocus, 0, col);
            if (c2 instanceof JLabel && c3 instanceof JLabel)
                ((JLabel)c2).setHorizontalAlignment(((JLabel)c3).getHorizontalAlignment());
        }
        return c2;
    }
    private final JTable dummy = new JTable();
});

上面的代码没有保留任何对渲染器的引用,因此避免了上面提到的 NPE bug。它不需要任何命名类,因此您只需将代码放在需要的地方即可。

The secret is to use the renderer from a dummy table to get correct L&F, and copy the alignment from the real table's row renderer. That way each column in aligned separately. Here is the code:

table.getTableHeader().setDefaultRenderer(new DefaultTableCellRenderer() {
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
        Component c2 = dummy.getTableHeader().getDefaultRenderer().getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
        if (table.getRowCount() > 0) {
            Component c3 = table.getCellRenderer(0, col).getTableCellRendererComponent(table, value, isSelected, hasFocus, 0, col);
            if (c2 instanceof JLabel && c3 instanceof JLabel)
                ((JLabel)c2).setHorizontalAlignment(((JLabel)c3).getHorizontalAlignment());
        }
        return c2;
    }
    private final JTable dummy = new JTable();
});

The above code does not keep any references to renderers, so it avoids the NPE bug mentioned above. It does not require any named class, so you can just drop the code in wherever you need it.

夜光 2024-12-13 04:41:34
  ((DefaultTableCellRenderer)jTable2.getTableHeader().getDefaultRenderer())
    .setHorizontalAlignment(JLabel.CENTER);
  ((DefaultTableCellRenderer)jTable2.getTableHeader().getDefaultRenderer())
    .setHorizontalAlignment(JLabel.CENTER);
慕烟庭风 2024-12-13 04:41:34
((JLabel)mTabBOM.getTableHeader().getDefaultRenderer()).setHorizontalAlignment( JLabel.CENTER );
((JLabel)mTabBOM.getTableHeader().getDefaultRenderer()).setHorizontalAlignment( JLabel.CENTER );
迷你仙 2024-12-13 04:41:33

这是修改表的 JTableHeader。对于这种用法来说,这并不是绝对必要的,但它最大限度地减少了对 UI 委托外观的影响。

典型用法:

JTable table = new JTable(…);
JTableHeader header = table.getTableHeader();
header.setDefaultRenderer(new HeaderRenderer(table));

自定义标头渲染器:

private static class HeaderRenderer implements TableCellRenderer {

    DefaultTableCellRenderer renderer;

    public HeaderRenderer(JTable table) {
        renderer = (DefaultTableCellRenderer)
            table.getTableHeader().getDefaultRenderer();
        renderer.setHorizontalAlignment(JLabel.CENTER);
    }

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

Here's an alternate approach to modifying the TableCellRenderer of a table's JTableHeader. It's not strictly necessary for this usage, but it minimizes the impact on the UI delegate's appearance.

Typical usage:

JTable table = new JTable(…);
JTableHeader header = table.getTableHeader();
header.setDefaultRenderer(new HeaderRenderer(table));

Custom header renderer:

private static class HeaderRenderer implements TableCellRenderer {

    DefaultTableCellRenderer renderer;

    public HeaderRenderer(JTable table) {
        renderer = (DefaultTableCellRenderer)
            table.getTableHeader().getDefaultRenderer();
        renderer.setHorizontalAlignment(JLabel.CENTER);
    }

    @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);
    }
}
你怎么这么可爱啊 2024-12-13 04:41:33

试试这个:

((DefaultTableCellRenderer)table.getTableHeader().getDefaultRenderer())
    .setHorizontalAlignment(JLabel.RIGHT);

Try this:

((DefaultTableCellRenderer)table.getTableHeader().getDefaultRenderer())
    .setHorizontalAlignment(JLabel.RIGHT);
萧瑟寒风 2024-12-13 04:41:33
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) your_jtable.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(0);

其中 0 是中心。

DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) your_jtable.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(0);

Where 0 is Centre.

≈。彩虹 2024-12-13 04:41:33

上面显示的 HeaderRenderer(2011/sep/21,trashgod)与 Heisenbug (2011/sep/21) 的代码相结合,只有在所有标题对齐相同的情况下才能正常工作。

如果您想以不同的方式对齐不同的标题,那么您将必须使用以下代码:

int[] alignments = new int[] { JLabel.LEFT, JLabel.RIGHT, JLabel.RIGHT };
for (int i = 0 ; i < jTable.getColumnCount(); i++){
  jTable.getTableHeader().getColumnModel().getColumn(i)
    .setHeaderRenderer(new HeaderRenderer(jTable, alignments[i]));
}

private static class HeaderRenderer implements TableCellRenderer {
  DefaultTableCellRenderer renderer;
  int horAlignment;
  public HeaderRenderer(JTable table, int horizontalAlignment) {
    horAlignment = horizontalAlignment;
    renderer = (DefaultTableCellRenderer)table.getTableHeader()
        .getDefaultRenderer();
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int col) {
    Component c = renderer.getTableCellRendererComponent(table, value,
      isSelected, hasFocus, row, col);
    JLabel label = (JLabel)c;
    label.setHorizontalAlignment(horAlignment);
    return label;
  }
}


getTableCellRendererComponent 中设置对齐方式,而不是在 HeaderRenderer 构造函数中设置。

The HeaderRenderer shown above (2011/sep/21 by trashgod) combined with code from Heisenbug (2011/sep/21) , will only work correctly if you have all headers aligned the same.

If you want to align different headers differently, then you will have to use the following code:

int[] alignments = new int[] { JLabel.LEFT, JLabel.RIGHT, JLabel.RIGHT };
for (int i = 0 ; i < jTable.getColumnCount(); i++){
  jTable.getTableHeader().getColumnModel().getColumn(i)
    .setHeaderRenderer(new HeaderRenderer(jTable, alignments[i]));
}

and

private static class HeaderRenderer implements TableCellRenderer {
  DefaultTableCellRenderer renderer;
  int horAlignment;
  public HeaderRenderer(JTable table, int horizontalAlignment) {
    horAlignment = horizontalAlignment;
    renderer = (DefaultTableCellRenderer)table.getTableHeader()
        .getDefaultRenderer();
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int col) {
    Component c = renderer.getTableCellRendererComponent(table, value,
      isSelected, hasFocus, row, col);
    JLabel label = (JLabel)c;
    label.setHorizontalAlignment(horAlignment);
    return label;
  }
}

That is:
Set the alignment in getTableCellRendererComponent , and not in the HeaderRenderer constructor.

羅雙樹 2024-12-13 04:41:33

关于包装默认表头要记住的一件事:不要保留它们的引用。

如果您(或您的用户)在 Windows 7 和您的应用程序上使用 Windows 经典主题 设置默认系统 LAF答案发布者@trashgod 可能会给你带来问题。

它受到十年前发布的此错误的影响(严重) 。如果您的表格正在显示,并且您在 Windows 首选项中将主题从 Aero 主题切换到 Windows 经典,则会出现一系列 NPE。您不应该保留渲染器的引用,因为它可能在某个时间点变得无效。包装应该以动态方式完成,正如错误报告的评论中所建议的那样。我从那里获取了代码并创建了以下可运行的示例:

import java.awt.*;
import java.lang.ref.WeakReference;
import javax.swing.*;
import javax.swing.table.*;

public class TestFrame extends JFrame {

    private static final boolean I_WANT_THE_BUG_TO_HAPPEN = true;

    public static void main(String[] args) throws IllegalAccessException, ClassNotFoundException, InstantiationException, UnsupportedLookAndFeelException {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                int res = JOptionPane.showConfirmDialog(null, "Do you want to use the XP L&F?", "laffo", JOptionPane.YES_NO_OPTION);
                if (res == JOptionPane.YES_OPTION) {
                    try {
                        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
                    } catch (Exception ex) {
                    }
                }
                new TestFrame().setVisible(true);
            }

        });

    }

    public class MyModel extends AbstractTableModel {

        public int getRowCount() {
            return 10;
        }

        public int getColumnCount() {
            return 10;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            return "" + rowIndex + " X " + columnIndex;
        }

    }

    public class MyJTable extends JTable {

        /**
         *
         */
        private static final long serialVersionUID = -233098459210523146L;

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

        public void doSomething() {
            System.out.println("HEHE");
        }
    }

    public class MyAlternativeJTable extends JTable {

        private WeakReference<TableCellRenderer> wrappedHeaderRendererRef = null;
        private TableCellRenderer wrapperHeaderRenderer = null;

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

        private class MyAlternativeTableColumn extends TableColumn {

            MyAlternativeTableColumn(int modelIndex) {
                super(modelIndex);
            }

            @Override
            public TableCellRenderer getHeaderRenderer() {
                TableCellRenderer defaultHeaderRenderer
                        = MyAlternativeJTable.this.getTableHeader().getDefaultRenderer();
                if (wrappedHeaderRendererRef == null
                        || wrappedHeaderRendererRef.get() != defaultHeaderRenderer) {
                    wrappedHeaderRendererRef
                            = new WeakReference<TableCellRenderer>(defaultHeaderRenderer);
                    wrapperHeaderRenderer
                            = new DecoratedHeaderRenderer(defaultHeaderRenderer);
                }
                return wrapperHeaderRenderer;
            }
        }

        @Override
        public void createDefaultColumnsFromModel() {
            TableModel m = getModel();
            if (m != null) {
                // Remove any current columns
                TableColumnModel cm = getColumnModel();
                while (cm.getColumnCount() > 0) {
                    cm.removeColumn(cm.getColumn(0));
                }

                // Create new columns from the data model info
                for (int i = 0; i < m.getColumnCount(); i++) {
                    TableColumn newColumn = new MyAlternativeTableColumn(i);
                    addColumn(newColumn);
                }
            }
        }
    }

    private JPanel jContentPane = null;
    private JScrollPane jScrollPane = null;
    private JTable table1 = null;
    private JScrollPane jScrollPane1 = null;
    private JTable table2 = null;

    /**
     * This is the default constructor
     */
    public TestFrame() {
        super();
        initialize();
        int res = JOptionPane.showConfirmDialog(null, "Do you want to call updateUI() on the tables ?", "laffo", JOptionPane.YES_NO_OPTION);
        if (res == JOptionPane.YES_OPTION) {
            table2.updateUI();
            table1.updateUI();
        }
    }

    /**
     * This method initializes this
     *
     * @return void
     */
    private void initialize() {
        this.setSize(753, 658);
        this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        this.setContentPane(getJContentPane());
        this.setTitle("JFrame");
    }

    /**
     * This method initializes jContentPane
     *
     * @return javax.swing.JPanel
     */
    private JPanel getJContentPane() {
        if (jContentPane == null) {
            jContentPane = new JPanel();
            jContentPane.setLayout(null);
            jContentPane.add(getJScrollPane(), null);
            jContentPane.add(getJScrollPane1(), null);
        }
        return jContentPane;
    }

    /**
     * This method initializes jScrollPane
     *
     * @return javax.swing.JScrollPane
     */
    private JScrollPane getJScrollPane() {
        if (jScrollPane == null) {
            jScrollPane = new JScrollPane();
            jScrollPane.setBounds(new java.awt.Rectangle(358, 0, 387, 618));
            jScrollPane.setViewportView(getTable1());
        }
        return jScrollPane;
    }

    /**
     * This method initializes table1
     *
     * @return javax.swing.JTable
     */
    private JTable getTable1() {
        if (table1 == null) {
            table1 = new JTable(new MyModel());
        }
        return table1;
    }

    /**
     * This method initializes jScrollPane1
     *
     * @return javax.swing.JScrollPane
     */
    private JScrollPane getJScrollPane1() {
        if (jScrollPane1 == null) {
            jScrollPane1 = new JScrollPane();
            jScrollPane1.setBounds(new java.awt.Rectangle(0, 0, 350, 618));
            jScrollPane1.setViewportView(getTable2());
        }
        return jScrollPane1;
    }

    /**
     * This method initializes table2
     *
     * @return javax.swing.JTable
     */
    private JTable getTable2() {
        if (table2 == null) {
            if (I_WANT_THE_BUG_TO_HAPPEN) {
                table2 = new MyJTable(new MyModel());
                JTableHeader header = table2.getTableHeader();
                TableCellRenderer render = new DecoratedHeaderRenderer(header.getDefaultRenderer());
                header.setDefaultRenderer(render);
            } else {
                table2 = new MyAlternativeJTable(new MyModel());
            }
        }
        return table2;
    }

    private class DecoratedHeaderRenderer implements TableCellRenderer {

        public DecoratedHeaderRenderer(TableCellRenderer render) {
            this.render = render;
        }
        private TableCellRenderer render;

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            Component c = render.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            return c;
        }

    }

}

只需运行该示例并选择 Yes 两次,然后观察它的分解。然后将 I_WANT_THE_BUG_TO_HAPPEN 静态成员更改为 false 并重复。将此成员设置为 true 的情况与此处获得最多支持的答案本质上相同。此示例最重要的部分是扩展的 JTable (MyAlternativeJTable),它动态执行包装。

目前对该问题接受的答案已被广泛使用,但这是不明智的。您可以在丢失的应用程序(包括 Netbeans 8.0.2)(其本身基于 Java)的情况下重现它,同时它显示可排序的表,例如 Window > 。 IDE工具>具有讽刺意味的是,通知,您还可以在其中获得 NPE 报告。只需在 Windows 7 上将 Windows 主题从 Aero 切换到 Windows Classic(通过右键单击桌面 > 个性化 > 更改计算机上的视觉效果和声音)即可。

如果您使用 Glazed Lists 并调用 <一个href="https://svn.java.net/svn/glazedlists~svn/tags/glazedlists-1_9_0/www/api/ca/odell/glazedlists/swing/TableComparatorChooser. html#install(javax.swing.JTable,%20ca.odell.glazedlists.SortedList,%20java.lang.Object,%20ca.odell.glazedlists.gui.TableFormat)" rel="nofollow noreferrer">ca.odell.glazedlists.swing.TableComparatorChooser.install,您也会受到影响。它注入自己的自定义渲染器来对箭头进行排序。

我在尝试寻找 这个问题我怀疑是相关的。

A thing to remember about wrapping default table headers: do not hold on to a reference of them.

If you (or your users) are using a Windows Classic theme on Windows 7 and your application sets default system LAF, the answer posted by @trashgod may cause problems for you.

It is affected by this bug, posted a decade ago (seriously). If your table is showing and you switch the theme in Windows preferences from an Aero Theme to Windows Classic, there will be a barrage of NPEs. You are NOT supposed to hold on to a reference of a renderer as it may become invalid at some point in time. The wrapping should be done in a dynamic way, as suggested in the comments of the bug report. I took the code from there and created the following runnable example:

import java.awt.*;
import java.lang.ref.WeakReference;
import javax.swing.*;
import javax.swing.table.*;

public class TestFrame extends JFrame {

    private static final boolean I_WANT_THE_BUG_TO_HAPPEN = true;

    public static void main(String[] args) throws IllegalAccessException, ClassNotFoundException, InstantiationException, UnsupportedLookAndFeelException {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                int res = JOptionPane.showConfirmDialog(null, "Do you want to use the XP L&F?", "laffo", JOptionPane.YES_NO_OPTION);
                if (res == JOptionPane.YES_OPTION) {
                    try {
                        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
                    } catch (Exception ex) {
                    }
                }
                new TestFrame().setVisible(true);
            }

        });

    }

    public class MyModel extends AbstractTableModel {

        public int getRowCount() {
            return 10;
        }

        public int getColumnCount() {
            return 10;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            return "" + rowIndex + " X " + columnIndex;
        }

    }

    public class MyJTable extends JTable {

        /**
         *
         */
        private static final long serialVersionUID = -233098459210523146L;

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

        public void doSomething() {
            System.out.println("HEHE");
        }
    }

    public class MyAlternativeJTable extends JTable {

        private WeakReference<TableCellRenderer> wrappedHeaderRendererRef = null;
        private TableCellRenderer wrapperHeaderRenderer = null;

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

        private class MyAlternativeTableColumn extends TableColumn {

            MyAlternativeTableColumn(int modelIndex) {
                super(modelIndex);
            }

            @Override
            public TableCellRenderer getHeaderRenderer() {
                TableCellRenderer defaultHeaderRenderer
                        = MyAlternativeJTable.this.getTableHeader().getDefaultRenderer();
                if (wrappedHeaderRendererRef == null
                        || wrappedHeaderRendererRef.get() != defaultHeaderRenderer) {
                    wrappedHeaderRendererRef
                            = new WeakReference<TableCellRenderer>(defaultHeaderRenderer);
                    wrapperHeaderRenderer
                            = new DecoratedHeaderRenderer(defaultHeaderRenderer);
                }
                return wrapperHeaderRenderer;
            }
        }

        @Override
        public void createDefaultColumnsFromModel() {
            TableModel m = getModel();
            if (m != null) {
                // Remove any current columns
                TableColumnModel cm = getColumnModel();
                while (cm.getColumnCount() > 0) {
                    cm.removeColumn(cm.getColumn(0));
                }

                // Create new columns from the data model info
                for (int i = 0; i < m.getColumnCount(); i++) {
                    TableColumn newColumn = new MyAlternativeTableColumn(i);
                    addColumn(newColumn);
                }
            }
        }
    }

    private JPanel jContentPane = null;
    private JScrollPane jScrollPane = null;
    private JTable table1 = null;
    private JScrollPane jScrollPane1 = null;
    private JTable table2 = null;

    /**
     * This is the default constructor
     */
    public TestFrame() {
        super();
        initialize();
        int res = JOptionPane.showConfirmDialog(null, "Do you want to call updateUI() on the tables ?", "laffo", JOptionPane.YES_NO_OPTION);
        if (res == JOptionPane.YES_OPTION) {
            table2.updateUI();
            table1.updateUI();
        }
    }

    /**
     * This method initializes this
     *
     * @return void
     */
    private void initialize() {
        this.setSize(753, 658);
        this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        this.setContentPane(getJContentPane());
        this.setTitle("JFrame");
    }

    /**
     * This method initializes jContentPane
     *
     * @return javax.swing.JPanel
     */
    private JPanel getJContentPane() {
        if (jContentPane == null) {
            jContentPane = new JPanel();
            jContentPane.setLayout(null);
            jContentPane.add(getJScrollPane(), null);
            jContentPane.add(getJScrollPane1(), null);
        }
        return jContentPane;
    }

    /**
     * This method initializes jScrollPane
     *
     * @return javax.swing.JScrollPane
     */
    private JScrollPane getJScrollPane() {
        if (jScrollPane == null) {
            jScrollPane = new JScrollPane();
            jScrollPane.setBounds(new java.awt.Rectangle(358, 0, 387, 618));
            jScrollPane.setViewportView(getTable1());
        }
        return jScrollPane;
    }

    /**
     * This method initializes table1
     *
     * @return javax.swing.JTable
     */
    private JTable getTable1() {
        if (table1 == null) {
            table1 = new JTable(new MyModel());
        }
        return table1;
    }

    /**
     * This method initializes jScrollPane1
     *
     * @return javax.swing.JScrollPane
     */
    private JScrollPane getJScrollPane1() {
        if (jScrollPane1 == null) {
            jScrollPane1 = new JScrollPane();
            jScrollPane1.setBounds(new java.awt.Rectangle(0, 0, 350, 618));
            jScrollPane1.setViewportView(getTable2());
        }
        return jScrollPane1;
    }

    /**
     * This method initializes table2
     *
     * @return javax.swing.JTable
     */
    private JTable getTable2() {
        if (table2 == null) {
            if (I_WANT_THE_BUG_TO_HAPPEN) {
                table2 = new MyJTable(new MyModel());
                JTableHeader header = table2.getTableHeader();
                TableCellRenderer render = new DecoratedHeaderRenderer(header.getDefaultRenderer());
                header.setDefaultRenderer(render);
            } else {
                table2 = new MyAlternativeJTable(new MyModel());
            }
        }
        return table2;
    }

    private class DecoratedHeaderRenderer implements TableCellRenderer {

        public DecoratedHeaderRenderer(TableCellRenderer render) {
            this.render = render;
        }
        private TableCellRenderer render;

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            Component c = render.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            return c;
        }

    }

}

Simply run the example and choose Yes twice and watch it break apart. Then change the I_WANT_THE_BUG_TO_HAPPEN static member to false and repeat. The case with this member set to true is essentially the same as the most upvoted answer here. The most important part of this example is the extended JTable (MyAlternativeJTable) which does the wrapping dynamically.

The currently accepted answer to this question is widely used, but it is ill advised. You can reproduce it with lost of applications, including Netbeans 8.0.2 (which itself is Java based) while it is showing a sortable table, such as Window > IDE Tools > Notifications, where you'll also get the NPE reports, ironically. Just switch the Windows theme from Aero to Windows Classic (via right-click Desktop > Personalize > Change the visuals and sounds on your computer) on Windows 7.

If you are using Glazed Lists and call ca.odell.glazedlists.swing.TableComparatorChooser.install, you are also affected. It injects its own custom renderer for sorting arrows.

I stumbled upon this by coincidence while trying to find a solution for this question which I suspect is related.

奢华的一滴泪 2024-12-13 04:41:33
for (int i = 0 ; i < table.getColumnCount(); i++){

    DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
    renderer.setHorizontalAlignment(SwingConstants.RIGHT);
    table.getColumn(i).setHeaderRenderer(renderer);

}
for (int i = 0 ; i < table.getColumnCount(); i++){

    DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
    renderer.setHorizontalAlignment(SwingConstants.RIGHT);
    table.getColumn(i).setHeaderRenderer(renderer);

}
糖粟与秋泊 2024-12-13 04:41:33
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) 
MSISDNTable.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(JLabel.RIGHT);

其中 MSISDNTable 是您的表格

DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) 
MSISDNTable.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(JLabel.RIGHT);

where MSISDNTable is your table

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文