TableModel: Wo werden die RowSorter gespeichert?

Ich bin gerade nicht sicher, ob du das, was ich gepostet hatte, mal gestartet hast. Aber es berücksichtigt auch die „historie“ (außer, wenn du die gerade umgekehrt berücksichtigen willst). Das volle Beispiel unter CommonUI/src/test/java/de/javagl/common/ui/table/test/TableSortingTest.java at master · javagl/CommonUI · GitHub zeigt sogar die schönen Header für die „historischen“ Sprtierkriterien. (Ist dir eigentlich aufgefallen, dass man bei sowas normalerweise nie Arrays.sort aufrufen muss?)

(EDIT: Nur aus Neugier hab’ ich gerade mal geschaut: Wenn man das ganze startet, wurde schon 383 mal sort aufgerufen, und bei jedem Sprtieren kommen nochmal genausoviele Aufrufe dazu. Schreib’ doch mal JavaDocs an die Methoden, bin gespannt, was da drin stehen würde…)

Und wie oft wurde effektiv sortiert?

Es geht ja darum, dass die Tabellendaten Einheiten-Postfixes haben.

1 „Gefällt mir“

Nun. Auch wenn ich gerade das Gefühl habe, dass du mich durch gespielte Dummheit dazu überlistest, hier mehr Zeit zu verschwenden, als das ganze wert ist, muss ich immernoch die Möglichkeit in Betracht ziehen, dass da nichts gespielt ist. Dass trotzdem jegliche Interaktion mit dir komplette Zeitverschwendung ist, ist davon nochmal unabhängig. Manchmal ist ja „egal“ ob man ein bißchen Zeit verschwendet. Und dass ich mich wiederhole, ist auch nicht schlimm. In dem geposteten Code sind auch einige Wiederholungen. Und manchmal ist ja „egal“, ob man ein bißchen Zeit verschwendet. Und es ist manchmal auch nicht schlimm, wenn man sich wiederholt. Das ist zwar manchmal Zeitverschwendung, aber manchmal ist ein bißchen Zeitverschwendung ja nicht schlimm. Und wenn du das so liest, und dir denkst "Ja, was soll das Gelaber mit den ganzen Wiederholungen? Das zu lesen ist Zeitverschwendung! :angry: " dann denke immer daran: Manchmal sind Wiederholungen nicht schlimm, und manchmal ist es auch nicht schlimm, wenn man ein bißchen Zeit verschwendet.

:exclamation: Dein kompletter Ansatz ist FALSCH :exclamation:

Ja, ich könnte Kritik auf allen Ebenen üben. Aber wenn ich „ganz oben“ anfangen soll, dann muss es eben diese Ebene sein. Dein kompletter Ansatz ist von vorne bis hinten unsinnig und falsch (und der ganze Quäl-Kot, mit dem du uns hier belästigst, ist zumindest teilweise darauf zurückzuführen).

Das Modell speichert die Daten. Die Daten sind nicht 739.6MiB oder 1.72% - auch wenn das das ist, was zufällig von irgendeinem Kommando auf der Konsole ausgegeben wird. Die Daten sind 775526809 oder 0.0172. Ja, wenn du die „alte“ Darstellung dann haben willst, brauchst du einen eigenen TableCellRenderer, aber den kann man recht generisch (und wiederverwendbar) implementieren.

Genau darum geht. So einen Ansatz finde ich falsch und 10-mal aufwändiger.

Ja, was du „findest“ ist halt wurscht. Daumen drücken, dass

  • docker stats nie „schlau“ wird und die Ausgabe von der Sprache des Systems abgängig macht, und du dann auf einmal 1,23% dort stehen hast
  • niemand dieses Programm benutzt, und genau fordert, dass die Ausgabe mit Kommas angezeigt werden soll
  • Niemand einen breakpoint in sort setzt, und dann die Fenstergrößde ändert…
  • Nie wieder irgendjemand irgendwas an diesem Code ändern muss

Die Frage nach dem „Benutzen“ und „ändern“ stellen sich aber nicht. Ich weiß, wie entspannend es sein kann, wenn man Code schreiben kann, bei dem man keinen Anspruch an sich selbst haben und praktisch direkt in die Mülltonne coden kann.

1 „Gefällt mir“

Ich meine das aber ernst. Lass doch mal die Sticheleien weg. Die Ausgabe von docker stats ist immer gleich, und mit deinem Vorschlag würde man die Daten zweimal halten. Deshalb möchte ich bei meinem Ansatz bleiben, weil dieser nicht schlecht ist (imho).

… Oder du würdest sagen, dass es ganz einfach ist, mehrere Renderer zu schreiben.

„Daten doppelt“ … „Mehrere Renderer“ … *seufz*

package bytewelt.cb;

import java.awt.BorderLayout;
import java.awt.Component;
import java.text.NumberFormat;
import java.util.Locale;
import java.util.function.Function;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;

public class ExampleRenderer
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGUI());
    }

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Object data[][] =
        {
            { 123, 0.123 },
            { 1234, 0.234 },
            { 12345, 0.345, },
            { 123456, 0.456 },
            { 1234567, 0.567 }, };
        Object[] columnNames =
        { "A", "B" };
        TableModel tableModel = new DefaultTableModel(data, columnNames);

        JTable table = new JTable(tableModel);
        table.getColumn("A").setCellRenderer(createBinary());
        table.getColumn("B").setCellRenderer(createPercent());

        f.getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);

        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static TableCellRenderer createPercent()
    {
        return create(ExampleRenderer::formatPercent);
    }

    private static TableCellRenderer createBinary()
    {
        return create(ExampleRenderer::formatBinary);
    }

    private static String formatPercent(Number n)
    {
        NumberFormat formatter =
            NumberFormat.getPercentInstance(Locale.ENGLISH);
        formatter.setMinimumFractionDigits(0);
        formatter.setMaximumFractionDigits(2);
        return formatter.format(n.doubleValue());
    }

    private static String formatBinary(Number n)
    {
        NumberFormat formatter = NumberFormat.getInstance(Locale.ENGLISH);
        formatter.setMinimumFractionDigits(0);
        formatter.setMaximumFractionDigits(2);
        String suffixes[] = new String[]
        { "", "KiB", "MiB", "GiB" };
        double current = n.doubleValue();
        for (int i = 0; i < suffixes.length; i++)
        {
            if (current < 1024)
            {
                return formatter.format(current) + " " + suffixes[i];
            }
            current /= 1024;
        }
        return formatter.format(current);
    }

    private static TableCellRenderer
        create(Function<? super Number, ? extends String> formatter)
    {
        return new DefaultTableCellRenderer()
        {
            @Override
            public Component getTableCellRendererComponent(JTable table,
                Object value, boolean isSelected, boolean hasFocus, int row,
                int column)
            {
                super.getTableCellRendererComponent(table, value, isSelected,
                    hasFocus, row, column);
                setText(formatter.apply((Number) value));
                return this;
            }
        };
    }
}

Und jetzt ein kleines Spielchen: WIr schreiben beide mal eine Funktion, die die Summen und Durchschnittswerte aller Spalten anzeigt (meinetwegen nur auf der Konsole ausgegeben).

Auf die Plätze… fertig… (bei mir: zwei Minuten. Drei vielleicht…)

Das ist aber nur die halbe Miete. Es fehlt:

  • Parsen,
  • Renderer für String und ggf. Long,
  • das Suffix B für Byte oder „“ für nicht Byte-Werte.

Ich schreibe gleich mal ein Hybrid-Modell, dass die Rohdaten und formatieren Daten hält. Zusammen mit einem sehr einfachen Renderer sollte dann ein Custom-Sorter auch entfallen.

Das wäre doch das nächste Problem, wie bringst das in der Tabelle unter?

Die fast schon wieder amüsante Mischung aus Naivität und Dreistigkeit überrascht mich nicht. Du rotzt hier irgendwelchen Dreckscode ins Forum, ich kritisiere einen Punkt, und zeige, wie man es besser machen kann, und du beschwerst dich, dass ich dir nicht deine komplette Anwendung sauber neugeschrieben habe. („Terabytes fehlen da auch noch!!!111einseinself“).

Woraus besteht die Tabelle? Aus Zahlen. Die kann man sortieren und meinetwegen bunt machen

Gar nicht. Hat da nichts zu suchen.

1 „Gefällt mir“

Was stimmt mit dir nicht, Medikamente vielleicht nicht genommen? Wenn nicht, solltest du das untersuchen lassen…

Eine Verbesserung muss vor allem eins sein: besser. Ansonsten ist es keine Verbesserung.

So, jetzt noch viel Spaß mit Martin hier.^^

Nenn’ vielleicht mal Argumente. Z.B. warum du die Daten sortierst. Ein RowSorter sortiert nicht die Daten, sondern ermöglicht eine sortierte Sicht auf die Daten. Also, was machst du richtig, was jeder andere Entwickler falsch macht?

Verwende brain.exe. :smiley:

Das stimmt nicht. Ein RowSorter macht das, was der Name sagt, nur normalerweise implementiert meinen keinen eigenen, sondern nimmt schon vor-implementierte Klassen.

Hatten wir doch schon … weil eine normale Sortierung hier nicht reicht.

Jetzt habe ich mich doch verleiten lassen, zu antworten.

Ach, ich hab’ heute mal einen geduldigen Tag.

Die Daten sind so, wie sie sind. Sie stehen in einer bestimmten Reihenfolge im Modell. Der RowSorter verändert diese Reihenfolge nicht. Er bewirkt nur, dass die Zeilen in einer nach verschiedenen Kriterien sortierten Reihenfolge angezeigt werden. Der RowSorter sortiert nicht die Daten. Er sortiert die Sicht auf die Daten.

weil eine normale Sortierung hier nicht reicht.

Beschreib’ mal technisch (meinetwegen sogar mit Formeln) den Unterschied zwischen einer „normalen“ Sortierung und einer „nicht-normalen“ Sortierung. Das Standardverhalten einer sortierten JTable ist schon, dass die „Historie“ berücksichtigt wird (man könnte höchstens über die Reihenfolge streiten). Und wenn man einen passenden Renderer für den Header verwendet, sieht man auch die primären, sekundären, und tertiären Sortierkriterien. Wie in dem Test aus CommonUI:

TableSorting

Zuerst wird nach „B“ sortiert. Dann nach „C“. Dabei wird „B“ als sekundäres Kriterium beibehalten (d.h. immer wenn „C“ gleiche Werte hat, wird nach „B“ sortiert). Dann wird die Reihenfolge für „C“ umgedreht. Dabei bleibt „B“ als sekundäres Kriterium beibehalten (d.h. immer wenn „C“ gleiche Werte hat, wird nach „B“ sortiert).

Bisher hast du nichts gesagt, was den Murx, den du da verzapfst, auf einer technischen Ebene rechtfertigen würde.

2 „Gefällt mir“

Danke, dass dein Ton wieder freundlicher geworden ist.

Nein, ich möchte jetzt kein formales Pflichtenheft, das die funktionalen Anforderungen genau definiert, schreiben, zumal ich glaube, dass du mich eigentlich bereits richtig verstanden hast, und also schon weißt, worum es geht, und evtl. den „sticking point“ schon kennst.

Außerdem habe ich heute Kopfschmerzen. :weary:

Bezieht sich das jetzt auf das, was ich oben geschrieben hatte…

?

Dein Ansatz ist unsinnig. Dein Code ist schlecht. Du hast keine Begründung, für das, was du tust.

1 „Gefällt mir“

Kurze Rückfrage: Oben in der Animation klickst du erst auf B, dann auf C, und die Sortierungsrichtungspfeilchen (v und ^) bleiben in beiden Spalten erhalten. Ist das nur ein Darstellungsfehler von deinem GIF-Generator?

Bei mir ist das nicht so.

ds09

Wieder nur eine Frage der Darstellung. Die Sortierkriterien (im Sinne der „SortKeys“) bleiben erhalten. In der Standard-Impementierung des JTable-Header-Renderers werden sie nur nicht angezeigt. Im Test, mit dem das GIF erstellt wurde, wird ein SortOrderTableHeaderCellRenderer verwendet. Der zeigt sie halt an.

1 „Gefällt mir“

Danke für die Erklärung!

Eine kleine 1 2 3 usw. an den Sortierrichtungen wäre cool… Ist das machbar/vorstellbar?

Ja