在应用默认的Nimbus样式时,最重要的prepareRenderer ?

时间:2022-06-22 12:04:32

I'm using Nimbus. To make things simple with overriding prepareRenderer on a JTable, the first thing I usually do is get the Component from the super method, so I can tweak only the properties I want while leaving everything else the same.

我用灵气。为了简化在JTable上重写prepareRenderer的操作,我通常做的第一件事就是从超级方法中获取组件,这样我就可以只调整我想要的属性,同时保留其他所有东西。

The problem is once I change a style property on that component, like background color, it does every single render after that with that color because it apparently is reusing that JLabel. So every new cell that renders becomes red, not just the one I wanted.

问题是,一旦我在那个组件上改变了一个样式属性,比如背景色,它会在那个颜色之后做每一个渲染,因为它显然是在重复使用JLabel。所以每一个呈现出来的新细胞都是红色的,而不仅仅是我想要的。

I've always used HTML to avoid this, but I need to manipulate the JLabel's foreground/background properties. Does anybody have a block of code that sets all the default properties for a renderer, and I can use that in the applyDefaults method placeholder I have below?

我一直使用HTML来避免这一点,但我需要操作JLabel的前景/背景属性。有没有人有一个代码块来设置渲染器的所有默认属性,我可以在下面的applyDefaults方法占位符中使用它?

I am using Nimbus so I don't know if that makes things harder. But I want the foreground/background for selected/unselected and odd/even rows to be rendered to their defaults, and everything is manipulated after that.

我使用的是Nimbus,所以我不知道这会不会让事情变得更困难。但是,我希望选择/未选择的、奇数/偶数行的前景/背景被呈现给它们的默认值,然后所有的操作都被操作。

@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {

        final Component c =super.prepareRenderer(renderer, row, col);
        applyDefaults(c, row, col); //what do I need to restore default styles here? 

        boolean highlightRed condtion == //some boolean condition
        boolean isSelected = //calculate whether row is selected

        if (c instanceof JLabel) { 
            if (isSelected == false && highlightRed) { 
                ((JLabel) c).setBackground(Color.RED);
            }
        }

UPDATE: Went with camickr's suggestion and I built a convenient default interface for Nimbus JTables. the restoreDefaultRenderer resets all the properties to the default Nimbus colors and alignments.

更新:使用camickr的建议,我为Nimbus JTables构建了一个方便的默认接口。restoreDefaultRenderer将所有属性重置为默认的Nimbus颜色和对齐。

public interface JTableCustomRender {
    static final Color foreGround = Color.black;
    static final Color oddBackGround = new Color(255,255,255);
    static final Color evenBackGround = new Color(242,242,242);
    static final Color selectedForeGround = new Color(255,255,255);
    static final Color selectedBackGround = new Color(57,105,138);

    //static final ImmutableList<Class<?>> leftAlignTypes = ImmutableList.of(String.class, Date.class, DateTime.class);
    static final ImmutableList<Class<?>> rightAlignTypes = ImmutableList.of(Integer.class, Double.class, Float.class, BigDecimal.class);

    public Component prepareRenderer(TableCellRenderer renderer, int viewRow, int viewCol);

    public default Component restoreDefaultRenderer(JTable table, Component c, int viewRow, int viewCol) { 

        if (c instanceof JLabel) { 
            final boolean rowSelected = Arrays.stream(table.getSelectedRows()).filter(i -> i == viewRow).findAny().isPresent();

            JLabel label = (JLabel) c;
            if (rowSelected) { 
                label.setForeground(selectedForeGround);
                label.setBackground(selectedBackGround);
            }
            else { 
                if (viewRow % 2 == 0) { 
                    label.setBackground(evenBackGround);
                }
                else { 
                    label.setBackground(oddBackGround);
                }
                label.setForeground(foreGround);
            }
            Object value = table.getValueAt(viewRow, viewCol);

            if(rightAlignTypes.contains(value.getClass())) { 
                label.setHorizontalAlignment(SwingConstants.RIGHT);
            }
            else { 
                label.setHorizontalAlignment(SwingConstants.LEFT);
            }
        }

        return c;
    }

}

2 个解决方案

#1


2  

it does every single render after that with that color because it apparently is reusing that JLabel.

它每一个渲染之后都用那个颜色,因为它显然是在重用JLabel。

Correct, which is why you need an else statement to reset the background back to the table default.

正确,这就是为什么您需要一个else语句来将背景重置为表默认值。

Check out Table Row Rendering for examples of how you might do this so that you also take into account the selection color of the row as well.

请查看表行呈现,以了解如何实现这一点,以便您也考虑到行的选择颜色。

Does anybody have a block of code that sets all the default properties for a renderer

有没有人有一段代码来设置渲染器的所有默认属性?

The basic code would be:

基本守则是:

c.setBackground( getBackground() );
c.setForeground( getForeground() );

You would do that for any property that you are manually tying to override.

您将对手动绑定的任何属性执行此操作。

#2


0  

Here is an example code overriding the method prepareRenderer(), hope it helps someone:

这里有一个示例代码覆盖了方法prepareRenderer(),希望它能帮助某人:

public class MyJTable extends JTable {
    private final Color lineSelectedBackgroundColor = new Color(153,204,255);
    private final Color cellSelectedBackgroundColor = new Color(51,153,255);
    private final Color cellSelectedForeGroundColor = Color.BLACK;

    private final Color oddRowBackgroundColor = new Color(224,224,224);
    private final Color evenRowBackgroundColor = Color.WHITE;

    private final int lowThreshold = 33;
    private final int highThreshold = 66;

    private final boolean debugEnabled = true;
    private void log(String msg){ if(debugEnabled){ System.out.println(msg); } }

    @Override
    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
        JComponent component = (JComponent) super.prepareRenderer(renderer, row, column);
        int selectedRow = super.getSelectedRow();
        int selectedColumn = super.getSelectedColumn();

        if(row==selectedRow && column==selectedColumn){
            component.setForeground(cellSelectedForeGroundColor);
            component.setBackground(cellSelectedBackgroundColor);
        }else if (row==selectedRow){
            component.setBackground(lineSelectedBackgroundColor);
        }else{
            if(row % 2 == 0) {
                component.setBackground(evenRowBackgroundColor);
            }else{
                component.setBackground(oddRowBackgroundColor);
            }
        }

        if(column==AppData.hyundaiTableStockIndex) {
            String stockStr = getValueAt(row, AppData.hyundaiTableStockIndex).toString();
            try{
                int stockValue = Integer.valueOf(stockStr);
                if (stockValue < lowThreshold) {
                    component.setBackground(Color.RED);
                } else if (stockValue > lowThreshold && stockValue < highThreshold) {
                    component.setBackground(Color.YELLOW);
                } else if (stockValue > highThreshold) {
                    component.setBackground(Color.GREEN);
                }
            }catch (Exception ex){
                log("parsing failed.");
            }
        }

        return component;
    }
}

