Swing remove(Component) blockiert Thread sehr lange.

Volvagia

Top Contributor
Hi, ich hoffe ihr könnt mir helfen.
Ich habe einen TimerTask, der ein Panel aus einer Map hohlt, es einem anderen Panel hinzufügt, und einen Thread startet, der ein Panel, was sich zu dem Zeitpunkt über dem hinzugefügten Panel befindet nach links verschiebt, bis es nichtmehr sichtbar ist und es danach entfernt.
Nun habe ich aber das Problem, dass die remove(Component) sehr lange in der Methode Thread.holdsLock(Object) dem momentanen Thread blockiert, und ich keine Ahnung habe woran das liegen könnte. Auch Google hat nichts ausgespuckt. Weiß jemand zufällig, woran das liegen könnte? Auf die 3 Panels wird sonst an keiner Stelle zugegriffen.

Java:
public void enterNextRoom(int x, int y, int floor, final Room newRoom)
{
	stopRoom();

	SwingUtilities.invokeLater(new Runnable() {
		public void run()
		{
			RoomPanel.getInstance().add(newRoom);
		}
	});

	new Thread("Fade Room") {
		public void run()
		{
			double speed = 0.0d;
			double x = getX();
			do
			{
				speed+= 4.0d;
				x-= speed;
				final int finalVar = (int) x;
				
				SwingUtilities.invokeLater(new Runnable() {
					public void run()
					{
						setLocation(finalVar, getY());
					}
				});
				
				try
				{
					TimeUnit.MILLISECONDS.sleep(40L);
				}
				catch (InterruptedException e) {}
			}
			while(x > -640);
			
			SwingUtilities.invokeLater(new Runnable() {
				public void run()
				{
					RoomPanel.getInstance().remove(Room.this);
				}
			});
			
			newRoom.focusPlayer();
		}
	}.start();
}
 
wie lange ist denn 'sehr lange'? wird es weniger wenn die Schleife mit setLocation() wegfällt oder auch schon wenn die Aufrufe verringert werden?
ein vollständiges Testprogramm wäre toll aber zuviel verlangt?
ich habe immerhin testweise selber eins gemacht, da läuft alles recht flott

Java:
public class TestGUI  extends JFrame {
    public TestGUI() {
        setLayout(null);
        setSize(300, 300);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) throws Exception {
        final TestGUI g = new TestGUI();

        Thread.sleep(1000);
        for (int j = 0; j < 5; j++) {
            final int y = j * 30 + 30;
            Thread.sleep(100);
            final JLabel l = new JLabel("test");
            l.setSize(100, 20);
            SwingUtilities.invokeLater(new Runnable()  {
                    public void run() {
                        g.add(l);
                    }
                });

            new Thread("Fade Room") {
                    public void run()    {
                        System.out.println("start");
                        for (int i = 0; i < 10; i++)  {
                            final int x = i * 10 + 30;
                            SwingUtilities.invokeLater(new Runnable()  {
                                    public void run()  {
                                        l.setLocation(x, y);
                                        g.repaint();
                                    }
                                });
                            try {
                                Thread.sleep(60);
                            }
                            catch (Exception e)  {
                                System.exit(0);
                            }
                        }

                        SwingUtilities.invokeLater(new Runnable()     {
                                public void run() {
                                    g.remove(l);
                                    g.repaint();
                                }
                            });
                        System.out.println("end");
                    }
                }.start();
        }
    }
}

ist mit null-Layout, wenn am Ende kein repaint() steht, dann bleibt das letzte JLabel vorerst stehen,
das verwechselst du nicht zufällig mit warten?
 
In etwa 18 Sekunden. Ohne Schleife dauert es genauso lange. Da der Thread in Thread.holdsLock(Object) festhängt, dachte ich mir, dass ein fremder Thread dem Monitor des Objektes hat. Ich selbst verwende aber nur ReentrantLock. 🙁
 
Ich meinte allgemein, gelockt wird eigendlich nur bei Listzugriffen.
Wobei, weiß zufällig jemand, ob remove noch etwas mit den Components macht, die darauf liegen? Auf dem Panel liegt ein anderes mit 462 Comps., und ich dachte, dass er vielleicht zufällig immer in der selben Methode wärend dem pausieren stehen bleibt, weil sie etwas länger als die anderen braucht? Ich habe es jetzt vorrübergehend so umgebaut, dass das Panel einfach links außerhalb des Bildschirms bleibt, aber ich denke, dass das auf Dauer ausbremsen wird, da die Panels sich mit der Zeit vermehren.
 

Zurück
Oben