简体   繁体   English

如何从多个 GUI 类集成多页 Java 桌面应用程序

[英]How to Integrate Multi-page Java Desktop Application from Multiple GUI Classes

I am working on a Java Swing desktop application project.我正在开发一个 Java Swing 桌面应用程序项目。 The application has about 15 GUI pages.该应用程序有大约 15 个 GUI 页面。 I can use Layered Panes and Tabbed Panes to put all the GUI components in one class.我可以使用分层窗格和选项卡式窗格将所有 GUI 组件放在一个类中。 But that class will be huge.但是那个班级会很大。 It would be idea if I can divide the project into several smaller sub-projects and let each have one or a few GUI pages.如果我可以将项目分成几个较小的子项目,并让每个子项目有一个或几个 GUI 页面,那将是一个想法。 I can work on each sub-project individually and integrate them back into one application when all sub-projects are finished.我可以单独处理每个子项目,并在所有子项目完成后将它们集成回一个应用程序。 My question is that how I can integrate all GUI pages from different classes so I can navigate back and force among different pages on button clicks?我的问题是如何集成来自不同类的所有 GUI 页面,以便我可以在单击按钮时在不同页面之间来回导航? Since the sub-projects contain GUI pages each needs to have a JFrame.由于子项目包含 GUI 页面,因此每个子项目都需要有一个 JFrame。 How I can switch back and force between JFrame 1 to JFrame 2 and make one visible and the other invisible?如何在 JFrame 1 和 JFrame 2 之间切换并强制使一个可见而另一个不可见? This question shows how to create new JFrames. 这个问题展示了如何创建新的 JFrame。 But did not show how switch back and forth among the JFrames.但是没有显示如何在JFrames 之间来回切换。

... The application has about 15 GUI pages. ...该应用程序有大约15个GUI页面。 I can use Layered Panes and Tabbed Panes to put all the GUI components in one class. 我可以使用Layered Panes和Tabbed Panes将所有GUI组件放在一个类中。 But that class will be huge. 但那个班级将是巨大的。

Not necessarily. 不必要。 The GUI could be quite simple, and could have a method that would allow other classes to add a page, say something called registerPage(...) : GUI可以非常简单,并且可以有一个允许其他类添加页面的方法,比如说一个名为registerPage(...)东西:

public void registerPage(JComponent page, String name) {
  pageHolder.add(page, name);
  nameComboModel.addElement(name);
}

Then give the class methods to allow one to go to the next or previous page or to a random page. 然后给出类方法,以允许一个方法转到下一页或上一页或随机页面。 For example a class as small as this could work: 例如,像这样小的类可以工作:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class LotsOfPagesPanel extends JPanel {
   private CardLayout cardlayout = new CardLayout();
   private JPanel pageHolder = new JPanel(cardlayout);
   private DefaultComboBoxModel<String> nameComboModel = new DefaultComboBoxModel<String>();
   private JComboBox<String> nameCombo = new JComboBox<String>(nameComboModel);

   public LotsOfPagesPanel() {
      JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0));
      btnPanel.add(new JButton(new PrevAction(this, "Previous", KeyEvent.VK_P)));
      btnPanel.add(new JButton(new NextAction(this, "Next", KeyEvent.VK_N)));
      JPanel bottomPanel = new JPanel();
      bottomPanel.add(btnPanel);
      bottomPanel.add(nameCombo);

      nameCombo.addActionListener(new NameComboListener());
      pageHolder.setBorder(BorderFactory.createEtchedBorder());

      setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
      setLayout(new BorderLayout(5, 5));
      add(pageHolder, BorderLayout.CENTER);
      add(bottomPanel, BorderLayout.PAGE_END);
   }

   public void previousPage() {
      cardlayout.previous(pageHolder);
   }

   public void nextPage() {
      cardlayout.next(pageHolder);
   }

   public void show(String name) {
      cardlayout.show(pageHolder, name);
   }

   public void registerPage(JComponent page, String name) {
      pageHolder.add(page, name);
      nameComboModel.addElement(name);
   }

   private class NameComboListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         String selection = nameCombo.getSelectedItem().toString();
         show(selection);
      }
   }
}

All this class really does is act as a repository for your "pages" and has the logic to allow flipping through pages either contiguously or randomly, and not much else, but that's all it really needs to do, and by limiting it so, we limit the class's size. 所有这一类真正做的就是作为你的“页面”的存储库,并且具有允许连续或随机翻页的逻辑,而不是其他,但这就是它真正需要做的全部,并且通过限制它,我们限制班级的规模。 If other functionality is needed, create other classes for these 如果需要其他功能,请为这些功能创建其他类

... such as our Action classes including the PrevAction class: ...比如我们的Action类,包括PrevAction类:

import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;

public class PrevAction extends AbstractAction {
   private LotsOfPagesPanel lotsOfPages;

