Как установить фон ячеек в зависимости от предыдущих значений обновленного JTable

1

Я заполняю Jtable кавычками yahoo, чья загрузка запланирована каждые 60 секунд, подклассифицируя Timertask. Я бы изменил фон отдельных ячеек в зависимости от новых значений (например, если новое значение меньше старого цвета фона фона становится зеленым).

Я попытался (без результата) реализовать TableCellRenderer добавив propertychangelistener следующим образом:

    private static class TextCellRenderer implements TableCellRenderer {

        @Override public Component getTableCellRendererComponent(final JTable table, Object value, boolean isSelected, boolean hasFocus, final int r, final int c) {
            table.setRowHeight(10);
            final JTextField text = new JTextField();
            text.setOpaque(true);//disable transparence
            text.setText(value.toString());
            text.addPropertyChangeListener(new PropertyChangeListener(){

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                   JTextField l=(JTextField)evt.getSource();
                   l.setOpaque(true);
                   String property=evt.getPropertyName();
                   double d1=(Double)evt.getOldValue();//old value
                   if(property=="text"){
                       double d2=(Double)evt.getNewValue();//new value
                       //nothing happens - mantain old backround
                       if (d2==d1){
                           l.setBackground(l.getBackground());
                       }
                       //new value>old value
                       else if (d2>d1){
                           l.setBackground(Color.green);
                       }
                       //new value<old value
                       else if (d2<d1){
                           l.setBackground(Color.red);
                       } 
                       d1=d2;
                       }

                }

            });
            return text;  
        }       
}

Мне нужно понять, что я делаю неправильно. благодаря

  • 0
    строка "d1 = d2" в конце явно неверна, она была написана в предыдущем коде, я забыл удалить ее.
  • 1
    Смотрите это, if(property=="text")
Показать ещё 2 комментария
Теги:
timer
swing
jtable
tablecellrenderer

1 ответ

1
Лучший ответ

Мое предложение состоит в том, чтобы сначала использовать некоторый хороший дизайн. Создайте простой компонент, например CurrentPrevious где вы можете сохранить значение текущего и предыдущего значений. Добавьте эти экземпляры CurrentPrevious в модель таблицы.

class CurrentPrevious {
    Double current;
    Double previous;
    // getters an setters

    @Override
    public String toString() {
        return current.toString();
    }
}

Вы хотите, чтобы current значение просматривалось в таблице, поэтому вы можете просто переопределить toString класса и вернуть строковое значение current.

Что касается рендеринга, вам не нужен собственный рендер. Я не вижу, чтобы ты делал что-то особенное. Создание текстового поля в качестве средства визуализации кажется бессмысленным. Любые требуемые функции редактирования должны быть выполнены с помощью компонента редактора. Поэтому вместо настраиваемого рендеринга просто переопределите prepareRenderer таблицы. Что-то вроде ниже:

@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
    Component c = super.prepareRenderer(renderer, row, col);
    Object value = getValueAt(row, col);
    if (value instanceof CurrentPrevious) {
        CurrentPrevious curPrev = (CurrentPrevious) value;
        Double current = curPrev.getCurrent();
        Double previous = curPrev.getPrevious();
        Color color = getColor(current, previous);
        c.setBackground(color);
    }
    return c;
}
...
private Color getColor(Double current, Double previous) {
    Color color;
    if (current.equals(previous) || current > previous) {
        color = Color.GREEN;
    } else {
        color = Color.RED;
    }
    return color;
}

Когда значение нужно обновить, просто измените значение предыдущего на текущий и установите ток в новое значение.

DefaultTableModel model = (DefaultTableModel) table.getModel();
for (int i = 0; i < model.getRowCount(); i++) {
    CurrentPrevious curPrev = (CurrentPrevious) model.getValueAt(i, 0);
    curPrev.setPrevious(curPrev.getCurrent());
    Double newCurrent = getRandomDouble();
    curPrev.setCurrent(newCurrent);
    model.setValueAt(curPrev, i, 0);
}

Результат будет выглядеть примерно так:

Изображение 174551

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;

public class ChangeCellColorDemo {

    private Random random = new Random();
    private JTable table = getTable();

    public ChangeCellColorDemo() {
        Timer timer = new Timer(2000, new TimerListener());
        JFrame frame = new JFrame();
        frame.add(new JScrollPane(table));
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        timer.start();
    }

    private class TimerListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            DefaultTableModel model = (DefaultTableModel) table.getModel();
            for (int i = 0; i < model.getRowCount(); i++) {
                CurrentPrevious curPrev = (CurrentPrevious) model.getValueAt(i, 0);
                curPrev.setPrevious(curPrev.getCurrent());
                Double newCurrent = getRandomDouble();
                curPrev.setCurrent(newCurrent);
                model.setValueAt(curPrev, i, 0);
            }
        }
    }

    private JTable getTable() {
        JTable table = new JTable(getTableModel()) {
            @Override
            public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
                Component c = super.prepareRenderer(renderer, row, col);
                Object value = getValueAt(row, col);
                if (value instanceof CurrentPrevious) {
                    CurrentPrevious curPrev = (CurrentPrevious) value;
                    Double current = curPrev.getCurrent();
                    Double previous = curPrev.getPrevious();
                    Color color = getColor(current, previous);
                    c.setBackground(color);
                }
                return c;
            }

            @Override
            public Dimension getPreferredScrollableViewportSize() {
                return getPreferredSize();
            }
        };
        return table;
    }

    private TableModel getTableModel() {
        String[] cols = {"Value"};
        DefaultTableModel model = new DefaultTableModel(cols, 0);
        for (int i = 0; i < 10; i++) {
            Object[] row = new Object[1];
            Double current = getRandomDouble();
            Double previous = getRandomDouble();
            row[0] = new CurrentPrevious(current, previous);
            model.addRow(row);
        }
        System.out.println(model.getRowCount());
        return model;
    }

    private Color getColor(Double current, Double previous) {
        Color color;
        if (current.equals(previous) || current > previous) {
            color = Color.GREEN;
        } else {
            color = Color.RED;
        }
        return color;
    }

    private Double getRandomDouble() {
        BigDecimal bd = new BigDecimal(random.nextDouble());
        bd = bd.setScale(4, RoundingMode.HALF_UP);
        return bd.doubleValue();
    }

    class CurrentPrevious {

        Double current;
        Double previous;

        public CurrentPrevious() {}

        public CurrentPrevious(Double current, Double previous) {
            this.current = current;
            this.previous = previous;
        }

        public Double getCurrent() {
            return current;
        }

        public Double getPrevious() {
            return previous;
        }

        public void setCurrent(Double current) {
            this.current = current;
        }

        public void setPrevious(Double previous) {
            this.previous = previous;
        }

        @Override
        public String toString() {
            return current.toString();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new ChangeCellColorDemo();
            }
        });
    }
}
  • 1
    спасибо большое, работает отлично. Я не знал о бобах. Благодарю.
  • 0
    Круто, рад помочь. "bean" на самом деле является сокращением от JavaBean. Это просто старый Java-объект (POJO), который следует соглашениям JavaBean

Ещё вопросы

Сообщество Overcoder
Наверх
Меню