【问题标题】:Very unusual cell highlighting in JXTableJXTable 中非常不寻常的单元格突出显示
【发布时间】:2014-12-21 13:37:01
【问题描述】:

我设置了一个 JXTable 来以某种颜色绘制选定的单元格。但是,只要选定的单元格位于顶行,就好像表格中的所有单元格都被绘制了一样。

谁能帮我理解为什么以及如何解决这个问题?

演示此问题的最小工作示例如下。

附加信息: 每次调用 Paint() 时都会重新应用 DefaultTableCellRenderer,因为它是我在完整程序中使用的 CustomTableCellRenderer 的占位符。有趣的是,如果我删除 DefaultTableCellRenderer 行,我的问题就解决了。为什么是这样?当然,如果没有指定渲染器,那么无论如何都使用默认值??

import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.HighlightPredicate;

public class MainClass {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        CustomTableModel tableModel = new CustomTableModel();
        JXXTable table = new JXXTable(tableModel);
        JScrollPane scrollPane = new JScrollPane(table);
        SelectionListener listener = new SelectionListener(table);
        table.getSelectionModel().addListSelectionListener(listener);    
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.add(scrollPane);
        frame.setVisible(true);
        frame.pack();
    }
}

class JXXTable extends JXTable {
    public JXXTable(CustomTableModel model){ super(model); }
    public void Paint(){
        this.setDefaultRenderer(Object.class, new DefaultTableCellRenderer());
        this.setHighlighters();
        HighlightPredicate predicate = new HighlightPredicate() {
            public boolean isHighlighted(Component renderer, ComponentAdapter adapter) {
                return adapter.hasFocus();
            }
        };
        this.addHighlighter(new ColorHighlighter(predicate, null, null, new Color(115,164,209), Color.WHITE)); 
    }
}

class SelectionListener implements ListSelectionListener {
    JXXTable table;
    public SelectionListener(JXXTable table) { this.table = table; }
    public void valueChanged(ListSelectionEvent e) { table.Paint(); }
}

class CustomTableModel extends AbstractTableModel {
    ArrayList<Object[]> al;

    public CustomTableModel() {
        al = new ArrayList<Object[]>(); 
        Object[] row = {1,2,3,"A","Collection","of","Random","Strings",9,10}; al.add(row);
        Object[] row2 = {11,12,13,"Another","Collection","Of","Random","Strings",19,20}; al.add(row2);
        Object[] row3 = {11,12,13,"Another","Collection","Of","Random","Strings",19,20}; al.add(row3);
        Object[] row4 = {11,12,13,"It","just","gets","more","random...",19,20}; al.add(row4);
    }

    public int getRowCount() { return al.size(); }
    public int getColumnCount() { return 10; }
    public Object getValueAt(int rowIndex, int columnIndex) { return al.get(rowIndex)[columnIndex]; }
}

【问题讨论】:

  • +1 表示实际可运行的示例

标签: java swing jtable swingx jxtable


【解决方案1】:

我“认为”部分问题与您在每次选择更改时添加另一个荧光笔有关。

相反,请考虑仅在初始化表格时添加突出显示...

话虽如此,也没有必要扩展JXTable,你并没有真正为类添加任何新功能。相反,您可以创建某种类型的工厂来配置您想要的表

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate;

public class MainClass {

    public static void main(String[] args) {
        new MainClass();
    }

    public MainClass() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                CustomTableModel tableModel = new CustomTableModel();
                JXTable table = new JXTable(tableModel);
                table.setDefaultRenderer(Object.class, new CustomTableCellRenderer());
                HighlightPredicate predicate = new HighlightPredicate() {
                    @Override
                    public boolean isHighlighted(Component cmpnt, org.jdesktop.swingx.decorator.ComponentAdapter ca) {
                        System.out.println(ca.getComponent());
                        return ca.hasFocus();
                    }
                };
                table.addHighlighter(new ColorHighlighter(predicate, null, null, new Color(115, 164, 209), Color.WHITE));

                JScrollPane scrollPane = new JScrollPane(table);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(scrollPane);
                frame.setVisible(true);
                frame.pack();
            }
        });
    }

    class CustomTableCellRenderer extends DefaultTableCellRenderer {

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

    class CustomTableModel extends AbstractTableModel {

        ArrayList<Object[]> al;

        public CustomTableModel() {
            al = new ArrayList<Object[]>();
            Object[] row = {1, 2, 3, "A", "Collection", "of", "Random", "Strings", 9, 10};
            al.add(row);
            Object[] row2 = {11, 12, 13, "Another", "Collection", "Of", "Random", "Strings", 19, 20};
            al.add(row2);
            Object[] row3 = {11, 12, 13, "Another", "Collection", "Of", "Random", "Strings", 19, 20};
            al.add(row3);
            Object[] row4 = {11, 12, 13, "It", "just", "gets", "more", "random...", 19, 20};
            al.add(row4);
        }

        public int getRowCount() {
            return al.size();
        }

        public int getColumnCount() {
            return 10;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            return al.get(rowIndex)[columnIndex];
        }
    }
}

【讨论】:

  • 感谢您的建议。不幸的是,我需要能够“刷新”桌子上的荧光笔(......在完整程序中还有其他荧光笔)。尽管如此,“this.setHighlighters()”行应该在重新应用它们之前准备一个干净的石板,所以我不会一直添加越来越多。 (如果这样做是问题的原因,我会质疑为什么只有顶行有症状。)
  • @DarkOwl 你有没有考虑过改变实际的高亮逻辑,而不是高亮然后自己
  • 抱歉,我不确定我理解这会涉及什么。听起来您基本上是在建议我寻找解决方法 - 我最终可能不得不求助于 - 但我仍然想确定上述问题的原因。
  • 我现在已经修好了。您说的问题是在每次选择更改时创建另一个对象的问题是正确的,但问题不是荧光笔对象,而是 TableCellRenderer 对象。
  • 它仍然关心荧光笔的娱乐性,但这更多的是性能问题知道;)
【解决方案2】:

对于其他遇到此问题的人,这是我的解决方案。

问题是每次调用表格的 Paint() 方法时(即每次更改选择时)都会创建一个新的 TableCellRenderer 对象。解决方案是将渲染器对象创建为表格对象的一个​​字段,然后在 Paint() 方法中简单地重新应用它(而不是重新创建它)。这个渲染器也需要在表的构造函数中应用。

我在此过程中进行的另一项代码改进是将上述相同的规则应用于 ColorHighlighter 和 HighlightPredicate 对象。

即。表类变为:

class JXXTable extends JXTable {
    DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
    HighlightPredicate predicate = new HighlightPredicate(){
        public boolean isHighlighted(Component renderer, ComponentAdapter adapter) {
            return adapter.hasFocus();
        }
    };
    Highlighter cellHighlight = new ColorHighlighter(predicate, null, null, new Color(115,164,209), Color.WHITE);

    public JXXTable(CustomTableModel model){ 
        super(model); 
        this.setDefaultRenderer(Object.class, renderer);
    }
    public void Paint(){
        this.setDefaultRenderer(Object.class, renderer);
        this.setHighlighters();
        this.addHighlighter(cellHighlight); 
    }
}

【讨论】:

    猜你喜欢
    • 2020-05-24
    • 2021-08-10
    • 2015-04-24
    • 1970-01-01
    • 1970-01-01
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多