第二个JFrame中的组件未显示

我想通过按下JFrame中的按钮来启动另一个JFrame。 但是,如果按下按钮,它会显示JFrame,但不会显示按钮和滑块。

public class MainMenu extends JFrame { private JFrame klick; private static final long serialVersionUID = 9002; public static void main(String[] args) { new MainMenu(); } public MainMenu() { buildGUI1(); } public void buildGUI1() throws NullPointerException { setTitle("Hauptmenü"); setSize(800, 480); setLayout(new GridLayout()); setAlwaysOnTop(false); setLocation((Toolkit.getDefaultToolkit().getScreenSize().width)/4, (Toolkit.getDefaultToolkit().getScreenSize().height)/4); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setResizable(false); setVisible(true); final JButton startclickbt = new JButton("Start Clicker"); startclickbt.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); if(klick == null ) { klick =new Clicker(); add(klick); } } }); add(startclickbt); } 

}

第二个具有完全相同的costructor.sliders和按钮不是静态的。 在出现按钮的地方,屏幕是黑色的。

希望你能帮我 :)

编辑:

 public class Clicker extends JFrame { private static final long serialVersionUID = 9001; protected JPanel panel; static Click j = null; protected JSlider jsl; protected JTextField tf; static final int CPS_MIN= 0; static final int CPS_MAX= 100; static final int CPS_INIT= 25; private int amount; private boolean visible; public int getDelay() { return Math.abs(jsl.getValue()-100); } public int getAmount() { return amount; } public boolean getVisible() { return visible; } public void setOpen(boolean visible) { this.visible=visible; } public Clicker(boolean visible) { buildGUI(visible); j = new Click(false).addPosition(new Point((Toolkit.getDefaultToolkit().getScreenSize().width)/2, (Toolkit.getDefaultToolkit().getScreenSize().height)/2)).addPosition(new Point(getLocation().x+1, getLocation().y+20)); while(true) { j.runClicks(getDelay()); } } public Clicker() { buildGUI(true); j = new Click(false).addPosition(new Point((Toolkit.getDefaultToolkit().getScreenSize().width)/2, (Toolkit.getDefaultToolkit().getScreenSize().height)/2)).addPosition(new Point(getLocation().x+1, getLocation().y+20)); while(true) { j.runClicks(getDelay()); } } public void buildGUI(boolean visible) { setTitle("Clicker"); setSize(340, 200); setLayout(new GridLayout()); setAlwaysOnTop(true); setLocation(0, 0); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setResizable(false); setVisible(visible); final JButton bt1 = new JButton("Schließen"); bt1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }); final JButton bt2 = new JButton("Start "); bt2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { j.setClick(true); } }); final JButton bt3 = new JButton("Stop "); bt3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { j.setClick(false); JOptionPane.showMessageDialog(null, "Klicken gestoppt. Klicks: " + j.getClickAmount()); j.setClickAmout(0); } }); final JButton bt4 = new JButton("StartAnzahl"); bt4.addActionListener(new ActionListener() { private int amount; public void actionPerformed(ActionEvent e) { String wert = tf.getText(); try { amount = Integer.parseInt(wert); }catch(Exception ee) { JOptionPane.showMessageDialog(null,"Das war keine Zahl oder mehr als ein Integer"); } j.doClick(amount); } }); tf = new JTextField("Anzahl gewünschte Clicks max "+ Integer.MAX_VALUE, 10); tf.setEditable(true); jsl = new JSlider(JSlider.HORIZONTAL,CPS_MIN,CPS_MAX,CPS_INIT); jsl.setMinorTickSpacing(5); jsl.setMajorTickSpacing(10); jsl.setPaintTicks(true); jsl.setPaintLabels(true); panel = new JPanel(); panel.addMouseMotionListener(new MouseMotionListener() { @Override public void mouseDragged(MouseEvent event) { j.setClick(false); } @Override public void mouseMoved(MouseEvent event) { j.setClick(false); } }); panel.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_F1) { j.setClick(true); } if(e.getKeyCode() == KeyEvent.VK_F2) { j.setClick(false); } } }); add(panel); add(bt2); add(bt3); add(bt1); add(bt4); add(jsl); add(tf); pack(); } } 

setVisible成为你调用的最后一件事……

 public void buildGUI1() throws NullPointerException { setTitle("Hauptmenü"); setSize(800, 480); setLayout(new GridLayout()); setAlwaysOnTop(false); setLocation((Toolkit.getDefaultToolkit().getScreenSize().width) / 4, (Toolkit.getDefaultToolkit().getScreenSize().height) / 4); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setResizable(false); final JButton startclickbt = new JButton("Start Clicker"); startclickbt.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); if (klick == null) { klick = new Clicker(); add(klick); // Add this when you need to add/remove components revalidate(); repaint(); } } }); add(startclickbt); // Move to here setVisible(true); } 

此外,使用revalidate()repaint()来鼓励容器在添加新组件时更新其布局

建议:

  • 确保您的UI在EDT的上下文中启动,有关详细信息,请参阅初始线程
  • 避免直接从顶级容器(如JFrame扩展,而是考虑使用JPanel作为基础容器。 这个免费提供UI到更广泛的用例,并防止您被锁定(因为您不能将帧添加到其他帧)
  • 使用多个JFrame,好/坏的做法?

更新

你有两个直接的问题

  1. ClickerJFrame扩展,但是你试图将它添加到另一个容器,这在Swing中是不可能的并且会导致exception,但是…
  2. 您正在使用while (true)循环阻止Event Dispatching Thread,这意味着Swing无法处理任何新事件,包括repaint事件

例如…

 public Clicker(boolean visible) { buildGUI(visible); j = new Click(false).addPosition(new Point((Toolkit.getDefaultToolkit().getScreenSize().width) / 2, (Toolkit.getDefaultToolkit().getScreenSize().height) / 2)).addPosition(new Point(getLocation().x + 1, getLocation().y + 20)); // This is bad while (true) { j.runClicks(getDelay()); } } public Clicker() { buildGUI(true); j = new Click(false).addPosition(new Point((Toolkit.getDefaultToolkit().getScreenSize().width) / 2, (Toolkit.getDefaultToolkit().getScreenSize().height) / 2)).addPosition(new Point(getLocation().x + 1, getLocation().y + 20)); // This is bad while (true) { j.runClicks(getDelay()); } } 

现在, Click看起来像它的UI组件,它带来了许多其他问题,但我们没有代码,因此无法评论。

直接的解决方案可能是使用:

  • SwingWorker ,有关详细信息,请参阅Worker Threads和SwingWorker

  • Swing Timer ,有关详细信息,请参阅如何使用Swing Timers

  • 普通老Thread

要记住的事情

  • Swing(像大多数UI框架一样)是单线程的,任何阻止此线程的东西(如永不停止的循环)都会阻止它处理新事件,包括绘制事件,这会使你的应用程序看起来像是“挂起”,因为它有
  • Swing不是线程安全的。 与UI的所有交互必须在事件调度线程的上下文中进行。 SwingWorker和Swing Timer提供了安全更新UI的function。

尝试使用构造函数末尾的repaint()revalidate() 。 并尝试在最后调用setVisible(true)