英文:
JTable keeps sorting numbers as Strings
问题
我想要正确地对比正确的类别来对表格进行排序,而不是字符串。
我正在使用一个 TableRowSorter:
TableRowSorter sorter = new TableRowSorter<CustomModelTable>(modelData);
tablaEJ.setRowSorter(sorter);
我在 CustomModelTable 中重写了 getColumnClass 方法,以便根据列名获取正确的类别(这是因为类型是以编程方式定义的):
@Override
public Class getColumnClass(int columnIndex)
{
try {
if (columnIndex < this.getColumnCount()) {
String name = getColumnName(columnIndex); //这只是获取列的标题
name = name.toLowerCase();
switch (name) {
case "int":
case "int[]":
case "núm.":
case "int[][]": return Integer.class; //或 Class.forName("java.lang.Integer");
case "byte":
case "byte[]":
case "byte[][]": return Class.forName("java.lang.Byte");
case "long":
case "long[]":
case "long[][]": return Class.forName("java.lang.Long");
case "float":
case "float[]":
case "float[][]": return Class.forName("java.lang.Float");
case "double":
case "double[]":
case "double[][]": return Class.forName("java.lang.Double");
case "boolean":
case "boolean[]":
case "boolean[][]": return Class.forName("java.lang.Boolean");
case "char":
case "char[]":
case "char[][]": return Class.forName("java.lang.Character");
case "string":
case "string[]":
case "string[][]": return Class.forName("java.lang.String");
default: return Class.forName("java.lang.String");
}
}
} catch (Exception e){
}
return null;
}
这里是一个截图:
Table wrongly sorted
最奇怪的是,我打印了类型:
for (int i = 0; i < tablaEJ.getModel().getColumnCount(); i++) {
System.out.println(tablaEJ.getModel().getColumnClass(i));
}
它返回了预期的输出(与上表的打印结果相同):
class java.lang.Integer
class java.lang.Integer
class java.lang.Integer
class java.lang.Integer
老实说,我不知道我做错了什么。
英文:
I want to sort the table correctly comparing the correct classes, not strings.
I'm using a TableRowSorter:
TableRowSorter sorter = new TableRowSorter<CustomModelTable>(modelData);
tablaEJ.setRowSorter(sorter);
I overrided the method getColumnClass in CustomModelTable so I get the correct class depending on the column's name (this was made because types are defined programatically):
@Override
public Class getColumnClass(int columnIndex)
{
try {
if (columnIndex < this.getColumnCount()) {
String name = getColumnName(columnIndex); //This just gets the header of the column
name = name.toLowerCase();
switch (name) {
case "int":
case "int[]":
case "núm.":
case "int[][]": return Integer.class; //Or Class.forName("java.lang.Integer");
case "byte":
case "byte[]":
case "byte[][]": return Class.forName("java.lang.Byte");
case "long":
case "long[]":
case "long[][]": return Class.forName("java.lang.Long");
case "float":
case "float[]":
case "float[][]": return Class.forName("java.lang.Float");
case "double":
case "double[]":
case "double[][]": return Class.forName("java.lang.Double");
case "boolean":
case "boolean[]":
case "boolean[][]": return Class.forName("java.lang.Boolean");
case "char":
case "char[]":
case "char[][]": return Class.forName("java.lang.Character");
case "string":
case "string[]":
case "string[][]": return Class.forName("java.lang.String");
default: return Class.forName("java.lang.String");
}
}
} catch (Exception e){
}
return null;
}
Here's an screenshot:
Table wrongly sorted
The most curious thing is that I print the types:
for (int i = 0; i < tablaEJ.getModel().getColumnCount(); i++) {
System.out.println(tablaEJ.getModel().getColumnClass(i));
}
And it returns the expected output (print of the above table):
class java.lang.Integer
class java.lang.Integer
class java.lang.Integer
class java.lang.Integer
Honestly, I don't know what I'm doing wrong.
答案1
得分: 2
Sure, here's the translated code portion:
public static class CustomTableModel extends DefaultTableModel {
private final List<Integer> columnIndicesWithNumbers = Arrays.asList(0);
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndicesWithNumbers.contains(columnIndex))
return Double.class;
return super.getColumnClass(columnIndex);
}
}
public class SorterTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
DefaultTableModel dm = new CustomTableModel();
dm.addColumn("Integers");
dm.addColumn("Strings");
//@formatter:off
Object[][] data = {
{ 1, "Something" }, { 102, "Something Else" },
{ 55, "Something" }, { 66, "Something" },
{ 1000, "Something" }, { 1524, "Something" },
{ 5801, "Something" }, { -55, "Something" },
};
//@formatter:on
for (Object[] row : data) {
dm.addRow(row);
}
JTable table = new JTable(dm);
table.setAutoCreateRowSorter(true);
JOptionPane.showMessageDialog(null, new JScrollPane(table));
});
}
public static class CustomTableModel extends DefaultTableModel {
private final List<Integer> columnIndicesWithNumbers = Arrays.asList(0);
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndicesWithNumbers.contains(columnIndex))
return Double.class;
return super.getColumnClass(columnIndex);
}
}
}
And after your clarifications in the comment section:
public class SorterTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
DefaultTableModel dm = new CustomTableModel();
dm.addColumn("Integers");
dm.addColumn("Strings");
//@formatter:off
Object[][] data = {
{ "1", "Something" }, { "102", "Something Else" },
{ "55", "Something" }, { "66", "Something" },
{ "1000", "Something" }, { "1524", "Something" },
{ "5801", "Something" }, { "-55", "Something" },
};
//@formatter:on
for (Object[] row : data) {
dm.addRow(row);
}
JTable table = new JTable(dm);
table.setAutoCreateRowSorter(true);
JOptionPane.showMessageDialog(null, new JScrollPane(table));
});
}
public static class CustomTableModel extends DefaultTableModel {
private final List<Integer> columnIndicesWithNumbers = Arrays.asList(0);
@Override
public Object getValueAt(int row, int column) {
Object value = super.getValueAt(row, column);
if (columnIndicesWithNumbers.contains(column)) {
return Double.parseDouble(String.valueOf(value));
}
return value;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndicesWithNumbers.contains(columnIndex))
return Double.class;
return super.getColumnClass(columnIndex);
}
}
}
英文:
The "safe" way is to declare which column indices are numbers:
public static class CustomTableModel extends DefaultTableModel {
private final List<Integer> columnIndicesWithNumbers = Arrays.asList(0);
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndicesWithNumbers.contains(columnIndex))
return Double.class;
return super.getColumnClass(columnIndex);
}
}
Here is a complete example to test yourself:
public class SorterTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
DefaultTableModel dm = new CustomTableModel();
dm.addColumn("Integers");
dm.addColumn("Strings");
//@formatter:off
Object[][] data = {
{ 1, "Something" }, { 102, "Something Else" },
{ 55, "Something" }, { 66, "Something" },
{ 1000, "Something" }, { 1524, "Something" },
{ 5801, "Something" }, { -55, "Something" },};
//@formatter:on
for (Object[] row : data) {
dm.addRow(row);
}
JTable table = new JTable(dm);
table.setAutoCreateRowSorter(true);
JOptionPane.showMessageDialog(null, new JScrollPane(table));
});
}
public static class CustomTableModel extends DefaultTableModel {
private final List<Integer> columnIndicesWithNumbers = Arrays.asList(0);
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndicesWithNumbers.contains(columnIndex))
return Double.class;
return super.getColumnClass(columnIndex);
}
}
}
Preview:
After your clarifications in the comment section:
You can @Override
getValueAt
method in order to return integers instead of strings.
Full example:
public class SorterTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
DefaultTableModel dm = new CustomTableModel();
dm.addColumn("Integers");
dm.addColumn("Strings");
//@formatter:off
Object[][] data = {
{ "1", "Something" }, { "102", "Something Else" },
{ "55", "Something" }, { "66", "Something" },
{ "1000", "Something" }, { "1524", "Something" },
{ "5801", "Something" }, { "-55", "Something" },};
//@formatter:on
for (Object[] row : data) {
dm.addRow(row);
}
JTable table = new JTable(dm);
table.setAutoCreateRowSorter(true);
JOptionPane.showMessageDialog(null, new JScrollPane(table));
});
}
public static class CustomTableModel extends DefaultTableModel {
private final List<Integer> columnIndicesWithNumbers = Arrays.asList(0);
@Override
public Object getValueAt(int row, int column) {
Object value = super.getValueAt(row, column);
if (columnIndicesWithNumbers.contains(column)) {
return Double.parseDouble(String.valueOf(value));
}
return value;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndicesWithNumbers.contains(columnIndex))
return Double.class;
return super.getColumnClass(columnIndex);
}
}
}
答案2
得分: 0
Sure, here's the translation:
我认为你不应该在那样做时转换类型。
在定义列时,你应该在设置任何内容之前实例化列的类型。
英文:
I think you shouldn't cast the types doing that.
When defining the columns, you should instantiate the type of column before setting anything in.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论