简体   繁体   中英

Highlight related cells in hairline cross pattern on selection

I want to add hairline cross highlighting to a JXTable . But I can either highlight the current row or the current column; never both.

What I currently have is the red part, the yellow part is what I want to add.

在此处输入图片说明

Below a SSCCE 1 .

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]; }
  }

}

Update

Using the code and suggestions provided by @camickr yields this:

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();
      }
    });
  }

}

But unfortunately I have problems with artifacts now. Similar to the picture below (which is taken from a version which is colored in red only).

在此处输入图片说明


I'm using Java 1.8.0_74 on Windows 10.0.16299 Build 16299. JXTable is from

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

It seems to work when using a JTable (although the order of the if statements needs to be changed if you want the column to have priority). So it seems that JXTable does some additional rendering that is causing the problem.

So here is an alternative approach based on Table Row Rendering that appears to work for 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;
    }
};

The above code replaces the custom renderer:

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

Note: in your "MCVE" of my suggestion you removed:

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

Why? I only gave you the above 2 changes.

This is why you need to post a proper "MCVE" so we can be sure you implemented the suggestion properly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM