突出显示 JTable 的列标题

2023-11-23

我目前正在构建一个小 JTable,并且希望在选择单元格时突出显示列标题(和行标题 - 行标题部分实际上正在工作),以便更轻松地找到与该单元格相关的名称。这是一张图片:

enter image description here

我已经尝试用以下方法切换标题的渲染器:

table.getTableHeader().setDefaultRenderer(new ColumnHeaderRenderer());

但只有当我单击标题时才会调用它,并且总是说 isSelected 为 false。

这是我用于行名称的代码,包括渲染器内的突出显示 - 代码不是我编写的,我只是对其进行了一些修改:

/*
 *  Use a JTable as a renderer for row numbers of a given main table.
 *  This table must be added to the row header of the scrollpane that
 *  contains the main table.
 */
public class RowNameTable extends JTable
        implements ChangeListener, PropertyChangeListener {

    private JTable main;

    public RowNameTable(JTable table) {
        main = table;
        main.addPropertyChangeListener(this);

        setFocusable(false);
        setAutoCreateColumnsFromModel(false);
        setModel(main.getModel());
        setSelectionModel(main.getSelectionModel());

        TableColumn column = new TableColumn();
        column.setHeaderValue(" ");
        addColumn(column);
        column.setCellRenderer(new RowNameRenderer(main));

        getColumnModel().getColumn(0).setPreferredWidth(table.getColumnModel().getColumn(0).getPreferredWidth());
        setPreferredScrollableViewportSize(getPreferredSize());
    }

    @Override
    public void addNotify() {
        super.addNotify();

        Component c = getParent();

        //  Keep scrolling of the row table in sync with the main table.

        if (c instanceof JViewport) {
            JViewport viewport = (JViewport) c;
            viewport.addChangeListener(this);
        }
    }

    /*
     *  Delegate method to main table
     */
    @Override
    public int getRowCount() {
        return main.getRowCount();
    }

    @Override
    public int getRowHeight(int row) {
        return main.getRowHeight(row);
    }

    /*
     *  This table does not use any data from the main TableModel,
     *  so just return a value based on the row parameter.
     */
    @Override
    public Object getValueAt(int row, int column) {
        return Integer.toString(row + 1);
    }

    /*
     *  Don't edit data in the main TableModel by mistake
     */
    @Override
    public boolean isCellEditable(int row, int column) {
        return false;
    }
//
//  Implement the ChangeListener
//

    public void stateChanged(ChangeEvent e) {
        //  Keep the scrolling of the row table in sync with main table

        JViewport viewport = (JViewport) e.getSource();
        JScrollPane scrollPane = (JScrollPane) viewport.getParent();
        scrollPane.getVerticalScrollBar().setValue(viewport.getViewPosition().y);
    }
//
//  Implement the PropertyChangeListener
//

    public void propertyChange(PropertyChangeEvent e) {
        //  Keep the row table in sync with the main table

        if ("selectionModel".equals(e.getPropertyName())) {
            setSelectionModel(main.getSelectionModel());
        }

        if ("model".equals(e.getPropertyName())) {
            setModel(main.getModel());
        }
    }

    /*
     *  Borrow the renderer from JDK1.4.2 table header
     */
    private static class RowNameRenderer extends DefaultTableCellRenderer {

        private JTable main;

        public RowNameRenderer(JTable main) {
            this.main = main;
            setHorizontalAlignment(JLabel.CENTER);
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            if (table != null) {
                JTableHeader header = table.getTableHeader();

                if (header != null) {
                    setForeground(header.getForeground());
                    setBackground(header.getBackground());
                    setFont(header.getFont());
                }
            }

            if (isSelected) {
                setFont(getFont().deriveFont(Font.BOLD));
            }

            setText((value == null) ? "" : main.getColumnName(row));
            setBorder(UIManager.getBorder("TableHeader.cellBorder"));

            return this;
        }
    }
}

这里我们有创建表的相关部分:

    costTableModel = new CostTableModel(costCalc);
    table = new JTable(costTableModel);
    table.setPreferredScrollableViewportSize(table.getPreferredSize());
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    table.setCellSelectionEnabled(true);

    scrollPane = new JScrollPane(table);

    RowNameTable nameTable = new RowNameTable(table);
    scrollPane.setRowHeaderView(nameTable);

还有 costTableModel 类,只是为了完整性:

public class CostTableModel extends AbstractTableModel {
    private CostCalculator costCalc;

    public CostTableModel(CostCalculator costCalc) {
        this.costCalc = costCalc;
    }

    @Override
    public int getRowCount() {
        return costCalc.getPersonsList().size();
    }

