简体   繁体   English

JTable 单元格渲染基于内容

[英]JTable cell render based on content

I design a system by Java Swing.我通过 Java Swing 设计了一个系统。 I have a tablet called sick and this tablet has a column called status which has two values,one is open and another is closed values.我有一个叫做病的平板电脑,这个平板电脑有一个叫做状态的列,它有两个值,一个是打开的,另一个是关闭的值。 When the value of the column is open I want to change color to blue and when it is closed I want to change color to red (when the information is selected from the database).当列的值打开时,我想将颜色更改为蓝色,当它关闭时,我想将颜色更改为红色(从数据库中选择信息时)。

What it appears you are looking to do is a form of Conditional Formatting against one or more specific cells within a JTable.您似乎想要做的是针对 JTable 中的一个或多个特定单元格的一种条件格式。 This can be done by overriding the JTable's prepareRenderer() method with a custom Prepare Renderer method:这可以通过使用自定义 Prepare Renderer 方法覆盖 JTable 的prepareRenderer()方法来完成:

在此处输入图像描述

Here is a runnable code example that displays the above example form image:这是显示上述示例表单图像的可运行代码示例:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;


public class JTablePrepareRendererExample {

    // Age Group colors
    Color ageGroup1Color = Color.decode("#FCF3CF");    // Light Yellow
    Color ageGroup2Color = Color.decode("#EBDEF0");    // Light Magenta
    Color ageGroup3Color = Color.decode("#D4EFDF");    // Light Green
    Color ageGroup4Color = Color.decode("#FAD7A0");    // Light Orange
    Color ageGroup5Color = Color.decode("#D4AC0D");    // Gold
    Color ageGroup6Color = Color.decode("#566573");    // Dark Gray

    // Status Group Colors
    Color openColor = Color.decode("#D4E6F1");         // Light Red
    Color closeColor = Color.decode("#FADBD8");        // Light Blue

    // Row Selection Color
    Color selection = Color.decode("#7FB3D5");         // A lighter Blue 

    // Table Default Colors
    Color cellsOrigBackColor = new JTable().getBackground();
    Color cellsOrigForeColor = new JTable().getForeground();


    public static void main(String[] args) {
        // So we don't need statics...
        new JTablePrepareRendererExample().startDemo(args);
    }

    private void startDemo(String[] args) {
        initializeForm();
    }

