为什么我不能将JPanel添加到JFrame?

时间:2010-03-22 13:27:01

标签: java user-interface swing jframe jpanel

以下是代码:

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.event.*;
import java.awt.*;

public class GameWindow {

 private String[] players;
 private JFrame frame;

 // Constructor.
 public GameWindow(String[] players) {
  this.players = players;
 }

 // Start the window in the EDT.
 public void start() {
  SwingUtilities.invokeLater(new Runnable() {
   public void run() {
    showWindow();
    controller.start();
   }
  });
 }

 // Defines the general properties of and starts the window.
 public void showWindow() {
  frame = new JFrame("Game");
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  frame.setSize(600,400);
  frame.setVisible(true);
 }

 // The thread controlling changes of panels in the main window.
 private Thread controller = new Thread() {
     public void run() {
      frame.add(generatePartnerSelectionPanel());
      frame.invalidate();
      frame.validate();
     }
 };

 // Generate the panel for the selection of a partner.
 private JPanel generatePartnerSelectionPanel() {
  JPanel panel = new JPanel();
  panel.add(new JLabel("Pleas select a partner:"));
  return panel;
 }

}

我应该看到“请选择合作伙伴”而我不这样做。为什么呢?

我想这是因为我没有看到Thread的run方法中的帧。

增加:

可能我需要在事件发送线程中进行所有更新......我现在就检查它。

已添加2:

我试图修改控制器的代码。它没有帮助:

 private Thread controller = new Thread() {
 public void run() {
      SwingUtilities.invokeLater(new Runnable() {
       public void run() {
        frame.getContentPane().add(generatePartnerSelectionPanel());
        frame.invalidate();
        frame.validate();
   }
      });
 }
 };

已添加3:

行。这是代码的完整版本(不起作用):

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.event.*;
import java.awt.*;

public class GameWindow {

    private String[] players;
    private JFrame frame;

    // Constructor.
    public GameWindow(String[] players) {
        this.players = players;
    }

    // Start the window in the EDT.
    public void start() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                showWindow();
                controller.start();
            }
        });
    }

    // Defines the general properties of and starts the window.
    public void showWindow() {
        frame = new JFrame("Game");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       
        frame.setSize(600,400);
        frame.setVisible(true);
    }

    // The thread controlling changes of panels in the main window.
    private Thread controller = new Thread() {
        public void run() {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    frame.getContentPane().add(generatePartnerSelectionPanel());
                    frame.invalidate();
                    frame.validate();
                }
            });
        }
    };

    // Generate the panel for the selection of a partner.
    private JPanel generatePartnerSelectionPanel() {
        JPanel panel = new JPanel();
        panel.add(new JLabel("Pleas select a partner:"));
        return panel;
    }

}

已添加4:

以下代码也不起作用。顺便说一下,我为什么要从invokeLater删除start?我需要在事件调度线程中启动GUI,并invokelater执行它。

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.event.*;
import java.awt.*;

public class GameWindow {

    private String[] players;
    private JFrame frame;

    // Constructor.
    public GameWindow(String[] players) {
        this.players = players;
    }

    // Start the window in the EDT.
    public void start() {
//      SwingUtilities.invokeLater(new Runnable() {
//          public void run() {
                showWindow();
                controller.start();
//          }
//      });
    }

    // Defines the general properties of and starts the window.
    public void showWindow() {
        frame = new JFrame("Game");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       
        frame.setSize(600,400);
        frame.setVisible(true);
    }

    // The thread controlling changes of panels in the main window.
    private Thread controller = new Thread() {
        public void run() {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    frame.getContentPane().add(generatePartnerSelectionPanel());
                    frame.invalidate();
                    frame.validate();
                }
            });
        }
    };

    // Generate the panel for the selection of a partner.
    private JPanel generatePartnerSelectionPanel() {
        JPanel panel = new JPanel();
        panel.add(new JLabel("Pleas select a partner:"));
        return panel;
    }

}

已添加5:

我解决了这个问题。

  1. 在课堂上我有startshowWindow方法。从主程序我调用了错误的方法(showWindow而不是start)。所以,我替换start方法(以避免与线程的开始混淆),然后我从主类调用startWindow,它解决了问题。

1 个答案:

答案 0 :(得分:4)

您正在通过<{em} invokeLater电话创建更新主题。这不是您使用invokeLater的方式。 invokeLater用于从单独的线程更新UI组件。致电invokeLater,传递更新您的UI组件的Runnable来自您的单独帖子。

有关其他信息,请参阅JavaDocs

例如:

// Start the window in the EDT. 
public void start() {   
    showWindow(); 
    controller.start();  
} 

// Defines the general properties of and starts the window. 
public void showWindow() { 
    frame = new JFrame("Game"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        
    frame.setSize(600,400); 
    frame.setVisible(true); 
} 

// The thread controlling changes of panels in the main window. 
private Thread controller = new Thread() { 
    public void run() { 

        // some long running process, I assume, but at 
        // some point you want to update UI:
        SwingUtilities.invokeLater(new Runnable() { 
            public void run() { 
                frame.add(generatePartnerSelectionPanel()); 
                frame.invalidate(); 
                frame.validate(); 
            } 
        });
    } 
};