当前位置: 首页 > 知识库问答 >
问题:

JTable Row Header外观

厍华清
2023-03-14

我正在尝试为我的JTable创建行标题。我在这里和这里做过研究,但几乎什么都没有。我的发现并没有保持系统的外观。

到目前为止,我发现:

第一列(没有名字的那列)是我能做到的最好的一列。我使用了表头渲染器,并将其应用于行单元格。这在一定程度上起了作用。正如您所见,降序/升序排序的小箭头图标出现在列的每个单元格中,单元格现在为灰色。除此之外,这是一次彻底的失败。此外,我不希望我的行标题中有任何箭头图标。

Col 1是我尝试应用UIManager的外观时发生的情况。显然,它没有起作用。

Col 2是photoshop,这是我正在尝试做的。

我没有做任何其他2列,所以它的默认设置。

问题是:如何将系统(不仅仅是windows)默认表格标题的外观赋予行单元格,以便创建行标题,当然还有一个小箭头图标。

这是代码

import java.awt.Component;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import sun.swing.table.DefaultTableCellHeaderRenderer;

public class RowHeaderTest extends JFrame
{

    public RowHeaderTest()
    {
        initComponents();
    }

    private void initComponents()
    {
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        JScrollPane scrollPane = new JScrollPane();
        JTable table = new JTable();
        table.setAutoCreateRowSorter(true);
        table.getTableHeader().setReorderingAllowed(false);
        table.setModel(new 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"
                }));
        table.getColumnModel().getColumn(0).setHeaderRenderer(HeaderRenderer.THIS);
        table.getColumnModel().getColumn(0).setCellRenderer(HeaderRenderer.THIS);
        table.getColumnModel().getColumn(1).setHeaderRenderer(HeaderRendererUI.THIS);
        table.getColumnModel().getColumn(1).setCellRenderer(HeaderRendererUI.THIS);
        table.getColumnModel().getColumn(3).setHeaderRenderer(RowTableHeaderRendere.THIS);
        table.getColumnModel().getColumn(3).setCellRenderer(RowTableHeaderRendere.THIS);
        scrollPane.setViewportView(table);
        setSize(new Dimension(400, 200));
        setLocationRelativeTo(null);
        add(scrollPane);
    }

    public static void main(String args[])
    {
        try
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex)
        {
            java.util.logging.Logger.getLogger(RowHeaderTest.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        java.awt.EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                new RowHeaderTest().setVisible(true);
            }
        });
    }
}

final class HeaderRenderer extends DefaultTableCellHeaderRenderer
{

    public static final HeaderRenderer THIS = new HeaderRenderer();

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

final class HeaderRendererUI extends DefaultTableCellHeaderRenderer
{

    public static final HeaderRendererUI THIS = new HeaderRendererUI();

    @Override
    public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column)
    {
        setText(value.toString());
        //TableHeader.ancestorInputMap
        setBackground(isSelected ? UIManager.getColor("TableHeader.focusCellBackground") : UIManager.getColor("TableHeader.background"));
        setBorder(UIManager.getBorder("TableHeader.cellBorder"));
        setFont(UIManager.getFont("TableHeader.font"));
        setForeground(UIManager.getColor("TableHeader.foreground"));
        return this;
    }
}

final class RowTableHeaderRendere extends DefaultTableCellHeaderRenderer
{

    public static final RowTableHeaderRendere THIS = new RowTableHeaderRendere();

    @Override
    public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column)
    {
        JTable t = new JTable(new DefaultTableModel(
                null,
                new String[]
                {
                    value.toString()
                }));
        return t.getTableHeader();
    }
}

编辑

我只是在代码中添加了部分解决方案。Col 3现在看起来不错,但仍然缺乏感觉(它没有鼠标悬停),我不太确定创建一个新表来获取标题是最好的方法

共有1个答案

凌炜
2023-03-14

为了保持系统外观,您需要稍微更改渲染器。

