JTable mit einem "close" -Button in der Spaltenüberschrift

8

Ich versuche, eine Tabelle mit benutzerdefinierten Spaltenüberschriften zu erstellen. Ich möchte, dass die Spaltenüberschriften eine Schaltfläche enthalten, auf die Benutzer klicken können. Die Funktion der Schaltfläche besteht darin, die Spalte aus der Tabelle zu entfernen. Im Wesentlichen versuche ich etwas wie dieses zu bauen.

Hier ist mein Code:

%Vor%

Wenn ich richtig verstehe, verwendet JTable standardmäßig ein JLabel, um Spaltenüberschriften zu rendern. Meine Idee ist es, eine benutzerdefinierte TableCellRenderer-Implementierung zu verwenden und meinen eigenen Spaltenkopf aus mehreren Komponenten zu erstellen, nämlich einem JPanel, der ein JLabel und ein JButton enthält. Ich baue und gebe das in getTableCellRendererComponent (...) -Funktion zurück.

Optisch funktioniert das. Das Problem ist, dass ich Mausklicks auf der Schaltfläche (oder auf dem Panel, das sie enthält) nicht erkennen kann. Das Hinzufügen eines MouseListener zur Schaltfläche funktioniert nicht. Das Ereignis erreicht es nie.

Ich habe mehrere ähnliche Dinge im Internet gefunden, aber sie erreichen nicht die Funktionalität, die ich brauche.

Zuerst gibt es ein Beispiel, wie man eine JCheckBox in den Header setzt, hier:

%Vor%

Das Problem dabei ist, dass der gesamte Header das Kontrollkästchen ist. Wenn Sie auf das Kontrollkästchen oder auf das zugehörige Label klicken, wird der gleiche Effekt erzielt. Daher ist es nicht möglich, die Spalte zu sortieren. Ich möchte es so einrichten, dass beim Klicken auf das Label die Spalte sortiert wird und durch Klicken auf die Schaltfläche "Schließen" die Spalte aus der Tabelle entfernt wird. Mit anderen Worten, der Header muss zwei getrennte Bereiche mit separaten Maus-Event-Handlern haben.

Ich habe hier ein anderes Beispiel gefunden:

%Vor%

Dazu werden JButtons in die Zellen der Tabelle platziert, dann Mausklicks auf die Tabelle selbst erkannt, die Spalte und Zeile berechnet, in der der Klick aufgetreten ist, und das Ereignis an die entsprechende Schaltfläche gesendet.

Das sind auch einige Probleme damit. Erstens befinden sich Schaltflächen in den Zellen, nicht in den Headern. Und zweitens ist dies wieder nur eine Komponente, nicht mehrere Komponenten in einem JPanel. Obwohl ich die Idee hatte, Ereignisse von diesem Beispiel zu versenden, kann ich es nicht für eine zusammengesetzte Komponente funktionieren lassen.

Ich habe einen anderen Ansatz versucht. Ich folgerte, dass, wenn ich die Koordinaten der Schließen-Knöpfe erhalten kann, ich dann, wenn ich die Koordinaten des Mausklicks kenne, berechnen kann, auf welchen Knopf geklickt wurde, und das Ereignis entsprechend absende. Ich habe mehrere Tests durchgeführt und festgestellt, dass die Komponenten in der Kopfzeile der Tabelle nicht auf dem Bildschirm angezeigt werden.

Ich habe meiner main (public) -Klasse eine statische JButton-Variable hinzugefügt und die Klasse, die TableCellRenderer implementiert, zu einer inneren Klasse der Hauptklasse gemacht. In getTableCellRendererComponent (...) weise ich vor der Rückgabe das JButton, das ich gerade erstellt habe, dieser statischen Variable zu. Auf diese Weise kann ich es sozusagen in den Griff bekommen. Dann versuchte ich in main, getX (), getY (), getWidth (), getHeight () und getLocationOnScreen () mit dieser statischen Variable zu erhalten. X, Y, Breite und Höhe geben alle Nullen zurück. GetLocationOnScreen () stürzt das Programm ab und sagt, dass die Komponente auf dem Bildschirm vorhanden sein muss, damit diese Funktion funktioniert.