   public PrevAction(LotsOfPagesPanel lotsOfPages, String name, Integer keyCode) {
      super(name);
      this.lotsOfPages = lotsOfPages;
      putValue(MNEMONIC_KEY, keyCode);
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      lotsOfPages.previousPage();
   }
}

and NextAction.java 和NextAction.java

import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;

public class NextAction extends AbstractAction {
   private LotsOfPagesPanel lotsOfPages;

   public NextAction(LotsOfPagesPanel lotsOfPages, String name, Integer keyCode) {
      super(name);
      this.lotsOfPages = lotsOfPages;
      putValue(MNEMONIC_KEY, keyCode);
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      lotsOfPages.nextPage();
   }
}

And you would need to have a main method of course: 当然,你需要一个主要的方法:

import java.awt.Color;
import java.awt.Dimension;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

public class LotsOfPagesMain {
   private static final String[] LABELS = { "One", "Two", "Three", "Four",
         "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve",
         "Thirteen", "Fourteen", "Fifteen" };
   private static final Dimension LABEL_SIZE = new Dimension(400, 300);

   private static void createAndShowGui() {
      LotsOfPagesPanel lotsOfPages = new LotsOfPagesPanel();
      Random random = new Random();

      // I'm using JLabels as a simple substitute for your complex JPanel GUI "pages"
      for (String labelText : LABELS) {
         JLabel label = new JLabel(labelText, SwingConstants.CENTER);
         label.setPreferredSize(LABEL_SIZE);
         label.setOpaque(true);
         label.setBackground(new Color(random.nextInt(170) + 85, random
               .nextInt(170) + 85, random.nextInt(170) + 85));
         lotsOfPages.registerPage(label, labelText);
      }

      JFrame frame = new JFrame("LotsOfPages");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(lotsOfPages);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

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

But it wouldn't be a huge class by any means, and you wouldn't have to worry about flipping multiple JFrames at the user. 但它绝不会是一个庞大的类,你不必担心在用户处翻转多个JFrame。

Your idea of a centralised controller isn't a bad one. 你对集中控制器的想法并不是坏事。

Personally, my first thoughts would be to try a group these separate pages into domain groups (or groups of responsibility). 就个人而言,我的第一个想法是尝试将这些单独的页面组成一个域组(或责任组)。 This would give me my first level of control. 这将给我我的第一级控制。 I'd decide how I would like these domains to be used by the user. 我决定如何让用户使用这些域名。

Once you have that working, you can move to the next level, which groups work with each other (if any) & how would you like the user to interact with these 一旦你有了这个工作,你可以进入下一个级别,哪些组相互协作(如果有的话)以及你希望用户如何与这些组进行交互

And so forth. 等等。

I agree with HovercraftFullOfEels, you don't want to throw lots of windows at users, this just frustrates them, you also don't want them to have to flick between related pages, where the information on one is useful on another. 我同意HovercraftFullOfEels,你不想向用户抛出大量的窗口,这只是让他们感到沮丧,你也不希望他们不得不在相关页面之间轻弹,其中一个页面上的信息对另一个页面有用。

You might find that you end up with a combination of both. 您可能会发现最终得到两者的组合。 That is, you might need to provide the user with the flexibility to open some pages in frames. 也就是说,您可能需要为用户提供在框架中打开某些页面的灵活性。 This would allow them the ability to decide what information they always need & what information they can flip through. 这将使他们能够决定他们总是需要哪些信息以及他们可以翻阅的信息。

IMHO 恕我直言

You have a couple of options: 你有几个选择:

  1. You can hide the old JFrame with setVisible(false) 你可以用setVisible隐藏旧的JFrame(false)
  2. You can get rid of the old JFrame with dispose() 你可以用dispose()摆脱旧的JFrame

You can get some more information on these methods and how they should be called here: http://docs.oracle.com/javase/6/docs/api/javax/swing/JFrame.html 您可以获得有关这些方法的更多信息以及如何在此处调用它们: http//docs.oracle.com/javase/6/docs/api/javax/swing/JFrame.html

Hope this helps! 希望这可以帮助!

The method I use to do that is to make pages as panels and make these panels static and add the panel that I want to my frame and delete the previous panel here is the function that I use :我使用的方法是将页面制作为面板并使这些面板静态并将我想要的面板添加到我的框架中并删除前一个面板,这是我使用的功能:

public static void add(JPanel panelYouWantToAdd, JPanel prevPanelToRemove) {
        prevPanelToRemove.setVisible(false);
        panelYouWantToAdd.setVisible(true);
        appFrame.add(panelYouWantToAdd);
        appFrame.getContentPane().remove(prevPanelToRemove);
        appFrame.getContentPane().invalidate();
        appFrame.getContentPane().validate();
        
        
    }

using this method you should just send the panel you want to use and the previous panel that is already on the frame使用此方法,您应该只发送要使用的面板和框架上已经存在的前一个面板

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM