java JTable 在鼠标单击时更改单元格背景 - 释放后更改背景?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7262099/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JTable change cell background at mouse click - after release change background back?
提问by ayk
my question is, how to solve following problem:
我的问题是,如何解决以下问题:
If i click on a cell in a JTable, i want to change its background. If i release the mousebutton, i want the background change back to normal color.
如果我单击 JTable 中的一个单元格,我想更改其背景。如果我松开鼠标按钮,我希望背景变回正常颜色。
Is that possible?
那可能吗?
Greetings ayk
问候ayk
回答by kleopatra
For doing it in the visual realm you need
为了在视觉领域做到这一点,你需要
- a MouseListener which sets some state in cell-coordinates on pressed and resets that state on released
- a PropertyChangeListener listeneng to that state which repaints the cell on change
- a custom renderer which sets a custom background for the cell that is flagged
- 一个 MouseListener,它在按下时在单元格坐标中设置一些状态并在释放时重置该状态
- 一个 PropertyChangeListener 侦听在更改时重新绘制单元格的状态
- 一个自定义渲染器,它为被标记的单元格设置自定义背景
some code for the listeners
听众的一些代码
MouseListener l = new MouseAdapter() {
/**
* @inherited <p>
*/
@Override
public void mousePressed(MouseEvent e) {
JTable table = (JTable) e.getComponent();
int col = table.columnAtPoint(e.getPoint());
int row = table.rowAtPoint(e.getPoint());
if (col < 0 || row < 0) {
table.putClientProperty("pressedCell", null);
} else {
table.putClientProperty("pressedCell", new Point(col, row));
}
}
/**
* @inherited <p>
*/
@Override
public void mouseReleased(MouseEvent e) {
((JTable) e.getComponent()).putClientProperty("pressedCell", null);
}
};
table.addMouseListener(l);
PropertyChangeListener property = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
JTable table = (JTable) evt.getSource();
Point cell = evt.getNewValue() != null ?
(Point) evt.getNewValue() : (Point) evt.getOldValue();
if (cell != null) table.repaint(table.getCellRect(cell.y, cell.x, false));
}
};
table.addPropertyChangeListener("pressedCell", property);
Highlighting the cell in SwingX (cant resist :-)
在 SwingX 中突出显示单元格(无法抗拒:-)
HighlightPredicate predicate = new HighlightPredicate() {
@Override
public boolean isHighlighted(Component renderer, ComponentAdapter adapter) {
Point p = (Point) adapter.getComponent().getClientProperty("pressedCell");
return p != null && p.x == adapter.column && p.y == adapter.row;
}
};
table.addHighlighter(new ColorHighlighter(predicate, Color.YELLOW, null, Color.YELLOW, null));
For core Swing, either implement a custom TableCellRenderer or subclass the JTable and override prepareRenderer to set the background color according to the cell flag, as explained in Rob's Table Row Rendering
对于核心 Swing,实现自定义 TableCellRenderer 或子类化 JTable 并覆盖 prepareRenderer 以根据单元格标志设置背景颜色,如 Rob 的表行渲染中所述
回答by mKorbel
in your renderer you have to overide hasFocus
在您的渲染器中,您必须覆盖 hasFocus
for example
例如
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableRenderer extends JFrame {
private static final long serialVersionUID = 1L;
private JTable table;
private String[] columnNames = {"Date", "String", "Centered", "Integer", "Boolean"};
private Object[][] data = {
{new Date(), "A", "A", new Integer(1), true},
{new Date(), "B", "B", new Integer(2), false},
{new Date(), "C", "C", new Integer(10), null},
{new Date(), "D", "D", new Integer(4), false}
};
public TableRenderer() {
DefaultTableModel model = new DefaultTableModel(data, columnNames);
table = new JTable(model) {
private static final long serialVersionUID = 1L;
// Returning the Class of each column will allow different
// renderers to be used based on Class
@Override
public Class getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane);
// Override default renderer on a specific Class
TableCellRenderer colorRenderer = new ColorRenderer();
table.setDefaultRenderer(String.class, colorRenderer);
// Override default renderer for a specific column
DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
centerRenderer.setHorizontalAlignment(JLabel.CENTER);
table.getColumnModel().getColumn(2).setCellRenderer(centerRenderer);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
TableRenderer frame = new TableRenderer();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
/*
** Color the focused cell
*/
private class ColorRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1L;
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (hasFocus) {
setBackground(Color.cyan);
} else if (isSelected) {
setBackground(table.getSelectionBackground());
} else {
setBackground(table.getBackground());
}
return this;
}
}
}
回答by Heisenbug
Yes it is possible. Use a custom ListSelectionModeland set your JTable to use that : setSelectionModel().
对的,这是可能的。使用自定义ListSelectionModel并设置您的 JTable 以使用它:setSelectionModel()。
Here's an example.
这是一个例子。