JTable将数字排序为字符串。

huangapple go评论108阅读模式
英文:

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&lt;CustomModelTable&gt;(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 &lt; this.getColumnCount()) {
String name = getColumnName(columnIndex); //This just gets the header of the column
name = name.toLowerCase();
switch (name) {
case &quot;int&quot;:
case &quot;int[]&quot;:
case &quot;n&#250;m.&quot;:
case &quot;int[][]&quot;: return Integer.class; //Or Class.forName(&quot;java.lang.Integer&quot;);
case &quot;byte&quot;:
case &quot;byte[]&quot;:
case &quot;byte[][]&quot;: return Class.forName(&quot;java.lang.Byte&quot;);
case &quot;long&quot;:
case &quot;long[]&quot;:
case &quot;long[][]&quot;: return Class.forName(&quot;java.lang.Long&quot;);
case &quot;float&quot;:
case &quot;float[]&quot;:
case &quot;float[][]&quot;: return Class.forName(&quot;java.lang.Float&quot;);
case &quot;double&quot;:
case &quot;double[]&quot;:
case &quot;double[][]&quot;: return Class.forName(&quot;java.lang.Double&quot;);
case &quot;boolean&quot;:
case &quot;boolean[]&quot;:
case &quot;boolean[][]&quot;: return Class.forName(&quot;java.lang.Boolean&quot;);
case &quot;char&quot;:
case &quot;char[]&quot;:
case &quot;char[][]&quot;: return Class.forName(&quot;java.lang.Character&quot;);
case &quot;string&quot;:
case &quot;string[]&quot;:
case &quot;string[][]&quot;: return Class.forName(&quot;java.lang.String&quot;);
default: return Class.forName(&quot;java.lang.String&quot;);
}
}
} 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 &lt; 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&lt;Integer&gt; columnIndicesWithNumbers = Arrays.asList(0);
@Override
public Class&lt;?&gt; 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(() -&gt; {
DefaultTableModel dm = new CustomTableModel();
dm.addColumn(&quot;Integers&quot;);
dm.addColumn(&quot;Strings&quot;);
//@formatter:off 
Object[][] data = { 
{ 1, &quot;Something&quot; }, { 102, &quot;Something Else&quot; }, 
{ 55, &quot;Something&quot; }, { 66, &quot;Something&quot; },
{ 1000, &quot;Something&quot; }, { 1524, &quot;Something&quot; }, 
{ 5801, &quot;Something&quot; }, { -55, &quot;Something&quot; },};
//@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&lt;Integer&gt; columnIndicesWithNumbers = Arrays.asList(0);
@Override
public Class&lt;?&gt; getColumnClass(int columnIndex) {
if (columnIndicesWithNumbers.contains(columnIndex))
return Double.class;
return super.getColumnClass(columnIndex);
}
}
}

Preview:

JTable将数字排序为字符串。

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(() -&gt; {
DefaultTableModel dm = new CustomTableModel();
dm.addColumn(&quot;Integers&quot;);
dm.addColumn(&quot;Strings&quot;);
//@formatter:off 
Object[][] data = { 
{ &quot;1&quot;, &quot;Something&quot; }, { &quot;102&quot;, &quot;Something Else&quot; }, 
{ &quot;55&quot;, &quot;Something&quot; }, { &quot;66&quot;, &quot;Something&quot; },
{ &quot;1000&quot;, &quot;Something&quot; }, { &quot;1524&quot;, &quot;Something&quot; }, 
{ &quot;5801&quot;, &quot;Something&quot; }, { &quot;-55&quot;, &quot;Something&quot; },};
//@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&lt;Integer&gt; 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&lt;?&gt; 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.

huangapple
  • 本文由 发表于 2020年8月14日 19:20:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/63411789.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定