2016-05-11 13 views
0

Die Frage ist, wie Swing Hörer behandelt. In diesem Beispiel steht die TableModelListener im Fokus.Wie werden Listener in Java Swing behandelt?

Das Tischmodell (nennen wir es TableModelImpl) Ich habe von AbstractTableModel erweitert. Zwischen diesem Tischmodell und der JTable habe ich die Klasse TableSorter, die wie ein Dekorator zu TableModelImpl ist (und die TableSorter erweitert auch AbstractTableModel). Die TableSorter ist über die Assoziation mit TableModelImpl verbunden, was ich meine ist, dass TableSorter einen Verweis auf die TableModelImpl enthält. Ferner haben die TableSorter Mitglieder des Typs TableModelListener, die auf mein TableModelImpl Objekt hören. Die JTable hört wiederum eine TableSorter.

Also im Allgemeinen kann gesagt werden, dass das JTable Objekt hört TableSorter, die auf meine TableModelImpl hört. Die Frage ist also: Wie funktioniert das? Angenommen zum Beispiel, dass ich TableModelStructureChanged() auf meinem TableModelImpl Objekt aufrufen möchte, wird dieses Event dann an die JTable über die TableSorter weitergeleitet?

So etwas verkürzt Beispiel:

public class TableModelImpl extends AbstractTableModel { 

private boolean enabled; 
public TableModelImpl(//non relevant parameter, linked to data) { 
    //Irrelevant code binds model to the data 
    this.enabled = false; 
} 

public void setEnabled(boolean enabled) { 
    this.enabled = enabled; 
    fireTableStructureChanged(); 
} 
    // More irrelevant code 
} 

public class TableSorter extends AbstractTableModel { 

private TableModel tableModel; 

    private MouseListener mouseListener; 
    private TableModelListener tableModelListener; 

    public TableSorter() { 
     this.mouseListener = new MouseHandler(); 
     this.tableModelListener = new TableModelHandler(); 
    } 

    public TableSorter(TableModel tableModel) { 
     this(); 
     setTableModel(tableModel); //Adds this.tableModelListener to tableModels listenerList 
    } 
} 

Also, wenn ich folgendes tun:

TableModelImpl tm = new TableModelImpl(); 
TableSorter sorter = new TableSorter(tm); 
JTable table = new JTable(sorter); 
tm.setEnabled(true); 

Wird die JTable benachrichtigt?

+3

Beschreiben Sie Ihren Code nicht, zeigen Sie ihn. – RealSkeptic

+0

@RealSkeptic Ok Ich habe ein Beispiel hinzugefügt. Der echte Code ist ziemlich lang, also habe ich versucht, die relevanten Teile einzubeziehen. Der TableSorter enthält auch Parameter und Code für die Sortierung, der nicht mit Listenern zusammenhängt. Außerdem gibt es Bindungen an das Datenmodell, die sich nicht auf Listener beziehen. – patrik

+1

Es ist schwer zu sagen, da wir keinen Zugriff auf Ihren 'TableModelHandler' oder' setTableModel' haben. Aus der Sicht der Dinge, 'TableSorter' will als Proxy zwischen' JTable' und 'TableModelImp' agieren, so dass alle Ereignisse, die von' TableModelImpl' ausgelöst werden, (möglicherweise modifiziert und) an alle mit '' registrierten Listener weitergeleitet werden müssen Tisch Sorter'. 'JTable' registriert sich selbst als' TableModeListener' zu welchem ​​Modell Sie es auch anbieten, also vorausgesetzt, Sie haben die Ereignisweiterleitung richtig eingerichtet, dann sollte es funktionieren – MadProgrammer

Antwort

2

Swing ist eine großartige Umsetzung der bekanntesten Design-Muster in Java wie Model-View-Controller (die meisten Zeiten bezeichnet als MVC), Singleton, Factory, Observer und etc.

Viele JComponents wie JTableJList oder JComboBox implementieren MVC Muster. In vielen Situationen, wenn das Modell geändert wird, wird eine Methode wie aufgerufen, die für die Iteration über die Liste der Listener verantwortlich ist, die dem Modell hinzugefügt wurden, und ruft ihre tableChanged(TableModelEvent tme)-Methode auf. Daher wird jede andere Komponente wie die Ansicht benachrichtigt, um ihren Status aufgrund der Änderungen des Modells zu aktualisieren.

Das gleiche gilt, wenn fireTableStructureChanged() aufgerufen wird. Da JTable die Schnittstelle TableModelListener implementiert und sich selbst als Listener für ihre TableModel registriert, wird sie automatisch benachrichtigt, wenn Sie fireTableStructureChanged() anrufen.

Es ist vorteilhaft, den Quellcode der JTable und AbstractTableModel zu sehen, um den Mechanismus der Zündung zu verstehen und die TableModelEvent s zu hören.

[UPDATE]

Es gibt keine magische Art und Weise, nur Methodenaufrufe. In der AbstractTableModel gibt es eine List<TableModelListener> namens listenerList. Auf der anderen Seite implementiert JTableTableModelListener Schnittstelle.Im Konstruktor der Klasse JTable fügt sich JTable zur Liste der Listener im Modell hinzu. Wenn also irgendetwas mit TableModel und seinen fireXXX() Methoden aufgerufen wird, ist die einzige Magie Iterieren über listenerList und Aufrufen der "TableChanged" -Methode. Da JTable in der Liste ist, wird 'tableChanged' von JTable aufgerufen.

Ich hoffe, das wäre hilfreich.

+0

Ich habe ein bisschen auf diese beiden Klassen geschaut. Meine Vermutung ist, dass das Event bis zum nächsten Objekt weitergeleitet wird, bis es eine JTable erreicht, und die Klasse 'TableSorter' sieht eine geschachtelte Klasse' TableModelHandler' vor, die den TableModelListener implementiert. Diese Methode ruft 'fireTableChanged' auf. Ich kann davon ausgehen, dass diese Klasse dafür verantwortlich ist, das Ereignis an die 'JTable' weiterzuleiten. Ich denke, ich hätte den Code ein wenig näher betrachten sollen und nicht davon ausgehen können, dass der Swing das auf "auto-magische Weise" handhaben sollte. Ich fühle mich dumm, danke für deine Zeit und Entschuldigung für die Störung. – patrik

+0

siehe das Update. – STaefi

+0

@STaefi carrecfully mit fireXxx und tableXxxChanged ohne Details, Beschreibung, weil die meisten von ihnen können alle benutzerdefinierten Einstellungen, Listener, Fitering, Sortierung ... zurücksetzen, AbstractTableModel ist nicht gut start_point mit dem Vergleich mit DefaultTableModel – mKorbel