    @Override
    public int getColumnCount() {
        return costCalc.getPersonsList().size();
    }

    @Override
    public String getColumnName(int col) {
        return costCalc.getPersonsList().get(col).getName();
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Person debtor = costCalc.getPersonsList().get(rowIndex);
        Person debtee = costCalc.getPersonsList().get(columnIndex);

        return costCalc.getAmountOwed(debtor, debtee);
    }

    @Override
    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();

    }
}

提前谢谢你的帮助!


一个细微的变化:当我阅读问题时,主要问题是标题没有更新column选择改变。有一个自定义标头监听row选择更改对于这种情况没有多大帮助。

事实上,JTableHeader 已经is监听 Co​​lumnModel 和模型的更改通知包括选择更改。只是故意实现了 columnSelectionChange 方法而不执行任何操作:

// --Redrawing the header is slow in cell selection mode.
// --Since header selection is ugly and it is always clear from the
// --view which columns are selected, don't redraw the header.

自定义标头可以简单地实现重新绘制(这里懒惰的我在表的工厂方法中这样做只是为了省去与表的连接,您可以轻松地将其设为独立的类:-)。

final JTable table = new JTable(new AncientSwingTeam()) {

    @Override
    protected JTableHeader createDefaultTableHeader() {
        // subclassing to take advantage of super's auto-wiring
        // as ColumnModelListener
        JTableHeader header = new JTableHeader(getColumnModel()) {

            @Override
            public void columnSelectionChanged(ListSelectionEvent e) {
                repaint();
            }

        };
        return header;
    }

};
table.setCellSelectionEnabled(true);
table.getTableHeader().setDefaultRenderer(new ColumnHeaderRenderer());

还使用 table api 对 Mad 的渲染器进行了一些调整:

/**
 * Slightly adjusted compared to @Mad
 * - use table's selectionBackground
 * - use table's isColumnSelected to decide on highlight
 */
public static class ColumnHeaderRenderer extends DefaultTableCellHeaderRenderer {

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean selected,  
        boolean focused, int row, int column) {
        super.getTableCellRendererComponent(table, value, selected, focused, row, column); 
        if (table.isColumnSelected(column)) {
            setBackground(table.getSelectionBackground());
        }
        return this;
    }
}

至于观察:

总是说 isSelected 为 false

原因是 BasicTableHeaderUI 中的一个小怪癖:

ui.selected != columnModel.selected

uiSelected 是键绑定可以访问的列 - 如果 laf 支持它并且标题是 focusOwner。对我来说确实没有意义,但是完全定义 ui 和 columnModel 选择的语义陷入了对新 babe fx 的兴奋之中,这被遗忘了;-)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

