2010-12-14 19 views
0

Je suis en train d'écrire une application qui va quelque chose comme ceci:
- Afficher une boîte de dialogue
- Lorsque l'utilisateur clique sur OK, dialogue de fermeture, accédez à l'application principalepaintComponent ne pas être appelé au bon moment

Voici les extraits de code pertinents:

public class Owari extends JPanel implements ActionListener, MouseListener, Runnable { 

// FIELDS 
JFrame frame; 
JTextField IP; 
String IPAddress; 

static final int SERVER_MODE = 0; 
static final int CLIENT_MODE = 1; 
int mode; 

OwariBoard board; 

    public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Owari()); 
    } 

    Owari() { 
    setPreferredSize(new Dimension(WIDTH, HEIGHT)); 
    board = new OwariBoard(); 
    } 

    void main() { 
    this.addMouseListener(this); 
    frame.dispose(); 
    frame = new JFrame("Owari"); 
    frame.setContentPane(this); 
    frame.pack(); 
    frame.setVisible(true); 
    if (mode == SERVER_MODE) { 
     server(); 
    } 
    if (mode == CLIENT_MODE) { 
     client(); 
    } 
    } 

    public void run() { 
    frame = new JFrame("Owari"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    JPanel init = new JPanel(new GridBagLayout()); 
    frame.setContentPane(init); 

    add some components to the init panel including a button with 
    this as its actionListener and OK as its command. 
    frame.pack(); 
    frame.setVisible(true); 
    } 


    public void actionPerformed(ActionEvent e) { 
    if (e.getActionCommand().equals("Client")) { 
     mode = CLIENT_MODE; 
     IP.setVisible(true); 
    } 
    else if (e.getActionCommand().equals("Server")) { 
     mode = SERVER_MODE; 
     IP.setVisible(false); 
    } 
    else { 
     IPAddress = IP.getText(); 
     main(); 
    } 
    } 

    public void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    System.out.println("painting"); 
    do some paintin 
    } 

    void server() { 
    frame.setTitle("Owari Server"); 
    try { 
    server = new ServerSocket(666); 
    socket = server.accept(); 
    initIO(); 
    } catch (IOException e) {} 
    yourTurn = true; 
    System.out.println("Got to end of server()"); // At this point, the window 
                 DOES get painted 

Ce qui se passe est la suivante:
la boîte de dialogue initiale affiche:
je clique sur le bouton OK. La fenêtre principale se redimensionnée à la taille préférée de l'application principale, mais qu'il ne soit pas peint, il est juste transparent (ici avec cette page en arrière-plan, heh):
http://imgur.com/6Ssij.jpg

je peux dire La méthode paintComponent n'a pas été appelée car "paint" n'est pas imprimé sur la console. Cependant, "arrivé à ce point dans le programme" est imprimé, donc le programme n'est pas suspendu, il n'appelle pas paintComponent. Ensuite, quand je lance un client et que je me connecte, l'application est enfin peinte, et "peindre" et "obtenir un client" sont imprimés sur la console. Plus tard dans l'application, les appels à repaint() sont retardés (ie paintComponent est appelé plus tard dans le programme que lorsque l'appel à repaint() est fait).

J'ai aussi essayé de remplacer la boîte de dialogue initiale à l'aide sthing le long des lignes de

public void main 
    frame.getRootPane.removeAll() 
    frame.setContentPane(this) 
    frame.getRootPane().revalidate() 
    frame.pack() 

Exactement le même résultat.

tl; dr paintcomponent n'est pas appelé quand je le veux, que faire?


supplantation pour un peu plus d'informations: l'appel à repeindre() se fait avant l'appel à sever.accept() Alors, pourquoi il n'a pas repeindre() avant accroché au server.accept() appel ?

+0

Où sont vos accolades? – jjnguy

+0

N'oubliez pas d'exécuter tout votre code Swing/AWT sur l'EDT, mais ne le bloquez pas./Ah deux principales. 'openasocketandwaitforaclient' est dans l'EDT, ce qui est une mauvaise chose. –

Répondre

2

openasocketandwaitforaclient

Votre code est en cours d'exécution dans le thread de répartition des événements de sorte que la prise de blocage empêche l'interface graphique de se repeindre.

Vous devez utiliser un fil distinct pour le socket. Lisez la section du tutoriel Swing sur Concurrency pour une explication et une solution.

+0

Merci beaucoup. Je savais que toute la peinture de balançoire devait être faite dans le fil d'expédition de l'événement, mais pas que des trucs sans peinture devaient être faits en dehors de cela. – Jonathan

+0

Bumping pour plus d'infos: l'appel à repaint() est fait avant l'appel à couper.accept() Alors pourquoi ne pas repeindre() avant de se suspendre en attendant une connexion? – Jonathan

+1

Un repaint() ne provoque pas le composant à être peint tout de suite. Il appelle le gestionnaire Repaint qui consolide potentiellement plusieurs demandes de repeint, puis les ajoute à la fin de l'EDT pour peindre. – camickr

0

votre code semble fonctionner, vous devriez peut-être essayer d'invoquer la méthode repaint() de votre cadre après le redimensionnement de ce cadre.

Anhuin