Der Code dafür sieht ungefähr so ​​aus:

%Vor%

"class CustomColumnCellRenderer implementiert TableCellRenderer" wird zu einer inneren Klasse von CustomColumnHeadersTable. Dafür muss ich statische Variablen in CustomColumnCellRenderer aufgeben, also habe ich mich nicht mit Icons oder URLs oder ähnlichem beschäftigt. Anstelle einer Schaltfläche mit einem Symbol habe ich nur eine einfache Schaltfläche verwendet, die "BUTTON" ...

sagte

Als nächstes habe ich in getTableCellRendererComponent (...), kurz vor der return-Anweisung,

getan %Vor%

Und dann, in main (), habe ich es versucht:

%Vor%

Die Ausgabe sieht folgendermaßen aus:

%Vor%

Mit anderen Worten, der Button hat alle Dimensionen von 0, und nach Java ist er nicht wirklich auf dem Bildschirm (obwohl ich es sehen kann ...). Der Aufruf von getLocationOnScreen () stürzt das Programm ab.

Also, bitte helfen Sie, wenn Sie können. Vielleicht weiß jemand, wie man das macht. Vielleicht könnten Sie einfach einen anderen Ansatz vorschlagen. Oder, vielleicht weißt du, dass es überhaupt nicht möglich ist ...

Danke für Ihre Hilfe.

    
Aleksey 10.02.2011, 18:44
quelle

3 Antworten

2

Ja, ich war überrascht, als ich das erste Mal versucht habe, etwas Ähnliches zu tun, wie JButton s in ein JList zu setzen - es funktioniert nicht ganz, aus den von Ihnen angegebenen Gründen. Der richtige Weg, um das zu tun, was ich mit einem listähnlichen LayoutManager verwenden wollte, um das JButton s in eine Liste zu stellen.

In Ihrem Fall würde ich versuchen, eine Kombination aus JLabel s und MouseListeners zu verwenden, von der ich glaube, dass sie korrekt funktioniert. Wenn Sie einen JLabel als Kopfzeile verwenden, können Sie sowohl ein Bild als auch einen Text bereitstellen, und Sie können MouseListener für JLabel registrieren. Zugegeben, Sie erhalten nicht die gleichen visuellen Effekte wie beim Klicken auf JButton (d. H. Die Schaltfläche wird gedrückt), aber es wird die gleiche Funktionalität ermöglichen.

Eine andere Sache, auf die Sie achten sollten, ist die Verwendung von statischem JButton s (oder einem beliebigen JComponent ). Das Problem dabei ist, dass die Koordinaten von JButton in JButton selbst gespeichert werden, was bedeutet, dass Sie nicht dieselbe JButton an verschiedenen Stellen verwenden können. Mit anderen Worten, wenn Sie versuchen, dieselbe static JButton mehrfach zu einer Liste hinzuzufügen, werden Sie nicht mehrere JButton s sehen, sondern nur die JButton in der Stelle, an der Sie sie zuletzt hinzugefügt haben. Der richtige Weg, um Ihren gewünschten Effekt zu erzielen, besteht darin, anstelle von JButton selbst eine statische Referenz auf den Inhalt von JButton - nämlich Bild und Text - beizubehalten. Dann instanziieren Sie einfach ein neues JButton mit dem Bild und Text und platzieren Sie es wo immer Sie wollen. Im Allgemeinen ist es am besten, statische Referenzen aufSwing-Komponenten beizubehalten, da es unmöglich ist, mehrere Instanzen derselben Komponente zu haben.

Swing schwingt manchmal nicht so. Hoffentlich habe ich einige nützliche Informationen zur Verfügung gestellt - kämpft weiter gegen den guten Kampf!

    
Nate W. 10.02.2011 19:48
quelle
1

Sie können JXTable (aus der swingx-Palette) verwenden, die diese Option zum Deaktivieren einer bestimmten Spalte aus Ihrer Tabelle haben.

Andrei Ionut Apopei

    
Apopei Andrei Ionut 02.08.2012 13:14
quelle
0

Ich habe die Lösung:

%Vor%     
Zhu Suihui 22.08.2012 10:25
quelle