突出显示 JTable 的列标题 的相关文章

  • Eclipse 在源代码管理中保存操作

    我们希望找到一种在签入之前执行代码标准的 轻量级 方法 我们真的很喜欢使用 Eclipse 内置的想法保存操作 go to Preferences gt gt Java gt gt Editor gt gt Save Actions 其中有
  • 如何在android上的python kivy中关闭应用程序后使服务继续工作

    我希望我的服务在关闭应用程序后继续工作 但我做不到 我听说我应该使用startForeground 但如何在Python中做到这一点呢 应用程序代码 from kivy app import App from kivy uix floatl
  • 这个函数(for循环)空间复杂度是O(1)还是O(n)?

    public void check 10 for string i list Integer a hashtable get i if a gt 10 hashtable remove i 这是 O 1 还是 O n 我猜测 O n 但不是
  • OpenCV 中的 Gabor 内核参数

    我必须在我的应用程序中使用 Gabor 过滤器 但我不知道这个 OpenCV 方法参数值 我想对虹膜进行编码 启动 Gabor 过滤器并获取特征 我想对 12 组 Gabor 参数值执行此操作 然后我想计算 Hamming Dystans
  • OSGi:如果不取消服务会发生什么

    这是我获取 OSGi 服务的方式 ServiceReference reference bundleContext getServiceReference Foo class getName Foo foo Foo bundleContex
  • java中如何连接字符串

    这是我的字符串连接代码 StringSecret java public class StringSecret public static void main String args String s new String abc s co
  • JavaFX 中具有自定义内容的 ListView

    How i can make custom ListView with JavaFx for my app I need HBox with image and 2 Labels for each line listView 您可以通过查看
  • 如何在不超过最大值的情况下增加变量?

    我正在为学校开发一个简单的视频游戏程序 我创建了一个方法 如果调用该方法 玩家将获得 15 点生命值 我必须将生命值保持在最大值 100 并且由于我目前的编程能力有限 我正在做这样的事情 public void getHealed if h
  • 匿名类上的 NotSerializedException

    我有一个用于过滤项目的界面 public interface KeyValFilter extends Serializable public static final long serialVersionUID 7069537470113
  • Calendar.getInstance(TimeZone.getTimeZone("UTC")) 不返回 UTC 时间

    我对得到的结果真的很困惑Calendar getInstance TimeZone getTimeZone UTC 方法调用 它返回 IST 时间 这是我使用的代码 Calendar cal Two Calendar getInstance
  • 普罗米修斯指标 - 未找到

    我有 Spring Boot 应用程序 并且正在使用 vertx 我想监控服务和 jvm 为此我选择了 Prometheus 这是我的监控配置类 Configuration public class MonitoringConfig Bea
  • 以编程方式在java的resources/source文件夹中创建文件?

    我有两个资源文件夹 src 这是我的 java 文件 资源 这是我的资源文件 图像 properties 组织在文件夹 包 中 有没有办法以编程方式在该资源文件夹中添加另一个 properties 文件 我尝试过这样的事情 public s
  • 如何在 Java 中测试一个类是否正确实现了 Serialized(不仅仅是 Serialized 的实例)

    我正在实现一个可序列化的类 因此它是一个与 RMI 一起使用的值对象 但我需要测试一下 有没有办法轻松做到这一点 澄清 我正在实现该类 因此在类定义中添加 Serialized 很简单 我需要手动序列化 反序列化它以查看它是否有效 我找到了
  • Javafx过滤表视图

    我正在尝试使用文本字段来过滤表视图 我想要一个文本字段 txtSearch 来搜索 nhs 号码 名字 姓氏 和 分类类别 我尝试过在线实施各种解决方案 但没有运气 我对这一切仍然很陌生 所以如果问得不好 我深表歉意 任何帮助将不胜感激 我
  • 有没有一种快速方法可以从 Jar/war 中删除文件,而无需提取 jar 并重新创建它?

    所以我需要从 jar war 文件中删除一个文件 我希望有类似 jar d myjar jar file I donot need txt 的内容 但现在我能看到从 Linux 命令行执行此操作的唯一方法 不使用 WinRAR Winzip
  • 游戏内的java.awt.Robot?

    我正在尝试使用下面的代码来模拟击键 当我打开记事本时 它工作正常 但当我打开我想使用它的游戏时 它没有执行任何操作 所以按键似乎不起作用 我尝试模拟鼠标移动和点击 这些动作确实有效 有谁知道如何解决这个问题 我发现这个问题 如何在游戏中使用
  • 具有特定参数的 Spring AOP 切入点

    我需要创建一个我觉得很难描述的方面 所以让我指出一下想法 com x y 包 或任何子包 中的任何方法 一个方法参数是接口 javax portlet PortletRequest 的实现 该方法中可能有更多参数 它们可以是任何顺序 我需要
  • FileOutputStream.close() 中的设备 ioctl 不合适

    我有一些代码可以使用以下命令将一些首选项保存到文件中FileOutputStream 这是我已经写了一千遍的标准代码 FileOutputStream out new FileOutputStream file try BufferedOu
  • hashcode 的默认实现为以相同方式构造的对象返回不同的值

    我在这里编写一个示例代码 public class Test private int i private int j public Test TODO Auto generated constructor stub public Test
  • 在 RESTful Web 服务中实现注销

    我正在开发一个需要注销服务的移动应用程序 登录服务是通过数据库验证来完成的 现在我陷入了注销状态 退一步 您没有提供有关如何在应用程序中执行身份验证的详细信息 并且很难猜测您在做什么 但是 需要注意的是 在 REST 应用程序中 不能有会话

