2012-01-07 5 views
16

Mam 2 JPanele w ramce. Pierwszy panel zawiera elementy java, takie jak przyciski itp. Dwa przyciski, które dodałem, pojawiają się, ale JSpinner pojawia się zaraz po zmianie rozmiaru okna. Sądzę, że stanie się to także z innymi przedmiotami, które dodam. Jak mogę rozwiązać ten problem?Elementy Java pojawiają się dopiero po zmianie rozmiaru okna

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.WindowAdapter; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JSpinner; 
import javax.swing.SpinnerListModel; 
import javax.swing.SpinnerNumberModel; 

public class StartingPoint { 

static JFrame window; 
static DrawingArea draw; 
static JButton b1, b2; 
static JPanel userInt; 
static JSpinner gravitySpinner; 

public static void main(String[] args) { 
    window = new JFrame("Ball"); 
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    window.setSize(600, 400); 
    window.setLayout(new BorderLayout()); 
    window.setVisible(true); 

    draw = new DrawingArea(); 
    window.add(draw, BorderLayout.CENTER); 

    userInt = new JPanel(); 
    window.add(userInt, BorderLayout.NORTH); 

    b1 = new JButton("Start"); 
    b2 = new JButton("aaa"); 
    b1.addActionListener(new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      draw.setUp(); 
     } 
    }); 
    userInt.add(b1); 
    userInt.add(b2); 


    SpinnerNumberModel gravityModel = new SpinnerNumberModel(.9, .1, 2, .1); 
    gravitySpinner = new JSpinner(gravityModel); 
    userInt.add(gravitySpinner); 
} 
} 

Odpowiedz

29

możliwość dodawania składników do GUI po wywołującego setVisible(true) na JFrame i to w tył, ponieważ jesteś renderowania GUI zanim cokolwiek zostało dodane, a więc ma to sens, że rzeczy dodane później wygrał” t wyświetla się, dopóki wszystko nie zostanie przemalowane.

Zamiast tego najpierw dodaj wszystkie komponenty i tylko , a następnie wyrenderuj GUI, wywołując setVisible(true) na JFrame.

Edit
Ponadto, będziemy chcieli, aby uniknąć wywoływania setSize(...) na cokolwiek, ale zamiast pozwolić komponenty rozmiar sami używając ich preferredSizes i wywołując pack() na JFrame przed wyświetleniem z setVisible(true).

Edycja 2
Na przykład:

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

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JSpinner; 
import javax.swing.SpinnerNumberModel; 
import javax.swing.SwingUtilities; 

public class StartingPoint { 

    private DrawingArea draw; 
    private JButton b1, b2; 
    private JPanel userInt; 
    private JSpinner gravitySpinner; 

    private JPanel mainPanel = new JPanel(); 

    public StartingPoint() { 
     mainPanel.setLayout(new BorderLayout()); 
     draw = new DrawingArea(); 
     mainPanel.add(draw, BorderLayout.CENTER); 

     userInt = new JPanel(); 
     mainPanel.add(userInt, BorderLayout.NORTH); 

     b1 = new JButton("Start"); 
     b2 = new JButton("aaa"); 
     b1.addActionListener(new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      draw.setUp(); 
     } 
     }); 
     userInt.add(b1); 
     userInt.add(b2); 

     SpinnerNumberModel gravityModel = new SpinnerNumberModel(.9, .1, 2, .1); 
     gravitySpinner = new JSpinner(gravityModel); 
     userInt.add(gravitySpinner); 
    } 

    public JPanel getMainPanel() { 
     return mainPanel; 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      JFrame window = new JFrame("Ball"); 
      window.add(new StartingPoint().getMainPanel()); 
      window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

      window.pack(); 
      window.setLocationRelativeTo(null); 
      window.setVisible(true); 
     } 
     }); 
    } 
} 

class DrawingArea extends JPanel { 

    private static final int PREF_W = 600; 
    private static final int PREF_H = 400; 

    public void setUp() { 
     // TODO finish 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(PREF_W, PREF_H); 
    } 

} 
+2

A chcesz zawinąć cały kod w swojej głównej metodzie w wywołaniu 'EventQueue.invokeLater()', aby przestrzegać [zasady Swing threading] (http://docs.oracle.com/javase/7/docs/ api/javax/swing/package-summary.html # threading) – Robin

+0

Powinienem przenieść cały mój kod z głównej metody w metodzie run oraz w głównej matematyce muszę dodać $ SwingUtilities.invokeLater (new StartingPoint()); ? – Alex

+0

@Alex: Pozbędziesz się * wszystkiego * statycznego w powyższym kodzie, utworzysz swoje gui JPanel w samej klasie, następnie w głównej grupie utworzymy Runnable, która zainicjuje twoją klasę, dodaje JPanel klasy do JFrame, a następnie wyświetli JFrame. Na przykład zobacz ** Edytuj 2 ** powyżej. –

4

Dodaj setVisible(true) na końcu i to działa.