#1


2  

it does every single render after that with that color because it apparently is reusing that JLabel.

它每一个渲染之后都用那个颜色,因为它显然是在重用JLabel。

Correct, which is why you need an else statement to reset the background back to the table default.

正确,这就是为什么您需要一个else语句来将背景重置为表默认值。

Check out Table Row Rendering for examples of how you might do this so that you also take into account the selection color of the row as well.

请查看表行呈现,以了解如何实现这一点,以便您也考虑到行的选择颜色。

Does anybody have a block of code that sets all the default properties for a renderer

有没有人有一段代码来设置渲染器的所有默认属性?

The basic code would be:

基本守则是:

c.setBackground( getBackground() );
c.setForeground( getForeground() );

You would do that for any property that you are manually tying to override.

您将对手动绑定的任何属性执行此操作。

#2


0  

Here is an example code overriding the method prepareRenderer(), hope it helps someone:

这里有一个示例代码覆盖了方法prepareRenderer(),希望它能帮助某人:

public class MyJTable extends JTable {
    private final Color lineSelectedBackgroundColor = new Color(153,204,255);
    private final Color cellSelectedBackgroundColor = new Color(51,153,255);
    private final Color cellSelectedForeGroundColor = Color.BLACK;

    private final Color oddRowBackgroundColor = new Color(224,224,224);
    private final Color evenRowBackgroundColor = Color.WHITE;

    private final int lowThreshold = 33;
    private final int highThreshold = 66;

    private final boolean debugEnabled = true;
    private void log(String msg){ if(debugEnabled){ System.out.println(msg); } }

    @Override
    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
        JComponent component = (JComponent) super.prepareRenderer(renderer, row, column);
        int selectedRow = super.getSelectedRow();
        int selectedColumn = super.getSelectedColumn();

        if(row==selectedRow && column==selectedColumn){
            component.setForeground(cellSelectedForeGroundColor);
            component.setBackground(cellSelectedBackgroundColor);
        }else if (row==selectedRow){
            component.setBackground(lineSelectedBackgroundColor);
        }else{
            if(row % 2 == 0) {
                component.setBackground(evenRowBackgroundColor);
            }else{
                component.setBackground(oddRowBackgroundColor);
            }
        }

        if(column==AppData.hyundaiTableStockIndex) {
            String stockStr = getValueAt(row, AppData.hyundaiTableStockIndex).toString();
            try{
                int stockValue = Integer.valueOf(stockStr);
                if (stockValue < lowThreshold) {
                    component.setBackground(Color.RED);
                } else if (stockValue > lowThreshold && stockValue < highThreshold) {
                    component.setBackground(Color.YELLOW);
                } else if (stockValue > highThreshold) {
                    component.setBackground(Color.GREEN);
                }
            }catch (Exception ex){
                log("parsing failed.");
            }
        }

        return component;
    }
}