草庐IT

java - 突出显示 JTable 的列标题

coder 2024-03-27 原文

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

我已经尝试用这个关闭标题的渲染器:

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

但它只在我点击标题时被调用,并且总是说 isSelected 是错误的。

这是我用于行名的代码,包括渲染器中的高亮部分 - 代码不是我写的,我只是稍微修改了一下:

/*
 *  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();

    }
}

提前感谢您的帮助!

最佳答案

一个轻微的变体:当我读到这个问题时,主要问题是标题没有在选择更改时更新。让自定义 header 监听选择更改对这种情况没有多大帮助。

事实上,JTableHeader 已经正在监听 ColumnModel 并且模型的更改通知包括选择更改。只有 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.

自定义 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;
    }
}

关于观察:

always says isSelected is false

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

ui.selected != columnModel.selected

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

关于java - 突出显示 JTable 的列标题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15489818/

有关java - 突出显示 JTable 的列标题的更多相关文章

  1. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  4. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  5. ruby-on-rails - link_to 不显示任何 rails - 2

    我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article

  6. ruby-on-rails - 使用 Rmagick 或 ImageMagick 在背景上放置标题 - 2

    我有一张背景图片,我想在其中添加一个文本框。我想弄清楚如何将标题放置在其顶部的正确位置。(我使用标题是因为我需要自动换行功能)。现在,我只能让文本显示在左上角,但我需要能够手动定位它的开始位置。require'RMagick'require'Pry'includeMagicktext="Loremipsumdolorsitamet"img=ImageList.new('template001.jpg')img 最佳答案 这是使用convert的ImageMagick命令行的答案。如果你想在Rmagick中使用这个方法,你必须自己移植

  7. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  8. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  9. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  10. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

随机推荐