Zawartość JPanel nie aktualizuje się

0

W tworzonej aktualnie aplikacji natknąłem się na pewien problem, którego nie mogę rozwiązać. W ramach testu stworzyłem kod realizujący tylko problematyczne zadanie, aby wykluczyć inne przyczyny i problem jest powtarzalny, gdyż także tutaj występuje.

Cel: w JPanel wstawiam kilka JLabel zawierające różne teksty. Po każdym wciśnięciu przycisku zawartość tego panelu jest odświeżana. Może się pojawić inna ilość etykiet z innymi tekstami (nie jest znana maksymalna ilość etykiet), dlatego w przykładzie do akcji wstawiającej etykiety wprowadziłem losowość zarówno do ich ilości jak i treści.

Problem jest taki, że po wciśnięciu przycisku "losuj" etykiety znikają, ale nie pojawiają się nowo dodane. Na początku uznałem, że rozwiązaniem będzie ponowne odrysowanie panelu, które wstawiłem w akcji po dodaniu nowych etykiet do panelu, jednak to nie pomaga. Etykiety jednak tam są, gdyż wystarczy złapać za krawędź okna w celu zmiany jego rozmiaru, żeby się pojawiły.

Kombinowałem na różne sposoby, jednak nie wiem gdzie popełniam błąd i będę wdzięczny za pomoc.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Blad
	{
	public static void main(String[] args)
		{
		EventQueue.invokeLater(
			new Runnable()
				{
				public void run()
					{
					BladFrame oOkno = new BladFrame();
					oOkno.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
					oOkno.setVisible(true);
					}
				}
			);
		}
	}

class BladFrame
	extends JFrame
	{
	private JPanel oPanelGlowny;
	private JPanel oTeksty;
	private JPanel oPrzyciski;
	private Random oRand;
	private class ActionLosuj
		extends AbstractAction
		{
		public ActionLosuj()
			{
			putValue(Action.NAME, "Losuj");
			}
		public void actionPerformed(ActionEvent oEvent)
			{
			oTeksty.removeAll();
			int iIlosc = oRand.nextInt(10) + 1;
			for (int i = 0; i <= iIlosc; ++i)
				oTeksty.add(new JLabel("" + oRand.nextInt(100)));
			oTeksty.repaint();
			}
		}
	public BladFrame()
		{
		setMinimumSize(new Dimension(200, 200));
		setPreferredSize(new Dimension(200, 200));
		setTitle("test");
		setLocationRelativeTo(null);
		
		oRand = new Random();
		oPanelGlowny = new JPanel();
		oPanelGlowny.setLayout(new BorderLayout());
		oTeksty = new JPanel();
		oTeksty.setLayout(new FlowLayout());
		oPrzyciski = new JPanel();
		oPrzyciski.setLayout(new GridLayout(1, 1));
		JButton oButtonLosuj = new JButton(new ActionLosuj());
		
		oPrzyciski.add(oButtonLosuj);
		oPanelGlowny.add(oTeksty, BorderLayout.CENTER);
		oPanelGlowny.add(oPrzyciski, BorderLayout.PAGE_END);
		add(oPanelGlowny);
		}
	}
0

Chyba znienawidzę to odświeżanie javy jak jej się podoba. Cały czas jakieś z tym problemy. Twój problem jest bez sensu. Sprawdziłem i jak klikniesz przycisk jest wywoływana metoda "paint" która dziwnym trafem nie potrafi wyświetlić etykiet. A jak zmienisz rozmiar to o dziwo zostaje wywołana ta sama metoda "paint" (ale niespodzianka :/ ) która już nagle się tego nauczyła. Jak dla mnie bez sensu. Ciekawe czy jest na to jakieś logiczne wyjaśnienie :)

Pozdro

0

A najlepsze w ogóle jest to:

public void actionPerformed(ActionEvent oEvent)
		{
			oTeksty.removeAll();
			int iIlosc = oRand.nextInt(10) + 1;
			for (int i = 0; i <= iIlosc; ++i)
				oTeksty.add(new JLabel("" + oRand.nextInt(100)));
			oTeksty.repaint();
			// tu resajzujemy :p
			setSize(200, 201);
			setSize(200, 200);
		}

i tak jak ręcznie działa tak i tu zadziała [rotfl]

Pozdrawiam

0

Przyznam, że takiego rozwiązania problemu się nie spodziewałem ;)
Dzięki za pomysł z zautomatyzowaniem tej zmiany rozmiaru. Spróbuję wstawić to do docelowego kodu, lub ewentualnie powalczę z innym sposobem wyświetlenia tych informacji, który być może będzie bardziej lubił się z repaint().
Ale także chętnie poznam przyczynę tego problemu, gdyby ktoś miał jakiś pomysł.

0
                        for (int i = 0; i <= iIlosc; ++i)
                                oTeksty.add(new JLabel("" + oRand.nextInt(100)));
                        oTeksty.doLayout();
                        oTeksty.repaint();

lub

                        for (int i = 0; i <= iIlosc; ++i)
                                oTeksty.add(new JLabel("" + oRand.nextInt(100)));
                        oTeksty.validate();
                        oTeksty.repaint();

Trzeba zażądać od menadżera rozkładu, żeby na nowo ustalił swój rozmiar.

0

Po przeczytaniu dokumentacji od podanych metod faktycznie wszystko już stało się jasne. Należy je wywołać, gdy nastąpiły zmiany, które mogą wpłynąć na rozkład elementów (choćby dodanie, czy usunięcie elementów), a że zmiana rozmiaru okna także jest taką sytuacją, pewnie wtedy ta metoda była automatycznie wywoływana. Do tej pory na problem się nie natknąłem, gdyż raz utworzoną strukturę komponentów nie zmieniałem w trakcie działania programu.
Dzięki wielkie za wskazanie rozwiązania.

1 użytkowników online, w tym zalogowanych: 0, gości: 1