运行 新 GUI window 来自另一个 class 的事件

Run new GUI window from an event of another class

我有 2 个 class。两者都实现了 运行 能够创建 GUI。第一个为主,第二个为副class.

我想在主 class 的 actionlistener 中启动辅助 class。

这是代码(两个class是分开的文件):

public class Main implements Runnable
{
    private JTextField txt1, txt2;
    private JLabel lbl1, lbl2;

    public void run() 
    {
        JFrame frame = new JFrame("Secondary");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container pane = frame.getContentPane();

        JPanel background = new JPanel();
        background.setLayout(new BoxLayout(background, BoxLayout.LINE_AXIS));

        ......... 

        // Horizontally adding the textbox and button in a Box
        Box box = new Box(BoxLayout.Y_AXIS);
        ......

        background.add(box);
        pane.add(background);

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

    private class SListener implements ActionListener 
    {
        public void actionPerformed(ActionEvent a)
        {
            Secondary s = new Secondary();
        }
    } 

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

}


public class Secondary implements Runnable
{
    private JTextField txt1, txt2;
    private JLabel lbl1, lbl2;

    public Secondary()
    {
      Secondary gui = new Secondary();
      SwingUtilities.invokeLater(gui);
    }

    public void run() 
    {
        JFrame frame = new JFrame("Secondary");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container pane = frame.getContentPane();

        JPanel background = new JPanel();
        background.setLayout(new BoxLayout(background, BoxLayout.LINE_AXIS));

        ......... 

        // Horizontally adding the textbox and button in a Box
        Box box = new Box(BoxLayout.Y_AXIS);
        ......

        background.add(box);
        pane.add(background);

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

我想将代码保存在两个文件中,我不想将两个 classes 混合在一个文件中。 正如您从代码中看到的那样,在辅助 class 中,在它的构造函数中我创建了辅助 class 的实例并且我 运行 gui 以便当此 [= 的实例26=]是在Main中创建的class,到运行的gui.

不幸的是,这种技术不起作用。

有什么想法吗? 谢谢

下面一行完全错误:

public Secondary(){
  Secondary gui = new Secondary();
  SwingUtilities.invokeLater(gui);
}

每次你在代码中的某处调用 new Secondary() 时,上面的代码都会被触发,它依次调用 new Secondary() 一次又一次,一次又一次,......你的程序是已屏蔽。

您可能想将其替换为

public Secondary(){
      SwingUtilities.invokeLater(this);
}

这将避免循环,但这对于构造函数来说是一种奇怪的行为。

切换到空构造函数(或将其全部删除)更有意义

public Secondary(){
}

并将您的侦听器重写为

public void actionPerformed(ActionEvent a){
  Secondary s = new Secondary();
  SwingUtilities.invokeLater( s );
}

我建议您完全重新设计您的程序。我发现将我的 GUI 用于创建 JPanel 而非顶级 windows(例如 JFrame)最有帮助,然后可以将其放置到 JFrames 或 JDialogs 或 JTabbedPanes 中,或通过 CardLayouts 在任何需要的地方进行交换。我发现这极大地增加了我的 GUI 编码的灵活性,这正是我建议您做的。所以...

  • 您的第一个 class 创建一个 JPanel,然后将其放入 JFrame。
  • 在第一个 class 的 ActionListener 中,创建第二个 class 的实例,将其放入 JDialog(而不是 JFrame)中,然后显示它。

例如,

import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.*;

public class TwoWindowEg {
   public TwoWindowEg() {
      // TODO Auto-generated constructor stub
   }

   private static void createAndShowGui() {
      GuiPanel1 mainPanel = new GuiPanel1();

      JFrame frame = new JFrame("Main GUI");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

class GuiPanel1 extends JPanel {
   private static final int PREF_W = 800;
   private static final int PREF_H = 650;
   private GuiPanel2 guiPanel2 = new GuiPanel2(); // our second class!
   private JDialog dialog = null;  // our JDialog

   public GuiPanel1() {
      setBorder(BorderFactory.createTitledBorder("GUI Panel 1"));
      add(new JButton(new LaunchNewWindowAction("Launch New Window")));
      add(new JButton(new DisposeAction("Exit", KeyEvent.VK_X)));
   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   private class LaunchNewWindowAction extends AbstractAction {
      public LaunchNewWindowAction(String name) {
         super(name);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         if (dialog == null) {
            // get the Window that holds this JPanel
            Window win = SwingUtilities.getWindowAncestor(GuiPanel1.this);
            dialog = new JDialog(win, "Second Window", ModalityType.APPLICATION_MODAL);
            dialog.add(guiPanel2);
            dialog.pack();
         }
         dialog.setVisible(true);
      }
   }
}

class GuiPanel2 extends JPanel {
   public GuiPanel2() {
      setBorder(BorderFactory.createTitledBorder("GUI Panel 1"));
      add(new JLabel("The second JPanel/Class"));
      add(new JButton(new DisposeAction("Exit", KeyEvent.VK_X)));
   }
}

class DisposeAction extends AbstractAction {
   public DisposeAction(String name, int mnemonic) {
      super(name);
      putValue(MNEMONIC_KEY, mnemonic);
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      Component comp = (Component) e.getSource();
      Window win = SwingUtilities.getWindowAncestor(comp);
      win.dispose();
   }
}

或者,您可以使用 CardLayout 交换 JPanel "views",但无论哪种方式,您都希望避免显示两个 JFrame。请看一下 The Use of Multiple JFrames, Good/Bad Practice?.