java 带有单元格选择和多区间选择的 JTable 显示不正确的选择
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15568131/
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 with cell selection and multiple interval selection shows incorrect selection
提问by Anthony
I'd like to have a table where people can freely select cells.
我想要一个表格,人们可以在其中自由选择单元格。
For this I've used the ListSelectionModel.MULTIPLE_INTERVAL_SELECTION and table.setCellSelectionEnabled(true).
为此,我使用了 ListSelectionModel.MULTIPLE_INTERVAL_SELECTION 和table.setCellSelectionEnabled(true)。
I have 2 problems:
我有两个问题:
- The method table.addRowSelectionIntervaldoesn't select any cells
- If you select 2 blocks, the cells having the same rows and columns selected are also selected. e.g. select B2-D4 and then F7. This will also select B7-D7 and F2-F4.
- 方法table.addRowSelectionInterval不选择任何单元格
- 如果选择 2 个块,则同时选择具有相同行和列的单元格。例如选择 B2-D4 然后 F7。这也将选择 B7-D7 和 F2-F4。
Here is the program to reproduce these problems:
这是重现这些问题的程序:
import java.awt.BorderLayout;
import javax.swing.*;
public class JTableCellSelection {
public static void showDemo(JComponent demo, String title) {
JFrame mainFrame = new JFrame();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setTitle(title);
JPanel contentPanel = new JPanel(new BorderLayout());
contentPanel.add(demo);
mainFrame.add(contentPanel);
mainFrame.pack();
mainFrame.setVisible(true);
}
public static void main(String[] args) {
JTable table = new JTable(10, 10);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setCellSelectionEnabled(true);
table.addRowSelectionInterval(6, 7); // Select 2 lines
showDemo(new JScrollPane(table), "Select a block and some rows");
}
}
It feels like I will have to check the selection by myself and not rely on the isSelected of the table cell renderer.
感觉我必须自己检查选择,而不是依赖表格单元格渲染器的 isSelected 。
回答by Anthony
So I've implemented it in the JTable.
所以我已经在 JTable 中实现了它。
Note that there are several drawbacks to this solution:
请注意,此解决方案有几个缺点:
- You cannot use the table.getListSelectionModelto select rows, you need to call table.addRowSelectionInterval
- trying to select another column next to a selected block will unselect the rows
- I haven't tested column selection but my guess is that it wouldn't work
- changing direction when selecting block does not work always
- 您不能使用table.getListSelectionModel来选择行,您需要调用table.addRowSelectionInterval
- 尝试选择所选块旁边的另一列将取消选择行
- 我还没有测试过列选择,但我的猜测是它不起作用
- 选择块时改变方向并不总是有效
but for the rest it does pretty much what I wanted
但对于其余的它几乎是我想要的
/*
* Copyright 2013 Japplis.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.awt.Point;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.swing.JTable;
import javax.swing.table.TableModel;
/**
* The JTable used to display data.
* This class is only to fix bugs or improve existing functionalities.
*
* @author Anthony Goubard - Japplis
*/
public class SheetTable extends JTable {
private Map<Integer, Set<Integer>> selectedCells = new HashMap<>();
private Point firstExtendCell;
public SheetTable(TableModel tableModel) {
super(tableModel);
}
@Override
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
if (toggle && isCellSelected(rowIndex, columnIndex) && !extend) {
selectedCells.get(rowIndex).remove(columnIndex);
} else {
if (!toggle && !extend) {
selectedCells.clear();
}
Set<Integer> selectedColumns = selectedCells.get(rowIndex);
if (selectedColumns == null) {
selectedColumns = new TreeSet<>();
selectedCells.put(rowIndex, selectedColumns);
}
selectedColumns.add(columnIndex);
if (!extend) {
firstExtendCell = new Point(rowIndex, columnIndex);
} else {
for (int i = Math.min(firstExtendCell.x, rowIndex); i <= Math.max(firstExtendCell.x, rowIndex); i++) {
for (int j = Math.min(firstExtendCell.y, columnIndex); j <= Math.max(firstExtendCell.y, columnIndex); j++) {
selectedCells.get(i).add(j);
}
}
}
}
super.changeSelection(rowIndex, columnIndex, toggle, extend);
}
@Override
public void addRowSelectionInterval(int index0, int index1) {
for (int i = index0; i < index1; i++) {
selectedCells.remove(i);
}
super.addRowSelectionInterval(index0, index1);
}
@Override
public void removeRowSelectionInterval(int index0, int index1) {
for (int i = index0; i < index1; i++) {
selectedCells.remove(i);
}
super.removeRowSelectionInterval(index0, index1);
}
@Override
public void selectAll() {
selectedCells.clear();
super.selectAll();
}
@Override
public void clearSelection() {
if (selectedCells != null) {
selectedCells.clear();
}
super.clearSelection();
}
@Override
public boolean isCellSelected(int row, int column) {
if (!getSelectionModel().isSelectedIndex(row)) {
return false;
}
if (getSelectionModel().isSelectedIndex(row) && selectedCells.get(row) == null) {
return true;
}
return selectedCells.get(row).contains(column);
}
}
The last version is in Joeffice Mercurial repository on bitbucket.org
最后一个版本位于bitbucket.org上的 Joeffice Mercurial 存储库中
回答by RGO
I did some experiments and also read the documentation here. It says the setCellSelectionEnabled()
method:
我做了一些实验,还阅读了此处的文档。它说的setCellSelectionEnabled()
方法:
Sets whether this table allows both a column selection and a row selection to exist simultaneously. When set, the table treats the intersection of the row and column selection models as the selected cells.
设置此表是否允许列选择和行选择同时存在。设置后,表格将行和列选择模型的交集视为选定的单元格。
I added two lines of code for the debugging purpose immediately before showDemo()
to see what the selected rows and columns are after adding the rows interval:
我在之前添加了两行代码用于调试目的,showDemo()
以查看添加行间隔后选定的行和列是什么:
public static void main(String[] args) {
JTable table = new JTable(10, 10);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setCellSelectionEnabled(true);
table.addRowSelectionInterval(6, 7); // Select 2 lines
// Let's see what rows and columns have been selected
System.out.println("Rows: " + Arrays.toString(table.getSelectedRows()));
System.out.print("Columns: " + Arrays.toString(table.getSelectedColumns()));
showDemo(new JScrollPane(table), "Select a block and some rows");
}
and I got this output:
我得到了这个输出:
Rows: [6, 7]
Columns: []
which explains why addRowSelectionInterval
doesn't work as you expected. It's easy to add the missing part:
这解释了为什么addRowSelectionInterval
不能按预期工作。添加缺失的部分很容易:
...
table.addRowSelectionInterval(6, 7); // Select 2 lines
table.addColumnSelectionInterval(0, 9); // and Select ** ALL** the columns
...
Similar justification could be made for the other observation.
可以为其他观察做出类似的证明。