Set JTable header 水平对齐基于值渲染器列对齐
Set JTable header horizontal alignment based on value renderer column alignment
我浏览了许多关于设置 JTable header 对齐方式的 questions/answers,但它们似乎没有涵盖这种情况。我希望我的 JTable headers 与它们下面的数据具有相同的对齐方式;让它们全部居中对我来说看起来很奇怪,特别是对于偶尔有长字符串但通常只包含短字符串的 space 的列 - header 在 [=45 的中心=] 本身。
我见过的许多解决方案都依赖于 DefaultCellTableRenderer——是否所有 table header 都在使用?我不想设置 default 渲染器,因为那会改变 all 列;我想编写代码来确定列中数据的水平对齐方式,并设置 header 以在水平对齐方面做同样的事情。
我是否必须从渲染器获取组件(使用特定的行、列和值)并在组件上设置对齐方式?我是否必须为此为 header 编写自定义渲染器?最干净的整体方法是什么?
-- 编辑
先生Camick 的解决方案很优雅,几乎可以满足我的要求;它拦截了为列 header 创建 table 单元格渲染器的过程。我所做的不知何故消除了 header 的正常格式,但是 - 我的 header 没有阴影和边框(尽管它们按我想要的方式对齐!)。
我目前有以下内容:我从哪里获得 table header 的渲染器,这样我就可以改变它的对齐方式?
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class TableHeaderRenderer implements TableCellRenderer
{
TableCellRenderer olderRenderer = null;
public TableHeaderRenderer(TableCellRenderer givenRenderer)
{
olderRenderer = givenRenderer;
}
// // get the default renderer for the table header.
// JTableHeader header = table.getTableHeader();
// TableCellRenderer defaultRenderer = header.getDefaultRenderer();
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column)
{
try // if the casts fail, we end up in the catch below
{
// get the renderer for the first row
DefaultTableCellRenderer firstRowTableCellRenderer = (DefaultTableCellRenderer)table.getCellRenderer(0, column);
// get the renderer for this column header
JTableHeader tableHeader = table.getTableHeader();
TableColumnModel columnModel = tableHeader.getColumnModel();
TableColumn tableColumn = columnModel.getColumn(column);
DefaultTableCellRenderer headerRenderer = (DefaultTableCellRenderer)tableColumn.getCellRenderer();
// if the renderer for the column is null, create one
if (headerRenderer == null)
{ headerRenderer = new DefaultTableCellRenderer();
}
// finally -- set the header's horizontal alignment to be the same as
// that for the first row, then get the component
headerRenderer.setHorizontalAlignment(firstRowTableCellRenderer.getHorizontalAlignment());
Component result = headerRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
return result;
}
catch (ClassCastException cce)
{
// either the first row or the header has a renderer that isn't a DefaultTableCellRenderer
// just return the component we already have
return olderRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
}
--
好的,编辑 2:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
@SuppressWarnings("serial")
public class TableHeaderRendererDemo extends JFrame
{
Object[][]data = { {new Integer(1), "two", "three"},
{ new Integer(4), "five", "six" }
};
Object[] columnNames = { "first", "second", "third" };
public static void main(String ... arguments)
{ new TableHeaderRendererDemo().go();
}
public void go()
{
JTable table = new JTable(data, columnNames);
JScrollPane scrollPane = new JScrollPane(table);
// set our own default renderer for the headers
JTableHeader header = table.getTableHeader();
try
{ DefaultTableCellRenderer defaultRenderer = (DefaultTableCellRenderer)header.getDefaultRenderer();
header.setDefaultRenderer(new TableHeaderRenderer(defaultRenderer));
}
catch (ClassCastException e)
{
System.err.println("Could not cast default renderer; table headers not aligned");
}
add(scrollPane, BorderLayout.CENTER);
pack();
setVisible(true);
}
}
你可以看到我说的header问题;我希望整数会默认为 right-justified,但由于某些原因它们不会。但是你可以从这里看到我遇到的问题。
这是一个自定义 header 呈现器的示例,它只是将所选列的文本加粗:
class MyTableHeaderRenderer implements TableCellRenderer
{
private TableCellRenderer tableCellRenderer;
public MyTableHeaderRenderer(TableCellRenderer tableCellRenderer)
{
this.tableCellRenderer = tableCellRenderer;
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column)
{
Component c = tableCellRenderer.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, column);
if (column == table.getSelectedColumn())
c.setFont(getFont().deriveFont(Font.BOLD));
return c;
}
}
您可以将渲染器与如下代码一起使用:
JTableHeader header = table.getTableHeader();
DefaultTableCellRenderer defaultRenderer = (DefaultTableCellRenderer)header.getDefaultRenderer();
header.setDefaultRenderer( new MyTableHeaderRenderer(defaultRenderer) );
在您的情况下,您需要更改对齐方式,而不是字体。
您可以使用如下代码:
TableCellRenderer tcr = table.getCellRenderer(0, column);
Component renderer = table.prepareRenderer(tcr, 0, column);
defaultRenderer.setAlignment( renderer.getAlignment() ); // whatever the alignment method is.
编辑:
Somehow what I've done eliminates the normal formatting for a header
您正在使用:
tableColumn.getCellRenderer();
不应该是:
tableColumn.getHeaderRenderer();
很少有人会按列为 table header 指定特殊的渲染器。因此,如果未为 TableColumn 指定 header 渲染器,您应该只使用 JTableHeader 的默认渲染器,不要创建 DefaultTableCellRenderer,这不是 table [=34= 使用的渲染器].
纠结到我终于想到了这个;不知何故,布尔值的默认渲染器不是 DefaultTableCellRenderer,所以我无法通过这种方式获得它的对齐方式。我尝试将组件放在第一行并进行 ITS 对齐,但如果 table 中没有数据,那将失败。这对我现在想要的已经足够好了。在我看来,列的对齐必须存在于某个地方,我仍然希望我能以某种方式获取它的值,但到目前为止,我所管理的只是一种在列数据使用 DefaultTableCellRenderer 时获取它的方法。
感谢 camickr 和 MadProgrammer 先生。
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
/**
* Renderer that aligns the table's column header with the column's data;
* if the renderer for the first row of the column data cannot be cast to
* DefaultTableCellRenderer, this just sets the alignment to CENTER.
* <P>Use:
* <pre>
* // set our own default renderer for the headers
JTableHeader header = table.getTableHeader();
try
{ DefaultTableCellRenderer defaultRenderer = (DefaultTableCellRenderer)header.getDefaultRenderer();
header.setDefaultRenderer(new TableHeaderRenderer(defaultRenderer));
}
catch (ClassCastException e)
{
System.err.println("Could not cast default renderer; table headers not aligned");
}
*
*/
@SuppressWarnings("serial")
public class TableHeaderRenderer extends DefaultTableCellRenderer implements TableCellRenderer
{
DefaultTableCellRenderer innerRenderer = null;
public TableHeaderRenderer(TableCellRenderer givenRenderer)
{
// save the given renderer, normally the default for the header
innerRenderer = (DefaultTableCellRenderer)givenRenderer;
}
@Override
public Component getTableCellRendererComponent
(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
try
{
// get the renderer for the first row
DefaultTableCellRenderer firstRowTableCellRenderer = (DefaultTableCellRenderer)table.getCellRenderer(0, column);
int firstRowAlignment = firstRowTableCellRenderer.getHorizontalAlignment();
// set the alignment of this header to that of the first row
innerRenderer.setHorizontalAlignment(firstRowAlignment);
return innerRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, firstRowAlignment, column);
}
catch (ClassCastException cce)
{
// the first row has a renderer that isn't a DefaultTableCellRenderer
// just set the alignment to CENTER
innerRenderer.setHorizontalAlignment(SwingConstants.CENTER);
return innerRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
}
我浏览了许多关于设置 JTable header 对齐方式的 questions/answers,但它们似乎没有涵盖这种情况。我希望我的 JTable headers 与它们下面的数据具有相同的对齐方式;让它们全部居中对我来说看起来很奇怪,特别是对于偶尔有长字符串但通常只包含短字符串的 space 的列 - header 在 [=45 的中心=] 本身。
我见过的许多解决方案都依赖于 DefaultCellTableRenderer——是否所有 table header 都在使用?我不想设置 default 渲染器,因为那会改变 all 列;我想编写代码来确定列中数据的水平对齐方式,并设置 header 以在水平对齐方面做同样的事情。
我是否必须从渲染器获取组件(使用特定的行、列和值)并在组件上设置对齐方式?我是否必须为此为 header 编写自定义渲染器?最干净的整体方法是什么?
-- 编辑
先生Camick 的解决方案很优雅,几乎可以满足我的要求;它拦截了为列 header 创建 table 单元格渲染器的过程。我所做的不知何故消除了 header 的正常格式,但是 - 我的 header 没有阴影和边框(尽管它们按我想要的方式对齐!)。
我目前有以下内容:我从哪里获得 table header 的渲染器,这样我就可以改变它的对齐方式?
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class TableHeaderRenderer implements TableCellRenderer
{
TableCellRenderer olderRenderer = null;
public TableHeaderRenderer(TableCellRenderer givenRenderer)
{
olderRenderer = givenRenderer;
}
// // get the default renderer for the table header.
// JTableHeader header = table.getTableHeader();
// TableCellRenderer defaultRenderer = header.getDefaultRenderer();
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column)
{
try // if the casts fail, we end up in the catch below
{
// get the renderer for the first row
DefaultTableCellRenderer firstRowTableCellRenderer = (DefaultTableCellRenderer)table.getCellRenderer(0, column);
// get the renderer for this column header
JTableHeader tableHeader = table.getTableHeader();
TableColumnModel columnModel = tableHeader.getColumnModel();
TableColumn tableColumn = columnModel.getColumn(column);
DefaultTableCellRenderer headerRenderer = (DefaultTableCellRenderer)tableColumn.getCellRenderer();
// if the renderer for the column is null, create one
if (headerRenderer == null)
{ headerRenderer = new DefaultTableCellRenderer();
}
// finally -- set the header's horizontal alignment to be the same as
// that for the first row, then get the component
headerRenderer.setHorizontalAlignment(firstRowTableCellRenderer.getHorizontalAlignment());
Component result = headerRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
return result;
}
catch (ClassCastException cce)
{
// either the first row or the header has a renderer that isn't a DefaultTableCellRenderer
// just return the component we already have
return olderRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
}
--
好的,编辑 2:
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
@SuppressWarnings("serial")
public class TableHeaderRendererDemo extends JFrame
{
Object[][]data = { {new Integer(1), "two", "three"},
{ new Integer(4), "five", "six" }
};
Object[] columnNames = { "first", "second", "third" };
public static void main(String ... arguments)
{ new TableHeaderRendererDemo().go();
}
public void go()
{
JTable table = new JTable(data, columnNames);
JScrollPane scrollPane = new JScrollPane(table);
// set our own default renderer for the headers
JTableHeader header = table.getTableHeader();
try
{ DefaultTableCellRenderer defaultRenderer = (DefaultTableCellRenderer)header.getDefaultRenderer();
header.setDefaultRenderer(new TableHeaderRenderer(defaultRenderer));
}
catch (ClassCastException e)
{
System.err.println("Could not cast default renderer; table headers not aligned");
}
add(scrollPane, BorderLayout.CENTER);
pack();
setVisible(true);
}
}
你可以看到我说的header问题;我希望整数会默认为 right-justified,但由于某些原因它们不会。但是你可以从这里看到我遇到的问题。
这是一个自定义 header 呈现器的示例,它只是将所选列的文本加粗:
class MyTableHeaderRenderer implements TableCellRenderer
{
private TableCellRenderer tableCellRenderer;
public MyTableHeaderRenderer(TableCellRenderer tableCellRenderer)
{
this.tableCellRenderer = tableCellRenderer;
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column)
{
Component c = tableCellRenderer.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, column);
if (column == table.getSelectedColumn())
c.setFont(getFont().deriveFont(Font.BOLD));
return c;
}
}
您可以将渲染器与如下代码一起使用:
JTableHeader header = table.getTableHeader();
DefaultTableCellRenderer defaultRenderer = (DefaultTableCellRenderer)header.getDefaultRenderer();
header.setDefaultRenderer( new MyTableHeaderRenderer(defaultRenderer) );
在您的情况下,您需要更改对齐方式,而不是字体。
您可以使用如下代码:
TableCellRenderer tcr = table.getCellRenderer(0, column);
Component renderer = table.prepareRenderer(tcr, 0, column);
defaultRenderer.setAlignment( renderer.getAlignment() ); // whatever the alignment method is.
编辑:
Somehow what I've done eliminates the normal formatting for a header
您正在使用:
tableColumn.getCellRenderer();
不应该是:
tableColumn.getHeaderRenderer();
很少有人会按列为 table header 指定特殊的渲染器。因此,如果未为 TableColumn 指定 header 渲染器,您应该只使用 JTableHeader 的默认渲染器,不要创建 DefaultTableCellRenderer,这不是 table [=34= 使用的渲染器].
纠结到我终于想到了这个;不知何故,布尔值的默认渲染器不是 DefaultTableCellRenderer,所以我无法通过这种方式获得它的对齐方式。我尝试将组件放在第一行并进行 ITS 对齐,但如果 table 中没有数据,那将失败。这对我现在想要的已经足够好了。在我看来,列的对齐必须存在于某个地方,我仍然希望我能以某种方式获取它的值,但到目前为止,我所管理的只是一种在列数据使用 DefaultTableCellRenderer 时获取它的方法。
感谢 camickr 和 MadProgrammer 先生。
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
/**
* Renderer that aligns the table's column header with the column's data;
* if the renderer for the first row of the column data cannot be cast to
* DefaultTableCellRenderer, this just sets the alignment to CENTER.
* <P>Use:
* <pre>
* // set our own default renderer for the headers
JTableHeader header = table.getTableHeader();
try
{ DefaultTableCellRenderer defaultRenderer = (DefaultTableCellRenderer)header.getDefaultRenderer();
header.setDefaultRenderer(new TableHeaderRenderer(defaultRenderer));
}
catch (ClassCastException e)
{
System.err.println("Could not cast default renderer; table headers not aligned");
}
*
*/
@SuppressWarnings("serial")
public class TableHeaderRenderer extends DefaultTableCellRenderer implements TableCellRenderer
{
DefaultTableCellRenderer innerRenderer = null;
public TableHeaderRenderer(TableCellRenderer givenRenderer)
{
// save the given renderer, normally the default for the header
innerRenderer = (DefaultTableCellRenderer)givenRenderer;
}
@Override
public Component getTableCellRendererComponent
(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
try
{
// get the renderer for the first row
DefaultTableCellRenderer firstRowTableCellRenderer = (DefaultTableCellRenderer)table.getCellRenderer(0, column);
int firstRowAlignment = firstRowTableCellRenderer.getHorizontalAlignment();
// set the alignment of this header to that of the first row
innerRenderer.setHorizontalAlignment(firstRowAlignment);
return innerRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, firstRowAlignment, column);
}
catch (ClassCastException cce)
{
// the first row has a renderer that isn't a DefaultTableCellRenderer
// just set the alignment to CENTER
innerRenderer.setHorizontalAlignment(SwingConstants.CENTER);
return innerRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
}