简体   繁体   中英

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

I am working on a Java Swing desktop application project. The application has about 15 GUI pages. I can use Layered Panes and Tabbed Panes to put all the GUI components in one class. 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. 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? Since the sub-projects contain GUI pages each needs to have a JFrame. How I can switch back and force between JFrame 1 to JFrame 2 and make one visible and the other invisible? This question shows how to create new JFrames. But did not show how switch back and forth among the JFrames.

... The application has about 15 GUI pages. I can use Layered Panes and Tabbed Panes to put all the GUI components in one class. 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(...) :

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:

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

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.

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.

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)
  2. You can get rid of the old JFrame with dispose()

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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