简体   繁体   中英

How to change the color of the line dynamically?

My table looks like this, everything works and everything is OK) I need that if the condition ARRIVAL = 0 or DEPART = 0 is met, then the text color in the whole row was of a different color, for example, red or black, it does not matter, I can not figure out how to change it, maybe it's easy, I'm new) I haven't found an answer to this question in other questions

private void btnLogIdentifications2ActionPerformed(java.awt.event.ActionEvent evt) {                                                       
    setTableSettingsReport();
    searchIdentificationsReport(true);
    open = true;
}
public void searchIdentificationsReport(boolean all) {
    int z = 0;
    while (z < tm.getRowCount()) {
        tm.removeRow(z);
    }
    Statement statement = null;
    try {
        statement = getDbConnection().createStatement();
        String sql = "select a.id, pr.p_name,pr.p_surname,pr.p_patronic, a.date_arrival_from,a.date_arrival_to, a.arrival,a.date_departure_from,a.date_departure_to, a.depart, a.arrival_comment, a.depart_comment,a.prsn_id "
                + "  FROM bio.persons pr, attendance a where pr.p_id=a.prsn_id and a.date<=CURDATE() ";
        if (cbPersons.getSelectedItem() != null && model.getSelectedItem() != null) {
            CodeValueDTO dto = (CodeValueDTO) model.getSelectedItem();
            sql += " and  pr.p_id='" + dto.getId() + "'";
        }
        if (!all) {
            sql += " and (ARRIVAL =0 or DEPART=0)";

        }

        statement.execute(sql);
        ResultSet rs = statement.getResultSet();
        int value = 1;
        while (rs.next()) {
            Object[] objects = new Object[13];
            for (int i = 0; i < 13; i++) {
                objects[i] = rs.getObject(i + 1);
            }
            if (rs.getInt(7) == 0) {
                objects[6] = "Нет";

            } else {
                objects[6] = "Да";
            }

            if (rs.getInt(10) == 0) {
                objects[9] = "Нет";
            } else {
                objects[9] = "Да";
            }
            System.out.println(value);
            jTblReport.setDefaultRenderer(String.class, new MyCellRenderer(6));
            jTblReport.setDefaultRenderer(String.class, new MyCellRenderer(9));

            tm.addRow(objects);
        }

    } catch (SQLException ex) {
        ex.printStackTrace();
    } finally {
        try {
            statement.close();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

}
private void setTableSettingsReport() {

    jTblReport.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    jTblReport.setRowSelectionAllowed(true);
    jTblReport.setAutoCreateRowSorter(true);
    jTblReport.getTableHeader().setReorderingAllowed(false);

    String[] dbColNames = new String[13];
    dbColNames[0] = "ID";
    dbColNames[1] = "Имя";
    dbColNames[2] = "Фамилия";
    dbColNames[3] = "Отчество";
    dbColNames[4] = "Дата прихода с ";
    dbColNames[5] = "Дата прихода до";
    dbColNames[6] = "Прибытие";
    dbColNames[7] = "Дата ухода с ";
    dbColNames[8] = "Дата ухода до";
    dbColNames[9] = "Убытие";
    dbColNames[10] = "Причина опоздания";
    dbColNames[11] = "Причина раннего ухода";
    dbColNames[12] = "ID лица";

    // dbColNames[8] = "Дата начала";
    //  dbColNames[9] = "Дата окончания";    
    tm.setColumnIdentifiers(dbColNames);
    jTblReport.setModel(tm);
    jTblReport.setSelectionForeground(Color.white);

    jTblReport.setSelectionBackground(Color.red);
    jTblReport.getColumnModel().getColumn(0).setPreferredWidth(10);
    jTblReport.getColumnModel().getColumn(1).setPreferredWidth(60);
    jTblReport.getColumnModel().getColumn(2).setPreferredWidth(60);
    jTblReport.getColumnModel().getColumn(3).setPreferredWidth(60);
    jTblReport.getColumnModel().getColumn(4).setPreferredWidth(60);
    jTblReport.getColumnModel().getColumn(5).setPreferredWidth(60);
    jTblReport.getColumnModel().getColumn(6).setPreferredWidth(60);
    jTblReport.getColumnModel().getColumn(7).setPreferredWidth(60);
    jTblReport.getColumnModel().getColumn(8).setPreferredWidth(60);
    jTblReport.getColumnModel().getColumn(9).setPreferredWidth(60);
    jTblReport.getColumnModel().getColumn(10).setPreferredWidth(60);
    jTblReport.getColumnModel().getColumn(10).setPreferredWidth(60);
    jTblReport.getColumnModel().getColumn(10).setPreferredWidth(60);

}

public class MyCellRenderer extends DefaultTableCellRenderer {

private int columNum = 0;

public MyCellRenderer(Integer columNum) {
    this.columNum = columNum;
}

@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
        int row, int column) {
    Object object = table.getValueAt(row, this.columNum);

    if (object.equals("Нет")) {
        setBackground(Color.RED);
    }
    return this;
}

}

I was advised to write my render, but using it, my whole table becomes red and the values ​​do not appear, that is, the table is empty

Arrival and Depart check by objects[6] = "Нет" and objects[9] = "Нет"

The problem why your whole table becomes red is because it reuses the renderer to paint each cell and in your code you only set background once (on first encounter of "Нет") and never return it back to default color (or no color).

Just think of a renderer as a stamp, if you color the stamp red once and not recolor it to something else - all your next stamps will be red.

Also you can't really do this:

jTblReport.setDefaultRenderer(String.class, new MyCellRenderer(6));
jTblReport.setDefaultRenderer(String.class, new MyCellRenderer(9));

Second one overrides the first one as table only stores one renderer per class type. Instead you can just handle this logic right in the renderer. That being said, it is not recommended to do any "heavy lifting" (like server/db requests and such) inside the renderer as it will dramatically slow down the UI responsiveness. Instead you should do such operations on a separate thread and provide results into your table model.

Either way, here is a fully working example for the simple case:

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.util.Objects;

/**
 * @author Mikle Garin
 * @see https://stackoverflow.com/questions/56831494/how-to-change-the-color-of-the-line-dynamically
 */
public class TableRenderer
{
    public static void main ( String[] args )
    {
        SwingUtilities.invokeLater ( () -> {
            final JFrame frame = new JFrame ( "Table renderer" );
            frame.add ( new JScrollPane ( createTableSettingsReport () ) );
            frame.setDefaultCloseOperation ( WindowConstants.EXIT_ON_CLOSE );
            frame.pack ();
            frame.setLocationRelativeTo ( null );
            frame.setVisible ( true );
        } );
    }

    private static JTable createTableSettingsReport ()
    {
        final String[] dbColNames = new String[ 13 ];
        dbColNames[ 0 ] = "ID";
        dbColNames[ 1 ] = "Имя";
        dbColNames[ 2 ] = "Фамилия";
        dbColNames[ 3 ] = "Отчество";
        dbColNames[ 4 ] = "Дата прихода с ";
        dbColNames[ 5 ] = "Дата прихода до";
        dbColNames[ 6 ] = "Прибытие";
        dbColNames[ 7 ] = "Дата ухода с ";
        dbColNames[ 8 ] = "Дата ухода до";
        dbColNames[ 9 ] = "Убытие";
        dbColNames[ 10 ] = "Причина опоздания";
        dbColNames[ 11 ] = "Причина раннего ухода";
        dbColNames[ 12 ] = "ID лица";

        final String[][] data = {
                { "1", "Сергей", "Кирчин", "Васильевич",
                        "15.12.2002", "22.12.2002", "Да",
                        "25.08.2005", "26.08.2005", "Да",
                        "Болел", "Стало плохо", "123" },

                { "2", "Сергей", "Кирчин", "Васильевич",
                        "15.12.2002", "22.12.2002", "Нет",
                        "25.08.2005", "26.08.2005", "Да",
                        "Болел", "Стало плохо", "123" },

                { "3", "Сергей", "Кирчин", "Васильевич",
                        "15.12.2002", "22.12.2002", "Да",
                        "25.08.2005", "26.08.2005", "Нет",
                        "Болел", "Стало плохо", "123" }
        };

        final JTable jTblReport = new JTable ( new DefaultTableModel ( data, dbColNames ) );
        jTblReport.setSelectionMode ( ListSelectionModel.SINGLE_SELECTION );
        jTblReport.setRowSelectionAllowed ( true );
        jTblReport.setAutoCreateRowSorter ( true );
        jTblReport.getTableHeader ().setReorderingAllowed ( false );

        jTblReport.setDefaultRenderer ( Object.class, new MyCellRenderer () );

        // Optionally (if you have Boolean values, just easier to distinguish the data by type):
        // jTblReport.setDefaultRenderer ( Boolean.class, new MyBooleanCellRenderer () );

        jTblReport.getColumnModel ().getColumn ( 0 ).setPreferredWidth ( 10 );
        jTblReport.getColumnModel ().getColumn ( 1 ).setPreferredWidth ( 60 );
        jTblReport.getColumnModel ().getColumn ( 2 ).setPreferredWidth ( 60 );
        jTblReport.getColumnModel ().getColumn ( 3 ).setPreferredWidth ( 60 );
        jTblReport.getColumnModel ().getColumn ( 4 ).setPreferredWidth ( 60 );
        jTblReport.getColumnModel ().getColumn ( 5 ).setPreferredWidth ( 60 );
        jTblReport.getColumnModel ().getColumn ( 6 ).setPreferredWidth ( 60 );
        jTblReport.getColumnModel ().getColumn ( 7 ).setPreferredWidth ( 60 );
        jTblReport.getColumnModel ().getColumn ( 8 ).setPreferredWidth ( 60 );
        jTblReport.getColumnModel ().getColumn ( 9 ).setPreferredWidth ( 60 );
        jTblReport.getColumnModel ().getColumn ( 10 ).setPreferredWidth ( 60 );
        jTblReport.getColumnModel ().getColumn ( 10 ).setPreferredWidth ( 60 );
        jTblReport.getColumnModel ().getColumn ( 10 ).setPreferredWidth ( 60 );

        return jTblReport;
    }

    public static class MyCellRenderer extends DefaultTableCellRenderer
    {
        public MyCellRenderer ()
        {
            super ();
            setOpaque ( true );
            setBackground ( Color.WHITE );
        }

        @Override
        public Component getTableCellRendererComponent ( final JTable table, final Object value, final boolean isSelected,
                                                         final boolean hasFocus, final int row, final int column )
        {
            // Still need to call this to setup default stuff below
            super.getTableCellRendererComponent ( table, value, isSelected, hasFocus, row, column );

            // We should let selection color override our highlight
            if ( !isSelected )
            {
                // Checking conditions
                final boolean arrival = Objects.equals ( table.getValueAt ( row, 6 ), "Да" );
                final boolean departure = Objects.equals ( table.getValueAt ( row, 9 ), "Да" );
                setBackground ( !arrival || !departure ? Color.RED : Color.WHITE );
            }

            return this;
        }
    }
}

In this example renderer is working for all cells of the table and colors all cells of each single row red in case it has "Нет" in either column 6 or 9 as you mentioned in the question.

And just a small note for the future - it is strongly recommended to post an SSCCE (fully-working short code example) on Stack Overflow to reduce the time other people need to spend going through your code and analyzing what exactly is wrong. You can read about SSCCE here . This will greatly increase chances to get a good response/solution from SO community :)

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