在选择时突出显示细线交叉图案中的相关单元格

Posted

技术标签:

【中文标题】在选择时突出显示细线交叉图案中的相关单元格【英文标题】:Highlight related cells in hairline cross pattern on selection 【发布时间】:2018-10-26 18:11:24 【问题描述】:

我想为JXTable 添加细线交叉突出显示。但我可以突出显示当前行或当前列;永远不要两者兼而有之。

我目前有的是红色部分,黄色部分是我要添加的。

低于 SSCCE1

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;

import org.jdesktop.swingx.JXTable;

public class Application


  public static void main(String[] args)
  
    EventQueue.invokeLater(new Runnable()
    
      @Override
      public void run()
      
        JFrame frame = new JFrame();
        JXTable table = new JXTable(new CustomTableModel());

        boolean highlightRow = false;
        table.setRowSelectionAllowed(highlightRow);
        table.setColumnSelectionAllowed(!highlightRow);

        table.setDefaultRenderer(Object.class, new CustomTableCellRenderer());

        frame.add(new JScrollPane(table));
        frame.setVisible(true);
        frame.pack();
      
    );
  

  public static class CustomTableCellRenderer extends DefaultTableCellRenderer
  

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    
      Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
      if (row == table.getSelectedRow())  component.setBackground(Color.YELLOW); 
      if (column == table.getSelectedColumn())  component.setBackground(Color.RED); 
      return component;
    
  

  static class CustomTableModel extends AbstractTableModel
  
    private final List<Object[]> data = new ArrayList<>();

    public CustomTableModel()
    
      data.add(new Object[] 1, 2, 3, "A", "Collection", "of", "Random", "Strings", 9, 10);
      data.add(new Object[] 1, 2, 3, "A", "Collection", "of", "Random", "Strings", 9, 10);
      data.add(new Object[] 1, 2, 3, "A", "Collection", "of", "Random", "Strings", 9, 10);
      data.add(new Object[] 1, 2, 3, "A", "Collection", "of", "Random", "Strings", 9, 10);
    

    @Override
    public int getRowCount()  return data.size(); 

    @Override
    public int getColumnCount()  return 10; 

    @Override
    public Object getValueAt(int rowIndex, int columnIndex)  return data.get(rowIndex)[columnIndex]; 
  


更新

使用@camickr 提供的代码和建议会产生这样的结果:

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

import org.jdesktop.swingx.JXTable;

public class Application


  public static void main(String[] args)
  
    EventQueue.invokeLater(new Runnable()
    
      @Override
      public void run()
      
        JFrame frame = new JFrame();

        DefaultTableModel model = new DefaultTableModel(5, 10);
        JXTable table = new JXTable(model)
        
            @Override
            public Component prepareRenderer(
                TableCellRenderer renderer, int row, int column)
            
                Component c = super.prepareRenderer(renderer, row, column);

                if (column == getSelectedColumn())  c.setBackground(Color.RED); 
                else if (row == getSelectedRow())  c.setBackground(Color.YELLOW); 
                else c.setBackground(getBackground());

                return c;
            
        ;

        frame.add(new JScrollPane(table));
        frame.setVisible(true);
        frame.pack();
      
    );
  


但不幸的是,我现在遇到了人工制品问题。类似于下图(取自仅以红色着色的版本)。


我在 Windows 10.0.16299 Build 16299 上使用 Java 1.8.0_74。JXTable 来自

        <dependency>
            <groupId>org.swinglabs.swingx</groupId>
            <artifactId>swingx-all</artifactId>
            <version>1.6.5-1</version>
        </dependency>

【问题讨论】:

我放弃了。您发布了“有效”的代码,但完全错误,因为不应从 prepareRenderer() 方法调用 repaint()。 System.out.println(...) 语句在哪里添加到 prepareRenderer() 方法中,它将显示该方法在无限循环中运行?为什么你甚至会认为这超出了我的范围。然而你仍然没有发布我的代码(我说它在我的机器上工作),作为一个合适的minimal reproducible example 供其他人复制/粘贴/编译/测试。 我还在我的原始答案中声明 JTable 可以与您的原始代码一起使用。因此,另一种方法可能是不使用 JXTable。不再支持此类。你需要什么功能?也许有一种简单的方法可以将它添加到 JTable。 “你的解决方案”是第二个例子。我弄错了吗? 它使用CustomTableModel,与问题无关。任何看到这个的人都希望使用标准 JDK 类尽可能简单地编写代码。 我删除了我的原始答案并在我的答案中重新添加以强调为什么正确的 minimal reproducible example 对于确保正确实施建议很重要。 【参考方案1】:

在使用 JTable 时似乎可以工作(尽管如果您希望列具有优先级,则需要更改 if 语句的顺序)。因此,似乎 JXTable 做了一些导致问题的额外渲染。

因此,这是一种基于Table Row Rendering 的替代方法,似乎适用于 JXTable:

JXTable table = new JXTable(new CustomTableModel())

    public Component prepareRenderer(
        TableCellRenderer renderer, int row, int column)
    
        Component c = super.prepareRenderer(renderer, row, column);

        if (column == getSelectedColumn())  c.setBackground(Color.RED); 
        else if (row == getSelectedRow())  c.setBackground(Color.YELLOW); 
        else c.setBackground(getBackground());

        return c;
    
;

以上代码替换了自定义渲染器:

//table.setDefaultRenderer(Object.class, new CustomTableCellRenderer());

注意:在您删除的我的建议的“MCVE”中:

boolean highlightRow = false;
table.setRowSelectionAllowed(highlightRow);
table.setColumnSelectionAllowed(!highlightRow);

为什么?我只给了你上面的 2 个改动。

这就是为什么您需要发布正确的“MCVE”,以便我们确保您正确实施了建议。

【讨论】:

公平地说:我只在 MCVE 中省略了 CustomTableModel ——但这并不具有建设性,我理解它为什么重要! 你能解释一下为什么代码可以工作,而且只能工作,行选择设置为false,列选择设置为true

以上是关于在选择时突出显示细线交叉图案中的相关单元格的主要内容,如果未能解决你的问题,请参考以下文章

目标 C:如何突出显示 tableView 单元格并在重新加载表格时保持突出显示?

点击时突出显示 tableview 单元格,按下警报控制器操作按钮时取消突出显示

单元格处于活动状态时突出显示整行

wps如何突出显示两列数据的重复项,而同列中重复数据不突出显示?

单击时突出显示表格视图单元格

Excel用底纹突出单元格的数据给Excel单元格添加底纹效果