Swing Oberfläche rekusiv updaten mit updateUi()

SignIn

Mitglied
Hallo zusammen,

ich habe eine Oberfläche, die sich beim ändern des Models rekursiv updatet. Dazu habe ich eine View mit der Funktion update()

Java:
[...]

public void update ()
	{
		//Oberfläche updaten
		updateChilds (_mainpanel);
	}
	
	public void updateChilds (Component comp)
	{
		
		if (comp == null) return;
		if (comp instanceof Container)
		{
			Container con = (Container) comp;
			Component[] comps = con.getComponents();
			for (int i = 0; i<comps.length; i++)
			{
				Component c = comps[i];
				if (c instanceof JComponent) {
					JComponent jc = (JComponent)comp;
					jc.updateUI();
				}
				updateChilds(c);
			}
			return;
			
		}

Dabei bekomme ich einen Fehler:

Code:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0
	at javax.swing.plaf.basic.BasicTabbedPaneUI.tabForCoordinate(BasicTabbedPaneUI.java:1506)
	at javax.swing.plaf.basic.BasicTabbedPaneUI.setRolloverTab(BasicTabbedPaneUI.java:575)
	at javax.swing.plaf.basic.BasicTabbedPaneUI.access$2000(BasicTabbedPaneUI.java:54)
	at javax.swing.plaf.basic.BasicTabbedPaneUI$Handler.mouseEntered(BasicTabbedPaneUI.java:3627)
	at java.awt.Component.processMouseEvent(Component.java:6534)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
	at java.awt.Component.processEvent(Component.java:6290)
	at java.awt.Container.processEvent(Container.java:2234)
	at java.awt.Component.dispatchEventImpl(Component.java:4881)
	at java.awt.Container.dispatchEventImpl(Container.java:2292)
	at java.awt.Component.dispatchEvent(Component.java:4703)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898)
	at java.awt.LightweightDispatcher.retargetMouseEnterExit(Container.java:4686)
	at java.awt.LightweightDispatcher.trackMouseEnterExit(Container.java:4665)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4514)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4462)
	at java.awt.Container.dispatchEventImpl(Container.java:2278)
	at java.awt.Window.dispatchEventImpl(Window.java:2739)
	at java.awt.Component.dispatchEvent(Component.java:4703)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:746)
	at java.awt.EventQueue.access$400(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:697)
	at java.awt.EventQueue$3.run(EventQueue.java:691)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.awt.EventQueue$4.run(EventQueue.java:719)
	at java.awt.EventQueue$4.run(EventQueue.java:717)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:716)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Dann wollte ich debuggen, und mein Eclipse stürzt ab und der Bildschirm friert ein. Also hab ich die Updatefunktion mal herausgenommen und ein return rein mit einem Haltepunkt versehen:

Java:
public void update ()
	{
	//also hier passiert eigentlich nichts, trotzdem friert der Bildschirm ein, aber nur im Debugmodus
		return;
}

Hat jemand eine Idee, woran das liegen könnte ?

Vielen Dank !

SignIn
 
Das er nur im Debugmodus einfriert, hört sich nach einer Race Condition an. Wie viele Threads verwendest du?

Welchen Teil aus diesem StackTrace hast du selber geschrieben?
 
Hallo Gucky,

danke für die Hilfe. Also ich verwende keine Threads. Und keine der genannten Dateien in der Fehlermeldung habe ich erstellt ....

Ehrlich gesagt, musste ich jetzt erstma Race Condition nachschlagen ....
 
Ach so. Ein Anfänger. Sorry 😉

Das ist natürlich ein interessantes Problem.
Poste mal den ganzen Code. So kann ich nichts sagen.
 
Auweia, der ganze Code ist so umfangreich. Da hängt eine Datenbank dran und ich hab ein eigenes MVC versucht zu schreiben, dementsprechend viele Klassen sind das mittlerweile. Bis dato hatte auch alles funktioniert, nur lassen sich die Tabellen auf der Oberfläche nicht updaten. Für die Tabellen habe ich ein TableModel, was meine Modelklasse enthält und sich daraus die Daten zieht.

Aus einer Combobox wird ein Objekt gewählt und das Model läd die neuen Daten. Danach wollte ich die Tabellen updaten. revalidate, repaint etc. funktionieren nicht.

Vielleicht hab ich wirklich einen Denkfehler in der Zeitabfolge ...... ich denke nochmal nach ...
 
Ok, ich versuch mal das wichtigste hierrein zu kopieren.
Also ich habe ein MainFrame was das Interface IView und IObserver implementiert. Hat eine update()-Methode, die die aktuelle Oberfläche updaten soll.
Ich habe aso eine ComboBox in der ein Lagerort ausgewählt werden kann. Das klappt soweit. Wenn jetzt ein anderes Item gewählt wird, wird der TableConnectController aufgerufen und die neuen Daten werden geladen.
Wenn das Laden fertig ist, wird _model.hasChanged() aufgerufen, welches die Observer benachrichtigt, sich upzudaten.