首先,使用UIRessource扩展渲染器。您需要此标记界面来接收UI更改:

class HeaderRenderer extends DefaultTableCellHeaderRenderer 
                     implements javax.swing.plaf.UIResource {

然后从JTableHeader中获取并保存原始渲染器(例如,作为构造函数传递的field defRenderer)。在GetTableCellRenderer组件中,调用defRenderer。GetTableCellRenderComponent,修改并返回此JLabel。

private final TableCellRenderer defRenderer;

HeaderRenderer (TableCellRenderer defRenderer) {
  this.defRenderer = defRenderer;
}

@Override
public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected,
        boolean hasFocus, int row, int column) {
  Component c = defRenderer.getTableCellRendererComponent (...);
  if ( c instanceof JLabel ) {
    JLabel lbl = (JLabel)c;
    // do anything you want...
  }
  return c;
}

至少覆盖渲染器中的updateUI()方法,并将updateUI调用委托给defRenler:

@Override
public void updateUI() {
  TableCellRenderer locDefRenderer = defRenderer;
  if (locDefRenderer instanceof JComponent) {
    ((JComponent) locDefRenderer).updateUI();
  } else {
    super.updateUI();
  }
}

有了这张收据,就有可能改变很多东西。素色的油漆Component-渲染有点复杂;-)-对于自己的油漆使用JLayer(在Java7中介绍)

 类似资料:
  • 问题内容: 到目前为止,我有这个 我正在尝试使主外观看起来像雨云,但是将标题边框更改为Windows。 我的边界是这样的: 有可能吗?如果是的话,有人可以指出我在哪里看?我现在很困惑。:\ 谢谢。 问题答案: 我做完了 您必须创建UI的各个部分,然后调用UIManager.setLookAndFeel()来更改外观,然后创建其他部分。更像是骇客。

  • 主要内容:介绍,实现,Shape.java,Rectangle.java,Square.java,Circle.java,ShapeMaker.java,FacadePatternDemo.java外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。 这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。 介绍 意图:为子系统中的

  • 我正在我的一个项目中使用JTabbedPane,我正在尝试改变应用程序的外观。当我设置windows外观(以及任何其他外观)时,所有按钮、检查按钮等都将改变为它们应该的外观,但选项卡仍然看起来像默认的swing选项卡。下面是它的一个示例: 按钮和复选框看起来像windows组件,但选项卡看起来像默认的Swing。如果有用的话,我将使用JTabbedPane的一个子类,它在一个单独的类文件中定义。我

  • 关于外观属性 外观属性是一组在不改变对象基础结构的前提下影响对象外观的属性。外观属性包括填色、描边、透明度和效果。如果把一个外观属性应用于某对象而后又编辑或删除这个属性,该基本对象以及任何应用于该对象的其他属性都不会改变。 您可以在图层层次结构的任意层级设置外观属性。例如,如果您对一个图层应用投影效果,则该图层中的所有对象都将应用此投影效果。但是,如果您将其中的一个对象移出该图层,则此对象将不再具

  • 外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。 这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。 介绍 意图:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 主要

  • 简介 外观模式(Facade pattern),是软件工程中常用的一种软件设计模式,它为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用。 模式实现 某软件公司欲开发一个可应用于多个软件的文件加密模块,该模块可以对文件中的数据进行加密并将加密之后的数据存储在一个新文件中,具体的流程包括三个部分,分别是读取源文件、加密、保存加密之后的文件,其中,读取文件和保存文件使用流来实现,加密操作

  • 外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。 这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。 介绍 意图:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 主要

  • 正如我们早前在书中提过的, 没面模式为一个庞大的(可能更复杂的)代码结构提供了一个更简单的抽象接口。 门面在jQuery库中能够经常见到,它们为开发者处理DOM节点,动画或者令人特别感兴趣的跨域Ajax提供了简单的实现入口。 下面的代码是jQuery $.ajax()方法的门面: $.get( url, data, callback, dataType ); $.post( url, data,