随机推荐

  • 多个客户端同时访问服务器

    我有一个登录屏幕 现在说我们有 2 个用户 用户名 amit 和 ajay 密码 pass 和 word 现在我希望假设他们是在同一系统上打开的两个桌面应用程序 我想要多个客户端同时访问服务器 意思是说 在一个登录屏幕中 amit 输入用户
  • Javascript 检测用户何时保存网页?

    JavaScript 可以检测用户何时将网页保存到本地磁盘吗 或者其他一些客户端脚本中是否有类似的功能 您可以观看组合键命令ctrl s被击中 但如果用户通过菜单选择保存 则无法捕获该信息
  • 安卓 SIP SSL

    我在 Android 2 3 4 中使用 SIP 堆栈 一切运行良好 但是 我需要系统使用 SSL 并创建了以下代码 SipProfile Builder builder new SipProfile Builder user domain
  • Android 只允许一次在屏幕上显示一个导航页面,使用

    下面2个实现有什么区别 public App The root page of your application MainPage new Views MainPage public App MainPage new NavigationP
  • 甜甜圈缓存是否可以与 ASP.NET MVC 一起正常工作?

    通过甜甜圈缓存 我指的是斯科特 格思里的博客文章这太棒了 有谁知道这是否正常 请注意 从 MVC 2 0 开始 此技术不再有效 这很糟糕
  • Sql HierarchyId 如何获取最后的后代?

    Using t sql 等级制度我如何获得所有没有子项的行 即最后的后代 假设我的表结构如下 Id Name HierarchyId 并且有这些行 1 Craig 2 Steve 1 3 John 1 1 4 Sam 2 5 Matt 2
  • 如何在 woocommerce 中添加自定义运费?

    我想使用 woocommerce 中的代码添加运费 这是我的要求 如果我的发货国家 地区是澳大利亚 则运费会有所不同 澳大利亚境外的运费也会有所不同 现在 如果我的发货国家 地区是澳大利亚并且 1 if order value is lt
  • Dynamic_cast 返回 NULL 但它不应该返回

    我有以下类层次结构 class IStorage Q DECLARE INTERFACE IStorage ch gorrion smssender IStorage 1 0 class ISQLiteStorage public ISto
  • 如何在Xcode中替换模板标题中的公司名称?

    当 Xcode 创建一个新文件时 文件头中总是有这样的内容 Copyright 2009 MyCompanyName All rights reserved 我怎样才能改变这一点 You can change it in Xcode pro
  • 如何在 sql 中使用的 linq 中使用 Left join?

    如何在编写 SQL 查询的 Linq 中使用 Left join select p Name p Family E EmployTypecode E employtypeName E EmplytyppeTye from personnel
  • 设置连续数字的格式

    我正在尝试使用 Python 格式化整数列表 但在实现我想要的效果时遇到了一些困难 输入是整数的排序列表 list 1 2 3 6 8 9 我希望输出是一个如下所示的字符串 outputString 1 3 6 8 9 到目前为止 我所实现
  • Class.forName 似乎仍然有必要

    来自Java 文档 在以前版本的 JDBC 中 要获取连接 您首先必须通过调用 Class forName 方法来初始化 JDBC 驱动程序 在类路径中找到的任何 JDBC 4 0 驱动程序都会自动加载 但是 您必须使用 Class for
  • 在 JavaScript(特别是 NativeScript)中添加全局变量/函数

    我正在学习如何使用 NativeScript 编写应用程序 我相信最好的学习方式就是实践 因此 我正在构建一个基本的应用程序 在此应用程序中 我尝试创建一个可以跨应用程序中的所有视图模型和其他代码访问的函数和变量 为了尝试做到这一点 我想我
  • 在 Mongoose 的 forEach 循环中添加属性

    假设我的 posts 数组中的每个帖子都有两个属性 name 和 number 所以它就像 var posts name hey number 1 name foo number 2 Javascript 允许我在 foreach 循环中更
  • 网络 - 绑定到本地主机

    我有一个关于绑定和连接的一般性问题localhost 我正在使用 TCP 客户端 服务器 在服务器端我执行以下形式的操作 bind localhost 9999 listen 这是在一个名称为例如 的 UNIX 主机上完成的 host1 现
  • 为什么 sp_columns 不返回结果?

    我试图为 StackOverflow 上的另一篇文章 描述 一个表 但是当我运行 sp columns 时 没有显示任何结果或行 sp columns assignee Results A bunch of column headers 我
  • Python - 根据总和对列表进行排序

    我想根据每个内部列表的总和对包含列表的列表进行排序 这是我当前的片段 vectors for i in range 0 10 vectors append generate vector generate vector works crea
  • 当您需要存储(非常)大的数字时该怎么办?

    我正在尝试做一个欧拉计划问题 但它涉及将一个非常大的数字相加 100 使用Java int和long太小了 感谢您的任何建议 Class 大整数看起来这可能就是您正在寻找的
  • 根据 Javascript 中的字符串输入生成唯一编号

    过去我制作了一个函数 可以从字符串生成唯一的 id 数字 今天我发现它并不像应有的那么独特 以前从未见过问题 如今 两个不同的输入会生成相同的 id 数字 我在 Delphi C PHP 和 Javascript 中使用相同的技术来生成相同
  • 突出显示 JTable 的列标题

    我目前正在构建一个小 JTable 并且希望在选择单元格时突出显示列标题 和行标题 行标题部分实际上正在工作 以便更轻松地找到与该单元格相关的名称 这是一张图片 我已经尝试用以下方法切换标题的渲染器 table getTableHeader