一个 JFrame 打开另一个

Posted

技术标签:

【中文标题】一个 JFrame 打开另一个【英文标题】:One JFrame opening another 【发布时间】:2011-06-22 06:57:54 【问题描述】:

我有一个 JFrame 和 JPanel,里面装满了 Jsomethings 和一个 actionlistener。当用户单击一个对象时,我想打开另一个 JFrame。这是我所做的:

public void actionPerformed(ActionEvent e) 
    Object source = e.getSource();

    if (source == rejectionbutton)
        RejectApp ra = new RejectApp();
        ra.main(null);

    


(RejectApp 调用一个新的 JFrame。)因此屏幕上会打开另一个 JFrame,其中包含更多选项。它工作正常(到目前为止),但我想知道这是标准吗?我的意思是这样调用主要方法? 另一个问题是,不使用卡片布局(我不想使用),是通过这种方式处理多个面板的最佳方式吗?

【问题讨论】:

您可能需要考虑 MigLayout (miglayout.com),一旦您了解它,它就是一个出色的布局管理器。 您从未告诉我们您为什么希望避免使用 CardLayout。 【参考方案1】:

我会改变一些事情。首先,通常一个应用程序有一个 JFrame,然后如果它需要显示另一个窗口,则可以使用模态或非模态对话框,例如可以通过 JDialog 或 JOptionPane 获得。话虽如此,更常见的是拥有一个 JFrame 并在 JFrame 中交换“视图”——通过 CardLayout 交换 contentPanes 或其他大面板,因为这将模仿我们目前使用的许多 gui 程序的行为。

就个人而言,我还尝试将我的 GUI 创建转向创建 JPanel 或 JComponent,而不是创建***窗口。这样,如果我想将 GUI 显示为独立应用程序、对话框或小程序,我可以将其分别弹出到 JFrame 或 JDialog 或 JApplet 的 contentPane 中,或者作为更复杂 GUI 的内部面板,然后将其插入那里,或者在具有交换视图的应用程序中,然后作为 CardLayout 中的卡片,如上所述。最重要的是,我认为这种结构为开发人员提供了更多使用此 GUI 的选择。

另外,我会避免调用另一个类的 main 方法(假设这是公共静态 void main 方法),因为您会失去 OOP 的所有好处。您似乎还试图以非静态方式调用静态方法(假设我正确理解您的程序结构)。

关于你的第二个问题,它引出了我自己的一个问题:你为什么不想使用 CardLayout?

编辑:我的意思的一个例子如下:

import java.awt.Dimension;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class SwingEg 
    private static void createAndShowUI() 
        JFrame frame = new JFrame("Main JFrame");
        frame.getContentPane().add(new MainGUI().getMainPanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    

    public static void main(String[] args) 
        java.awt.EventQueue.invokeLater(new Runnable() 
            public void run() 
                createAndShowUI();
            
        );
    


class MainGUI 
    private static final Dimension MAIN_PANEL_SIZE = new Dimension(450, 300);
    private JPanel mainPanel = new JPanel();
    private JDialog modalDialog;
    private JDialog nonModalDialog;

    public MainGUI() 
        JButton openModalDialogBtn = new JButton("Open Modal Dialog Window");
        openModalDialogBtn.addActionListener(new ActionListener() 
            public void actionPerformed(ActionEvent e) 
                openModalDialogBtnActionPerformed(e);
            
        );
        JButton openNonModalDialogBtn = new JButton("Open Non-Modal Dialog Window");
        openNonModalDialogBtn.addActionListener(new ActionListener() 
            public void actionPerformed(ActionEvent e) 
                openNonModalDialogBtnActionPerformed(e);
            
        );
        mainPanel.setPreferredSize(MAIN_PANEL_SIZE);
        mainPanel.add(openModalDialogBtn);
        mainPanel.add(openNonModalDialogBtn);
    

    private void openModalDialogBtnActionPerformed(ActionEvent e) 
        if (modalDialog == null) 
            Window topWindow = SwingUtilities.getWindowAncestor(mainPanel);
            modalDialog = new JDialog(topWindow, "Modal Dialog", ModalityType.APPLICATION_MODAL);
            modalDialog.getContentPane().add(new DialogPanel().getMainPanel());
            modalDialog.pack();
            modalDialog.setLocationRelativeTo(topWindow);
            modalDialog.setVisible(true);
         else 
            modalDialog.setVisible(true);
        
    

    private void openNonModalDialogBtnActionPerformed(ActionEvent e) 
        if (nonModalDialog == null) 
            Window topWindow = SwingUtilities.getWindowAncestor(mainPanel);
            nonModalDialog = new JDialog(topWindow, "Non-Modal Dialog", ModalityType.MODELESS);
            nonModalDialog.getContentPane().add(new DialogPanel().getMainPanel());
            nonModalDialog.pack();
            nonModalDialog.setLocationRelativeTo(topWindow);
            nonModalDialog.setVisible(true);
         else 
            nonModalDialog.setVisible(true);
        
    

    public JPanel getMainPanel() 
        return mainPanel;
    


class DialogPanel 
    private static final Dimension DIALOG_SIZE = new Dimension(300, 200);
    private JPanel dialogPanel = new JPanel();

    public DialogPanel() 
        dialogPanel.add(new JLabel("Hello from a dialog", SwingConstants.CENTER));
        dialogPanel.setPreferredSize(DIALOG_SIZE);
    

    public JPanel getMainPanel() 
        return dialogPanel;
    

【讨论】:

-1 这听起来根本不对...任何支持声明“通常应用程序有一个 JFrame,然后如果它需要显示另一个窗口则作为模态或非模态对话框,例如可以通过 JDialog 或 JOptionPane 获得? 对于我使用的大多数应用程序来说似乎都是如此。例如,当您使用 Microsoft Word 时,您通常会看到多少个主窗口?如果用户需要更改某种属性并单击菜单以更改属性并弹出一个窗口,那么通常 > 90% 的时间会看到哪种类型的窗口?再次以我的经验,它是一个对话。另外,如果用户关闭一个对话框,是否有关闭整个应用程序的风险?你能对 JFrame 说同样的话吗? +1 Hovercraft 的建议是查看 JFrame 的“健康”方式。只有一个***容器是有意义的。 @Hovercraft Full Of Eels 可能有一个主应用程序框架的概念,它处理其他框架的创建/处置,当用户决定关闭主框架时,它应该做出相应的反应(即检查是否所有生成的帧都可以安全关闭,如果可能发生数据丢失等情况,拒绝关闭应用程序)。企业桌面应用程序有多个非对话框窗口,Web 应用程序有多个窗口(任何链接都可以在单独的浏览器选项卡或窗口中打开)等。 @Hovercraft Full Of Eels Modality 应该仅在有意义的情况下使用——而不是作为拥有“其他窗口”的一种方式。【参考方案2】:

我宁愿创建一个新的 JFrame 实例或一个子类,或者调用一个新的方法来创建一个新的 JFrame:

public void actionPerformed(ActionEvent e) 
Object source = e.getSource();

if (source == rejectionbutton)
    JFrame frame = new JFrame("New Frame");
   //or
   makeNewFrame();

另一个简单的布局管理器是 BorderLayout,它是 JFrame 类的默认布局管理器。

【讨论】:

别忘了调用 frame.setVisible(true);此外,可能有人希望保留对开放框架的引用。如果需要重新打开同一框架,这可能很有用。但是,这需要正确处理缓存的 JFrame 引用(即在需要时释放它们等)。【参考方案3】:
new YourJFrameNameHere().setVisible(true);

将 YourJFrameNameHere 替换为 JFrame 名称。

简单,不是吗?

【讨论】:

以上是关于一个 JFrame 打开另一个的主要内容,如果未能解决你的问题,请参考以下文章

如何在打开另一个JFrame时关闭JFrame? [重复]

JButton 不会显示另一个 jframe

让 JButton 打开一个新的 JPanel

如何将值从一个JFrame传递到另一个JFrame?

JAVA怎么写代码使一个窗口打开另一个窗口

jframe跳转另一个页面