JTable valuechanged,然后更改单元格颜色 [英] JTable valuechanged then change cell color

查看:488
本文介绍了JTable valuechanged,然后更改单元格颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 JTable ,有两(2)列。



因此,我的问题是,每当用户更改单元格的值时,该特定单元格就会改变它的单元格颜色。



我想这样做,因为我想让用户知道他/她在表中做了一些修改。



我发现这个地方,它不知何故解决了我的问题,但没有出现我的期望的一件事情是,改变了值后,点击另一个单元格,颜色变回原来的颜色。

  @Override 
public Component prepareEditor(TableCellEditor editor,int data ,int columns){
Component c = super.prepareEditor(editor,data,columns);
c.setBackground(Color.RED);
return c;
}

有可能吗?如果是,请显示一些示例。



更新:

 字符串[] columnname = {学生姓名,成绩}; 

Object [] [] data = {};

gradetable = new JTable(data,columnname){
private Object [] [] rowData;

public boolean isCellEditable(int data,int columns){
return columns == 1;
}


public Component prepareRenderer(TableCellRenderer r,int data,int columns){
final Component c = super.prepareRenderer(r,data,columns);

if(data%2 == 0){
c.setBackground(Color.LIGHT_GRAY);
}
else {
c.setBackground(Color.WHITE);
}

if(isCellSelected(data,columns)){
c.setBackground(Color.ORANGE);
}

return c;
}

@Override
public Component prepareEditor(TableCellEditor editor,int data,int columns){
Component c = super.prepareEditor(editor,data,columns) ;
c.setBackground(Color.RED);
return c;
}
};

gradetable.setModel(new DefaultTableModel(data,columnname));
gradetable.setPreferredScrollableViewportSize(new Dimension(350,130));
gradetable.setFillsViewportHeight(true);
gradetable.getTableHeader()。setReorderingAllowed(false);
gradetable.setGridColor(new Color(128,128,128,128));
JScrollPane jsp = new JScrollPane(gradetable);
panel3.add(jsp);表格使用 TableCellRenderer / code>在屏幕上绘制值。



因此,一旦编辑器被关闭(接受或取消),编辑器就不会与对方有任何关系),则使用分配的 TableCellRenderer



重新绘制单元格您需要在表模型中提供某种方式以确定哪些行已更新,并更改渲染器的状态以匹配。



FYI- DefaultTableCellRenderer a JLabel 作为基本渲染器,因此默认情况下是透明的;



请检查使用自定义渲染器了解详情



使用示例更新



这只是一个概念证明。它不会满足您的绝对要求,您应该认真看看上面链接的教程。



  import java.awt.BorderLayout; 
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

public class TableEdit {

public static void main(String [] args){
new TableEdit();
}

public TableEdit(){
EventQueue.invokeLater(new Runnable(){
@Override
public void run(){
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex){
}

JFrame frame = new JFrame(Testing);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

public TestPane(){
setLayout(new BorderLayout());
JTable table = new JTable(new MyTableModel());
table.setSurrendersFocusOnKeystroke(true);
TableColumnModel model = table.getColumnModel();
model.getColumn(1).setCellRenderer(new MyTableCellRenderer());
add(new JScrollPane(table));
}

@Override
public Dimension getPreferredSize(){
return new Dimension(200,200);
}
}

public class MyData {

private String key;
private String value;
private boolean changed;

public MyData(String key,String value){
this.key = key;
this.value = value;
this.changed = false;
}

public String getKey(){
return key;
}

public String getValue(){
return value;
}

public void setValue(String newValue){
if(value == null?newValue!= null:!value.equals(newValue)){
value = newValue;
changed = true;
}
}

public boolean hasChanged(){
return changed;
}
}

public class MyTableModel extends AbstractTableModel {

private List< MyData>数据;

public MyTableModel(){
data = new ArrayList<>(25);
for(int index = 0; index< 5; index ++){
data.add(new MyData(A+(index + 1),B+(index + 1)) );
}
}

@Override
public int getRowCount(){
return data.size();
}

@Override
public int getColumnCount(){
return 2;
}

@Override
public Object getValueAt(int rowIndex,int columnIndex){
MyData myData = data.get(rowIndex);
对象值= null;
switch(columnIndex){
case 0:
value = myData.getKey();
break;
case 1:
value = myData.getValue();
break;
}
返回值;
}

@Override
public Class<?> getColumnClass(int columnIndex){
return String.class;
}

@Override
public boolean isCellEditable(int rowIndex,int columnIndex){
return columnIndex == 1;
}

public boolean hasChanged(int rowIndex){
MyData myData = data.get(rowIndex);
return myData.hasChanged();
}

@Override
public void setValueAt(Object aValue,int rowIndex,int columnIndex){
MyData myData = data.get(rowIndex);
myData.setValue(aValue == null?null:aValue.toString());
}
}

public class MyTableCellRenderer extends DefaultTableCellRenderer {

@Override
public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected ,boolean hasFocus,int row,int column){
super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column);
setOpaque(isSelected);
TableModel model = table.getModel();
if(MyTableModel的model instance){
MyTableModel myModel =(MyTableModel)model;
if(myModel.hasChanged(row)){
if(!isSelected){
setBackground(Color.RED);
setOpaque(true);
}
}
}
return this;
}
}
}