So, nun zum Quelltext:

Model:
Java:
[...]
	public void hasChanged ()
	{
		if (_observer == null) return;
		Iterator<IObserver> it = _observer.iterator();
		while (it.hasNext())
		{
			it.next().update();
		}
	}
[...]

View = Observer
Java:
	public void updateChilds (Component comp)
	{
		
		if (comp == null) return;
		
		if (comp instanceof JScrollPane) {
			Component compo = ((JScrollPane)comp).getViewport().getView();
			if (compo instanceof JTable) {
				JTable tab = ((JTable)compo);
				tab.updateUI();
			}
			return;
		}
		
		if (comp instanceof Container)
		{
			Container con = (Container) comp;
			Component[] comps = con.getComponents();
			if (comps == null) return;
			int anzahl = comps.length;
			
			for (int i = 0; i<anzahl; i++)
			{
				Component c = comps[i];
				/*if (c instanceof JComponent) {
					JComponent jc = (JComponent)comp;
					//jc.repaint();
					
				}*/
				if (c instanceof JTable) continue;
				updateChilds(c);
				
			}
			
		}
	}

Controller erbt von ActionListener
Java:
@Override
	public void actionPerformed(ActionEvent ev) {
		// TODO Auto-generated method stub
		if (_art == Art.LAGERORTE)
		{
			if (ev.getSource() instanceof JComboBox)
			{
				JComboBox<IMObject> combo = (JComboBox<IMObject>)ev.getSource();
				if (combo.getSelectedItem() instanceof MLagerort)
				{
					MLagerort ort = (MLagerort) combo.getSelectedItem();
					ort.loadSubs(_model.getDatabase(), MLagerort.Subs.GERAETE);
					ort.loadSubs(_model.getDatabase(), MLagerort.Subs.CHEMIKALIEN);
					_model.hasChanged();
				}
					
			}
		}
 
Kannst du versuchen ein KSKB zu erstellen, dass den Fehler enthält?

Versuch mal Zeilen nach einander auszukommentieren und versuche so den Fehler einzugrenzen.
 
Tut mir leid. Kam heute erst wieder dazu, was zu machen.

Ich habe jetzt diesen merkwürdigen Absturz versucht auf die Schliche zu kommen.

Der Debugger stürzt beim Aufruf der actionPerformed - Methode ab.
Auch wenn diese Methode scheinbr lehr ist (nur ein System.out.println um einen Haltepunkt zu setzen) ... fand ich sehr komisch. Also hab ich mal versucht meiner Combobox ein Objekt einer Klasse mit addActionListener hinzuzufügen, die direkt von ActionListener erbt und siehe da, es funktioniert und nichts friert ein.

Bisher habe ich von IController abgeleitet, welcher wiederum von ActionListener erbt.

Java:
package controller;

import model.IModel;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import view.IView;

public interface IController extends ActionListener {
	public IModel getModel ();
	public void actionPerformed (ActionEvent ev);
	public void setModel (IModel model);
	public void setView (IView view);
	public void error (Exception ex, String ustr);
	public void message();
}

Anwendung:
Java:
		LagerortComboBoxController ctrl = new LagerortComboBoxController ();
		combo.addActionListener(ctrl);

LagerortComboBoxController erbte einmal direkt von ActionListener und einmal von IController. Bis letzterem friert am Haltepunkt der Bildschirm ein.
Das witzige ist, dass ich IController schon im Zusammenhang mit einer ComboBox verwendet habe und da geht es :noe:

Jemand eine Idee ? Was mache ich da falsch ? Ich nutze Java 8.

Viele Grüße, SignIn
 
Hab mich jetzt dazu entschlossen, doch nur die Tabellen auf der Oberfläche upzudaten, wenn sich was am Model ändert, weil ich eigentlich keine anderen Anzeigen derzeit habe. Und das funktioniert jetzt ...

Hier der Code der UpdateChild-Methode:

Java:
public void updateChilds (Component comp)
	{
		
		if (comp == null) return;
		if (comp instanceof JTable) {
			JTable tab = (JTable) comp;
			TableModel mod = tab.getModel();
			if (mod instanceof ITableModel) ((ITableModel) mod).modelChanged();
			tab.updateUI();
			return;
		}
		
		if (comp instanceof Container)
		{
			Component[] comps = ((Container)comp).getComponents();
			if (comps == null || comps.length == 0) return;
			for (int i=0;i<comps.length;i++) updateChilds(comps[i]);
		}
	}
 

Zurück
Oben