打开一个框架的多个实例,并跟踪打开实例的源

时间:2014-08-05 21:19:17

标签: java swing jframe multiple-instances

我有一个主窗口(JFrame),其中包含许多组件,包括一个按钮。按下该按钮后,打开另一个窗口(JFrame),让我们称之为客户窗口,供用户搜索详细信息并在主窗口中显示这些详细信息。

有许多类似于主窗口的窗口,所有这些主窗口都有自己的客户窗口,用于搜索和显示详细信息。

现在,我的问题是我希望所有主窗口只有一类客户窗口,而不是每个主窗口都有它。这是因为客户窗口内的所有主窗口都是相同的,除了每个客户窗口打开该特定主窗口的详细信息,即设置字段文本和将数据插入表格等等。 这里的问题是当我必须修改某些内容时...我必须编写所有其他客户窗口的代码,这也浪费时间并且还增加了应用程序/重复代码的大小。

所以,我想知道一些方法,我可以为所有主窗口提供1类客户窗口,并跟踪打开客户窗口的主窗口,以便我可以在该主窗口中打开详细信息。请注意,用户将同时打开多个主窗口,因此需要打开多个客户窗口实例。

下面是一些代码,可以了解我目前是如何做到的......

Cash_sale_customer_window:

..... get all the data from database.....

CashSaleInvoice.customerNumberTextField.setText(rs.getString(1));
CashSaleInvoice.customerNameTextField.setText(rs.getString(2));
....and so on....

Credit_sale_customer_window:

.....get all the data from database.....

CreditSaleInvoice.customerNumberTextField.setText(rs.getString(1));
CreditSaleInvoice.customerNameTextField.setText(rs.getString(2));
....and so on....

该计划的屏幕截图:

主窗口:http://postimg.org/image/adrdmrli5/

现金销售发票:http://postimg.org/image/6bcdynwhd/

任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:2)

首先,请查看The Use of Multiple JFrames: Good or Bad Practice?

其次,考虑使用模态对话框,因为这些将允许你"暂停"在对话框可见的位置执行代码并且"继续"关闭后执行。

这允许您提示用户提供详细信息,收集结果并处理它们,而无需设置引用链或回调

请查看How to make dialogs了解详情

<强>更新

如果您不能使用模态对话框,则需要将主框架的引用传递给子框架。就个人而言,我首先定义一个interface来描述子框架可以对主窗口执行的允许操作,这样就可以解耦实现并防止子框架对主窗口执行操作#39; t,就像移除所有组件一样......

答案 1 :(得分:1)

我可能会误解这个问题,但过去我做过类似的事情。这是我写的代码。这是一个Singleton,Duplicatable JFrame(我根据我的设计扩展JPanel)。

这是如何工作的: 如果您尝试打开一个新窗口并且它已经打开,它会收到焦点。如果不是,则打开一个新窗口。它使用identifier变量(可以是任何东西)来跟踪。

如何使用它: 使用静态showPanel方法,以便类确定您是否需要新面板,如下所示:

SingletonDuplicatableFramePanel.showPanel(new SingletonDuplicatableFramePanel(identifier));

(请记住,SingletonDuplicatableFramePanel是抽象的,所以你需要创建另一个扩展它的类。)

您传递了showPanel()新班级的实例。

  • 如果需要新实例,则使用它。
  • 如果它不需要新实例,则将其抛弃(注意:新实例的构造函数几乎不应该执行任何操作,因为它们可能不需要)。

只有在实际创建新实例时才会执行抽象方法init()。这是您初始化新窗口所需的任何内容。在init()方法结束时,您拨打setVisible()

如前所述,为了使其可复制,它会跟踪一个唯一的identifier,它用于确定您是否已打开实例。运行演示时应该很清楚。

以下是SingletonDuplicatableFramePanel的代码:

public abstract class SingletonDuplicatableFramePanel extends JPanel {

   public SingletonDuplicatableFramePanel(String name) {
       this.name = name;
   }
   static LinkedHashMap<Class, LinkedHashMap<Object, SingletonDuplicatableFramePanel>> self_panel_map;

   JFrame self_jf;
   protected SingletonDuplicatableFramePanel self_panel;
   boolean loading;
   boolean showing;
   LinkedList<SingletonDuplicatableFramePanel> vpanel_children;
   LinkedList<JDialog> dialog_children;

   public final String name;
   public abstract void init();

   private boolean searchablePanel;

   public boolean isSearchablePanel() {
       return searchablePanel;
   }