    private void initializeForm() {
        // Create a JFrame Form (with title).
        JFrame frame = new JFrame("JTable Conditional Formatting");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  // Set its' Close Operation
        frame.setAlwaysOnTop(true);  // Set that form will be on top of all other applications.
        frame.setSize(new Dimension(400, 250));     // Set the form size.
        frame.setLayout(new BorderLayout());  // Set the form to utilize the Border Layout Manager.

        // Table Column Names
        Object[] columnNames = {"Name", "Age", "Alive", "Case Status"};

        // Table Data...
        Object data[][] = {
            {"Tracey Johnson", 24, "Yes", "Unknown"},
            {"Frank Thetank", 108, "Barely", "Closed"},
            {"Denis Therman", 41, "Yes", "Open"},
            {"Joe Blow", 60, "Yes", "Unknown"},
            {"Fred Flintston", "@1", "No", "Closed"},
            {"John Doe", 73, "Yes", "Open"},
            {"James Brown", 87, "No", "Closed"} };

        // Create a JTable Model and fill the table model with the above Object data...
        DefaultTableModel model = new DefaultTableModel(data, columnNames);
        // Declare a JTable and set the Table Model to that table.
        JTable table = new JTable(model) {
            private static final long serialVersionUID = 1L;
            // Here is where all the cell formatting is done in this example
            @Override
            public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int columnIndex) {
                Color cellBackColor = cellsOrigBackColor;  // Original Cells Backgound color.
                Color cellForeColor = cellsOrigForeColor;  // Original Cells Foregound (text) color.

                /* Acquire the current cell component being Rendered.
                   ALL cells get Rendered.            */
                JComponent component = (JComponent) super.prepareRenderer(renderer, rowIndex, columnIndex);

                // The 'Age' Field Color Conditions...
                // ===================================
                // Get the 'Age' field value and convert to integer.
                if (columnIndex == 1) {
                    String sAge = getValueAt(rowIndex, 1).toString();
                    int age = -1; // Age Default.
                    /* Make sure the data value in the current Age cell 
                       being rendered is indeed a string representation 
                       of a Integer (int) numerical value.           */
                    if (sAge.matches("\\d+")) {
                        // Convert the table cell value to Integer
                        age = Integer.parseInt(sAge);
                    }
                    else {
                        /* If it's not a Integer type value then indicate
                           ERROR in cell and highlight RED  */
                        cellBackColor = Color.RED;
                        component.setBackground(cellBackColor);
                        cellForeColor = properTextColor(cellBackColor);
                        component.setForeground(cellForeColor);
                        model.setValueAt("** ERROR **", rowIndex, 1);
                        return component;
                    }

                    if (age <= 25) {
                        cellBackColor = ageGroup1Color;
                    }
                    else if (age >= 26 && age <= 45) {
                        cellBackColor = ageGroup2Color;
                    }
                    else if (age >= 46 && age <= 65) {
                        cellBackColor = ageGroup3Color;
                    }
                    else if (age >= 66 && age <= 80) {
                        cellBackColor = ageGroup4Color;
                    }
                    else if (age >= 81 && age <= 95) {
                        cellBackColor = ageGroup5Color;
                    }
                    else if (age > 95) {
                        cellBackColor = ageGroup6Color;
                    }
                    else {
                        cellBackColor = cellsOrigBackColor;
                    }
                }

                // The 'Status' Field Color Conditions...
                // ======================================
                // Get the 'Status' field value
                String status = getValueAt(rowIndex, 3).toString();
                if (columnIndex == 3) {
                    if (status.equalsIgnoreCase("closed")) {
                        cellBackColor = closeColor;
                    }
                    else if (status.equalsIgnoreCase("open")) {
                        cellBackColor = openColor;
                    }
                    else {
                        cellBackColor = cellsOrigBackColor;
                    }
                }

                /* Set Age cell's determined Background color 
                   based on any of the particular conditions 
                  stipulated above.               */
                component.setBackground(cellBackColor);
                /* Set cell's Text (foreground) Color based on 
                   color and brightness of Cell's Background 
                   color.           */
                cellForeColor = properTextColor(cellBackColor); // Helper method
                component.setForeground(cellForeColor);

                // If a row is selected, maintain the conditional formatting...
                if (isRowSelected(rowIndex)) {
                    component.setBackground(selection);
                } else {
                    component.setBackground(cellBackColor);
                }
                return component;
            }
        };

        /* Set the table size, columns not selectable, 
           rows selectable via single selection   */
        table.setPreferredSize(new Dimension(400, 250));
        table.setColumnSelectionAllowed(false);
        table.setRowSelectionAllowed(true);
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        /* Create a JScrollPane, set its size to Table and 
           add the Table to the JScrollPane ViewPort.   */
        JScrollPane sp = new JScrollPane();
        sp.setPreferredSize(table.getPreferredSize());
        sp.getViewport().add(table);

        // Create a JPanel to hold JScrollPane (and JTable)
        JPanel tablePanel = new JPanel();
        tablePanel.add(sp);   // Add ScrollPane to JPanel

        /* Create another JPanel to hold a JLabel 
           and the JButtons 'Add' and 'Close'  */
        JPanel buttonsPanel = new JPanel();
        // Set this JPanel to utilize a 'Flow Layout Manager'
        buttonsPanel.setLayout(new FlowLayout(FlowLayout.CENTER)); // Center any compnents in panel.

        // Create a JLabel. Shown how to utilize HTML here for a JLabel.
        JLabel doLabel = new JLabel("<html><pre><font color=blue>"
                + "Select a row and edit a cell.      </font></pre>"
                + "</html>");

        // Create the 'Add' JButton.
        JButton addButton = new JButton("Add"); 
        addButton.setToolTipText(" Add a Table Row ");  // Set a ToolTip for 'Add' Button.
        // Apply an Action Listener to 'Add' Button.  
        addButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                model.addRow(new Object[]{"", "0", "", ""});
            }
        }); 

        // Create the 'Close' JButton.
        JButton closeButton = new JButton("Close");
        closeButton.setToolTipText(" Close Application ");  // Set a ToolTip for 'Close' Button.
        closeButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        }); // Apply an Action Listener to 'Close' Button.

        buttonsPanel.add(doLabel);      // Add JLabel to Buttons JPanel.
        buttonsPanel.add(addButton);    // Add 'Add' JButton to Buttons JPanel.
        buttonsPanel.add(closeButton);  // Add 'Close' JButton to Buttons JPanel.

        frame.add(tablePanel, BorderLayout.NORTH);   // Add The Table JPanel to top of JFrame Form.
        frame.add(buttonsPanel, BorderLayout.SOUTH); // Add The Buttons JPanel to bottom of JFrame Form.

        frame.pack();   // Pack the components on JFrame.
        frame.setVisible(true); // Make the JFrame form visible.
        frame.setLocationRelativeTo(null);  // Make sure JFrame displays at center Screen.
    }

    /**
     * Returns either the Color WHITE or the Color BLACK dependent upon the
     * brightness of what the supplied background color might be. If the
     * background color is too dark then WHITE is returned. If the background
     * color is too bright then BLACK is returned.<br><br>
     *
     * @param currentBackgroundColor (Color Object) The background color text
     *                               will reside on.<br>
     *
     * @return (Color Object) The color WHITE or the Color BLACK.
     */
    public static Color properTextColor(Color currentBackgroundColor) {
        double L; // Holds the brightness value for the supplied color
        Color determinedColor;  // Default

        // Calculate color brightness from supplied color.
        int r = currentBackgroundColor.getRed();
        int g = currentBackgroundColor.getGreen();
        int b = currentBackgroundColor.getBlue();
        L = (int) Math.sqrt((r * r * .241) + (g * g * .691) + (b * b * .068));

        // Return the required text color to suit the 
        // supplied background color.
        if (L > 129) {
            determinedColor = Color.decode("#000000");  // White
        }
        else {
            determinedColor = Color.decode("#FFFFFF");  // Black
        }
        return determinedColor;
    }

}

In the above example there are two specific data columns that have specific conditions checked on each column cell, the Age column and the Case Status column.在上面的示例中,有两个特定数据列在每个列单元格上检查了特定条件,即年龄列和案例状态列。

In the Age column, a specific age range determines the cell background color that will be displayed.在“年龄”列中,特定的年龄范围决定了将显示的单元格背景颜色。 You will notice that for the Fred Flintston row, the age value holds a ERROR message (highlighted in red) instead of a age value.您会注意到,对于Fred Flintston行,年龄值包含错误消息(以红色突出显示)而不是年龄值。 If you look in the Object data array values you will see that the value supplied there ( "@1" ) for Age is not a proper integer value.如果您查看 Object 数据数组值,您会发现那里提供的年龄值 ( "@1" ) 不是正确的 integer 值。 This yet another condition which is checked within the Renderer.这是在渲染器中检查的又一个条件。 The colors used for this column are declared within the class as member variables.用于此列的 colors 在 class 中声明为成员变量。

The Case Status Table column checks for three specific conditions:案例状态表列检查三个特定条件:

  1. If cell value contains a string value of "Open" then that cells background color will be a light red .如果单元格值包含“Open”字符串值,则该单元格的背景颜色将为浅红色
  2. If cell value contains a string value of "Closed" then that cells background color will be a light blue .如果单元格值包含 "Closed" 字符串值,则该单元格的背景颜色将为浅蓝色
  3. If a cell value is anything other than "Open" or "Closed" then that cells background color will be the original cell background color.如果单元格值不是“打开”或“关闭”,则该单元格背景颜色将是原始单元格背景颜色。

Even the Row Selection color is modified within this custom Renderer to a lighter, more comfortable blue (well, in my opinion).甚至在这个自定义渲染器中,行选择颜色也被修改为更浅、更舒适的蓝色(嗯,在我看来)。

Because the possibility of background color change is available so too must be the capability to change the text (cell foreground) color so that it will be legible within certain colors.因为可以使用背景颜色更改,所以也必须能够更改文本(单元格前景)颜色,以便在某些 colors 内清晰可见。 By default the JTable cell text color is black, this makes text extremely hard to read if the cell's background color is changed to dark gray or even dark red.默认情况下,JTable 单元格文本颜色为黑色,如果单元格的背景颜色更改为深灰色甚至深红色,这会使文本极难阅读。 White text would be a better choice.白色文本将是更好的选择。 For this reason I have also included a helper method named properTextColor() that will automatically supply a text color (either White or Black) that would be the easiest to see dependent upon the Background color supplied to the method.出于这个原因,我还包含了一个名为properTextColor()的辅助方法,它将自动提供最容易看到的文本颜色(白色或黑色),具体取决于提供给该方法的背景颜色。 You can see this at work within the example application image provided specifically in Age column cells (rows: "Frank Thetank" and "Fred Flintston").您可以在Age列单元格中专门提供的示例应用程序图像中看到这一点(行:“Frank Thetank”和“Fred Flintston”)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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