更改JTable的选择行为以仅选择行或列中可变数量的单元格 [英] Alter selection behavior for a JTable to only select a variable number of cells in a row or column
问题描述
我有一个JTable,可以在其中启用行或列选择之间进行更改.此功能效果很好,但我希望能够确定在当前所选单元格旁边突出显示的单元格数量.当前,选择整个行或整个列.我试图添加一个ListSelectionModel来实现此功能,但它只允许选择整个行或整个列.以下是示例图片:
I have a JTable in which I alter between having row or column selection enabled. This feature works well but I want to be able to determine the number of cells which are highlighted adjacent to the currently selected cell. Currently, either the entire row or column is selected. I have tried to add a ListSelectionModel to implement this functionality but it only allows for either an entire row or column to be selected. Here are example images:
和
ADJACENTSELECTION默认情况下设置为2,所以我想在启用rowSelection时突出显示所选单元格左右两侧的2个单元格,或者当rowSelection为false时突出显示所选单元格上下的2个单元格.任何帮助将不胜感激.这是我的代码:
ADJACENTSELECTION is by default set to two so I'd like to highlight the 2 cells to the right and left of the selected cell when rowSelection is enabled or 2 cells above and below the selected cell when rowSelection is false. Any help would be greatly appreciated. Here is my code:
package selectionTest;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.border.Border;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
public class App {
private void display() {
JFrame f = new JFrame("Demo");
JPanel gui = new JPanel(new BorderLayout());
GridTable gridTable = new GridTable(25, 25);
gui.add(gridTable, BorderLayout.CENTER);
f.add(gui);
f.setBackground(Color.BLUE);
gui.setBackground(Color.WHITE);
f.setLocationByPlatform(true);
f.pack();
f.setSize(500, 600);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new App().display();
}
});
}
}
class GridTable extends JTable {
static int ADJACENTSELECTION = 2;
boolean rowSelection = false;
int rows, cols;
public GridTable(int rows, int cols) {
this.rows = rows;
this.cols = cols;
this.setModel(new DefaultTableModel(rows, cols));
this.setShowGrid(true);
Border blackline = BorderFactory.createLineBorder(Color.black);
this.setBorder(blackline);
this.setGridColor(Color.black);
ActionMap map = this.getActionMap();
Action action = switchOrientation();
String keyStrokeAndKey = "control O";
KeyStroke keyStroke = KeyStroke.getKeyStroke(keyStrokeAndKey);
this.getInputMap().put(keyStroke, keyStrokeAndKey);
this.getActionMap().put(keyStrokeAndKey, action);
this.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent event) {
int row = getSelectedRow();
int column = getSelectedColumn();
if (rowSelection) {
setRowSelectionInterval(Math.max(0, row - ADJACENTSELECTION), Math.min(row, row + ADJACENTSELECTION));
} else {
setColumnSelectionInterval(Math.max(0, column - ADJACENTSELECTION), Math.min(column, column + ADJACENTSELECTION));
}
}
});
}
private AbstractAction switchOrientation() {
AbstractAction switchOrientation = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
rowSelection = !rowSelection;
setColumnSelectionAllowed(rowSelection);
setRowSelectionAllowed(!rowSelection);
}
};
return switchOrientation;
}
}
推荐答案
您已经快到了,只需执行几个额外的步骤,就可以更新选择侦听器以仅突出显示特定的单元格:
You are almost there, just a couple of extra steps and you can update the selection listener to only highlight specific cells:
-
通过在
GridTable
方法中添加this.setCellSelectionEnabled(true);
允许选择特定的单元格:
Allow for selection of specific cells by adding
this.setCellSelectionEnabled(true);
to yourGridTable
method:
public GridTable(int rows, int cols) {
this.setCellSelectionEnabled(true);
//...
确保SelectionInterval
范围/值正确:
make sure that the SelectionInterval
ranges/values are correct:
if (rowSelection == true){
//Correct using `getRowCount()` for selection range
setRowSelectionInterval(Math.max(0, row - ADJACENTSELECTION), Math.min(getRowCount()-1, row + ADJACENTSELECTION));
}
else{
//Correct using `getColumnCount()` for selection range
setColumnSelectionInterval(Math.max(0, column - ADJACENTSELECTION), Math.min(getColumnCount()-1, column + ADJACENTSELECTION));
}
确保在更新选择时不会触发选择事件再次发生.您可以通过使用布尔值来跟踪选择事件来做到这一点:
Make sure that when you update the selection that it does not trigger the selection event to happen again. You can do this by using a boolean to track the selection event:
this.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
//Use this to track changes
boolean initial = true;
//...
public void valueChanged(ListSelectionEvent e){
if (initial){
int column = getSelectedColumn();
int row = getSelectedRow();
//...
最后,将它们放在一起,这是全选侦听器(并且不要忘记将this.setCellSelectionEnabled(true);
添加到GridTable中):
Finally, putting it all together, this is the full selection listener (And don't forget to add this.setCellSelectionEnabled(true);
to GridTable):
this.getSelectionModel().addListSelectionListener(new ListSelectionListener(){
//Use this to track changes
boolean initial = true;
public void valueChanged(ListSelectionEvent e){
//Only change value on first select (This prevents the below from triggering itself)
if (initial){
int column = getSelectedColumn();
int row = getSelectedRow();
initial = false;
if (rowSelection == true){
setRowSelectionInterval(Math.max(0, row - ADJACENTSELECTION), Math.min(getRowCount()-1, row + ADJACENTSELECTION));
}
else{
setColumnSelectionInterval(Math.max(0, column - ADJACENTSELECTION), Math.min(getColumnCount()-1, column + ADJACENTSELECTION));
}
}
//Set the value back once a selection is complete
else{
initial = true;
}
}
});
这将突出显示选定的单元格,并在选择的两侧显示两个单元格
This will highlight the selected cell, and two cells either side of the selection
这篇关于更改JTable的选择行为以仅选择行或列中可变数量的单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!