I have here a JTable with two(2) columns. The right column is an editable one while the other is not.

So, what my problem is that whenever the user changed the value of a cell, that specific cell will changed its cell color.

I wanna do this because I want to let the user know that he/she made some changes in the table.

I found this somewhere and it somehow solved my problem but 1 thing that didn't come up with my expectation is that after changing the value and clicked another cell, the color changes back to its original color. I want to let it stay until it is saved.

@Override
public Component prepareEditor(TableCellEditor editor, int data, int columns) {
    Component c = super.prepareEditor(editor, data, columns);
    c.setBackground(Color.RED);
    return c;
}

Is it possible? If yes, please show some example.

UPDATE:

    String[] columnname = {"Student Name", "Grade"};

    Object[][] data = {};

    gradetable = new JTable(data, columnname){
        private Object[][] rowData;

        public boolean isCellEditable(int data, int columns){
            return columns == 1;
        }


        public Component prepareRenderer(TableCellRenderer r, int data, int columns){
            final Component c = super.prepareRenderer(r, data, columns);

            if (data % 2 == 0){
                c.setBackground(Color.LIGHT_GRAY);
            }
            else{
                c.setBackground(Color.WHITE);
            }

            if (isCellSelected(data, columns)){
                c.setBackground(Color.ORANGE);
            }                

            return c;
        }

        @Override
        public Component prepareEditor(TableCellEditor editor, int data, int columns) {
            Component c = super.prepareEditor(editor, data, columns);
            c.setBackground(Color.RED);
            return c;
        }
    };

    gradetable.setModel(new DefaultTableModel(data, columnname));
    gradetable.setPreferredScrollableViewportSize(new Dimension (350, 130));
    gradetable.setFillsViewportHeight(true);
    gradetable.getTableHeader().setReorderingAllowed(false);
    gradetable.setGridColor(new Color(128,128,128,128));
    JScrollPane jsp = new JScrollPane(gradetable);
    panel3.add(jsp);

解决方案

Tables use a TableCellRenderer to paint values on the screen. The editors and renderers don't actually have anything to do with each other (from a painting point of view).

So once the editor has been dismissed (accepted or cancelled), the cell is repainted using the assigned TableCellRenderer

You need to supply, in your table model, some way to determine which rows have been updated and change the state of the renderer to match.

FYI- The DefaultTableCellRenderer uses a JLabel as it's base renderer, so it is transparent by default; you will need to make it opaque to make it render properly.

Check out Using custom renderers for more details

Update with example

This is nothing more then a proof of concept. It will not meet your absolute requirements and you should take a serious look at the tutorial linked above.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

public class TableEdit {

    public static void main(String[] args) {
        new TableEdit();
    }

    public TableEdit() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new BorderLayout());
            JTable table = new JTable(new MyTableModel());
            table.setSurrendersFocusOnKeystroke(true);
            TableColumnModel model = table.getColumnModel();
            model.getColumn(1).setCellRenderer(new MyTableCellRenderer());
            add(new JScrollPane(table));
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }
    }

    public class MyData {

        private String key;
        private String value;
        private boolean changed;

        public MyData(String key, String value) {
            this.key = key;
            this.value = value;
            this.changed = false;
        }

        public String getKey() {
            return key;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String newValue) {
            if (value == null ? newValue != null : !value.equals(newValue)) {
                value = newValue;
                changed = true;
            }
        }

        public boolean hasChanged() {
            return changed;
        }
    }

    public class MyTableModel extends AbstractTableModel {

        private List<MyData> data;

        public MyTableModel() {
            data = new ArrayList<>(25);
            for (int index = 0; index < 5; index++) {
                data.add(new MyData("A" + (index + 1), "B" + (index + 1)));
            }
        }

        @Override
        public int getRowCount() {
            return data.size();
        }

        @Override
        public int getColumnCount() {
            return 2;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            MyData myData = data.get(rowIndex);
            Object value = null;
            switch (columnIndex) {
                case 0:
                    value = myData.getKey();
                    break;
                case 1:
                    value = myData.getValue();
                    break;
            }
            return value;
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return String.class;
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return columnIndex == 1;
        }

        public boolean hasChanged(int rowIndex) {
            MyData myData = data.get(rowIndex);
            return myData.hasChanged();
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            MyData myData = data.get(rowIndex);
            myData.setValue(aValue == null ? null : aValue.toString());
        }
    }

    public class MyTableCellRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            setOpaque(isSelected);
            TableModel model = table.getModel();
            if (model instanceof MyTableModel) {
                MyTableModel myModel = (MyTableModel) model;
                if (myModel.hasChanged(row)) {
                    if (!isSelected) {
                        setBackground(Color.RED);
                        setOpaque(true);
                    } 
                }
            }
            return this;
        }
    }
}

这篇关于JTable valuechanged,然后更改单元格颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