   public void setSearchablePanel(boolean searchablePanel) {
       this.searchablePanel = searchablePanel;
   }

   public void toFront() {
       self_jf.toFront();
   }

   protected Object identifier;
   public static SingletonDuplicatableFramePanel showPanel(Object identifier, SingletonDuplicatableFramePanel newInstance) {
       if(self_panel_map == null)
           self_panel_map = new LinkedHashMap<>();
       Class newInstanceClass = newInstance.getClass();
       if(self_panel_map.containsKey(newInstanceClass) && self_panel_map.get(newInstanceClass).containsKey(identifier)) {
           SingletonDuplicatableFramePanel oldInstance = self_panel_map.get(newInstanceClass).get(identifier);
           oldInstance.showing = oldInstance.self_jf.isVisible();

           if(!oldInstance.loading && !oldInstance.showing) {
               newInstance.loading = true;
               newInstance.self_panel = newInstance;
               newInstance.self_jf = new JFrame(newInstance.name);
               newInstance.identifier = identifier;
               newInstance.self_panel.init();
               self_panel_map.get(newInstanceClass).put(identifier, newInstance);
               return newInstance;
           } else if(oldInstance.showing) {
               oldInstance.self_jf.toFront();
           }
           return oldInstance;
       } else {
           if(!self_panel_map.containsKey(newInstanceClass))
               self_panel_map.put(newInstanceClass, new LinkedHashMap<Object, SingletonDuplicatableFramePanel>());
           newInstance.loading = true;
           newInstance.self_panel = newInstance;
           newInstance.self_jf = new JFrame(newInstance.name);
           newInstance.identifier = identifier;
           newInstance.self_panel.init();
           self_panel_map.get(newInstanceClass).put(identifier, newInstance);
           return newInstance;
       }
   }

   public void addChild(SingletonDuplicatableFramePanel panel) {
       if(vpanel_children == null)
           vpanel_children = new LinkedList<>();
       vpanel_children.add(panel);
   }

   public void dispose() {
       loading = false;
       showing = false;
       self_jf.dispose();
   }

   boolean packed;
   public void pack() {

       self_jf.add(self_panel);
       self_jf.pack();
       self_jf.addWindowListener(new WindowAdapter() {
           @Override
           public void windowClosing(WindowEvent e) {
               if(vpanel_children != null)
                   for(SingletonDuplicatableFramePanel vpanel : vpanel_children)
                       vpanel.dispose();
               if(dialog_children != null)
                   for(JDialog dialog : dialog_children)
                       dialog.dispose();
           }
       });
       setLocationByPlatform(true);
       self_jf.toFront();
       self_jf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
       packed = true;
   }

   public void setVisible() {
       if(!packed) {
           pack();
       }
       self_jf.setVisible(true);
       loading = false;
   }

   public void setTitle(String title) {
       self_jf.setTitle(title);
   }

   public void centerJF() {
       self_jf.setLocationRelativeTo(null);
   }

   public void setLocationByPlatform(boolean bool) {
       self_jf.setLocationByPlatform(bool);
   }

}

这是一个正在使用的样本:

static class My_SDFP extends SingletonDuplicatableFramePanel {

    String customer_number;
    public My_SDFP(String customer_number) {
        super("My SDFP");
        this.customer_number = customer_number;
    }

    @Override
    public void init() {
        JLabel label = new JLabel("Customer Number = " + customer_number);
        add(label);
        setVisible();
    }

}

public static void main(String[] args) {

    JFrame baseFrame = new JFrame();
    baseFrame.setLayout(new GridBagLayout());
    JButton button = new JButton("Open customer #");
    final JTextField identifier_field = new JTextField();
    button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent evt) {
            String identifier = identifier_field.getText();
            My_SDFP.showPanel(identifier, new My_SDFP(identifier));
        }
    });
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.insets = new Insets(2, 2, 2, 2);
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;

    gbc.gridy = 1;
    baseFrame.add(new JLabel("Customer #:"), gbc);
    baseFrame.add(identifier_field, gbc);

    gbc.gridwidth = 2;
    gbc.gridy = 2;
    baseFrame.add(button, gbc);
    baseFrame.pack();
    baseFrame.setLocationByPlatform(true);
    baseFrame.setVisible(true);
    baseFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

在Customer#字段中键入一个数字,然后单击按钮。您会注意到您无法打开同一客户编号的两个实例。如果您尝试,它只会重新聚焦您尝试重新打开的帧(但不能因为它已经打开)。

enter image description here