2011-01-09 18 views
5

Mam JPanel wewnątrz ramki. Zawartość JPanela powinna być aktualizowana przy każdym wywołaniu do paintComponent (która jest wywoływana przez repaint()), ale kiedy robię to jak poniżej, widzę tylko białe okno. (proszę wybaczyć zmasakrowane wcięcia, Eclipse wykonuje wszelkiego rodzaju dziwne rzeczy z zakładkami.)Odświeżanie JPanel wewnątrz ramki

private static void handleGUI() 
{  
    JFrame frame = new JFrame("Animation"); 
    frame.setPreferredSize(new Dimension(100, 100)); 

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    Board b = new Board(); 

    frame.getContentPane().add(b); 

    frame.pack(); 
    frame.setVisible(true); 

    while(true) 
    { 
     System.out.println("Repainting panel"); 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
     } 
     b.repaint(); 
    } 
} 

public class Board extends JPanel 
{ 
public Board() { t=0; } 

    private int t; 

public void paintComponent(Graphics g) 
{ 
    super.paintComponent(g); 

    ++t; 

    /* Variables snipped */ 

    g.setColor(Color.white); 
    g.drawOval(0, 0, width, height); 

    BufferedImage image = ImageIO.read(new File(imagePath)); 
    g.drawImage(image, x(t), y(t)); 
    /* There's some more image and rectangle drawing ahead */ 
} 

}

+2

W rzeczywistości, Eclipse robi wszystkie fajne rzeczy z zakładkami. :-) Po prostu naciśnij CTRL-SHIFT-F, aby automatycznie sformatować źródło. Zapewni to spójne formatowanie i wcięcie, uwalniając cię od ciężaru robienia tego samemu. – harschware

+0

jakie są wartości x (0), y (0)? Obraz może znajdować się poza panelem. Czy uruchamiasz go w debugerze? Kod może wygenerować wyjątek w wątku GUI, jeśli obraz nie zostanie znaleziony. – josefx

Odpowiedz

6

Masz kilka problemów z kodem, jeden został wymieniony powyżej (1+ rep - choć wygląda na to, że masz teraz kod w metodzie paintComponent, która robi rysunek), twoja metoda paintComponent jest wadliwa, ale nie tylko to, masz pętlę (true) i Thread.sleep w głównym wątku Swing, EDT, który uśpi Swing i cały GUI. Lepiej używać Swing Timer zamiast tego. Ponadto, trzeba stwierdzić,

Zawartość JPanel mają być aktualizowane z każdym wywołaniu paintComponent (który jest nazywany przez repaint()),

jesteś pewien, że chcesz umieścić logika programu wewnątrz metody paintComponent? Zazwyczaj jest to marszczone, ponieważ programista nie ma pełnej kontroli nad tym, kiedy ta metoda jest wywoływana. Może on zostać wywołany, gdy wywołasz odświeżenie (ale nie zawsze) i może zostać wywołany z powodu komunikatów z systemu operacyjnego, gdy nie oczekujesz, że zostanie wywołany.

Nie należy również czytać pliku wewnątrz metody paintComponent, ponieważ spowoduje to spowolnienie malowania do cawl.

polecam te zmiany:

1) Tworzenie zegara Swing z okresem 1000, aw jego metody actionPerformed ActionListener jest, czytane w obrazie (najlepiej w wątku tła, jeśli obraz ma żadnego znaczącego rozmiar) i mieć obraz odczytany w polu klasy, na przykład nazwany obrazem.

2) W tym samym działaniu Timeru Opracowano metodę inkrementacji t.

3) Po wczytaniu obrazu odśwież obraz na rysunku JPanel, a rysunek JPanel użyje zmiennej obrazowej do namalowania obrazu. Bądź ostrożny, jeśli używasz wątku tła do odczytywania obrazu, ponieważ musisz mieć ten wątek, aby powiadomić GUI, gdy obraz został całkowicie odczytany. Jeśli używasz SwingWorker do tego celu, możesz dodać właściwość PropertyChangeListener, która nasłuchuje do wartości stanu SwingWorker i wyzwala, gdy zmieni się na StateValue.DONE.

Jeśli którykolwiek z powyższych jest niejasny lub mylący, poproś o wyjaśnienia.

edytuj: jeśli zdjęcia nie są zbyt duże, możesz przeczytać je wszystkie za jednym razem lub zrobić wsad czytany, gdy potrzebna jest wiązka. Nie ma absolutnej potrzeby odczytywania obrazów bezpośrednio przed ich użyciem.

1

Twój paintComponent po prostu wywołuje super.paintComponent. Tak więc JPanel podczas malowania sam, który będzie jasnoszary, lub biały lub jasnobrązowy lub coś w zależności od twojego wyglądu i stylu.

+0

Prawdopodobnie jest biały, ponieważ jego aplikacja została zamknięta, gdy zasnął i nie dokończyła wszystkich odorów. – harschware

2

Nie twórz wątku. Użyj Swing Timer, aby rozpocząć odświeżanie wydarzeń.