Reputation: 23
I am making a graphic program with swing that involves placing various panels with components on the frame. One of them is a panel with buttons that, when an option in an options menu is chosen, is entirely replaced with a different one that has different buttons. We've been thinking and it seems that the best way to do this would be to, each time the option is selected, to rebuild the frame from scratch.
This is the snippet of code in which I'm building the main panels:
import java.awt.Color;
import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import com.jtattoo.plaf.graphite.GraphiteLookAndFeel;
import com.nacher.calc.Main;
import com.nacher.calc.controller.Controller;
import net.miginfocom.swing.MigLayout;
/**
*
* @author chema && Sergio
* This Panel contains buttons and textbox to perform the calculator actions
*/
public class PanelCalculator extends JPanel implements PropertyChangeListener {
private static final long serialVersionUID = -8377215712645516042L;
private PanelNumbers panelNumbers;
private PanelScreen panelScreen;
private PanelOptions panelOptions;
private PanelScientific panelScientific;
public Controller controller;
public PanelCalculator(Controller controller) {
this.controller = controller;
//Initialize JTattoo Library
try{
UIManager.setLookAndFeel(new GraphiteLookAndFeel());
}catch(UnsupportedLookAndFeelException ulafe){
System.out.println("JTattoo Graphite failed to set");
}
this.setLayout(new MigLayout("wrap"));
buildComponents();
situateComponents();
//controller = new Controller();
controller.addPropertyChangeListener(panelScreen);//panelScreen escucha al controller
panelOptions.addPropertyChangeListener(controller);//controller escucha al panelOptions
panelNumbers.addPropertyChangeListener(controller);//controller escucha al panelNumbers
panelScreen.addPropertyChangeListener(controller);//controller escucha al panelScreen
}
private void buildComponents(){
this.setPreferredSize(new Dimension(210, 280));
this.setBorder(new EmptyBorder(0, 0, 0, 0));
panelOptions = new PanelOptions();
panelOptions.setBorder(new EmptyBorder(0, 0, 0, 0));
panelOptions.setPreferredSize(new Dimension(200, 50));
panelScreen = new PanelScreen();
panelScreen.setBorder(BorderFactory.createEtchedBorder());
panelScreen.setPreferredSize(new Dimension(200, 40));
panelScreen.setBackground(new Color(255, 255, 255));
panelNumbers = new PanelNumbers();
panelNumbers.setBorder(new EmptyBorder(0, 0, 0, 0));
panelNumbers.setPreferredSize(new Dimension(200, 185));
panelOptions.addPropertyChangeListener(panelScreen);//panelScreen escucha al panelOptions
panelNumbers.addPropertyChangeListener(panelScreen);//panelScreen escucha al panelNumbers
}
private void situateComponents(){
this.add(panelOptions, "span");
this.add(panelScreen, "span");
this.add(panelNumbers, "span" );
}
/**
* To build the Scientific Calculator
*/
private void buildScientific() {
//Instantiate the panelScientific
panelScientific = new PanelScientific();
panelScientific.setBorder(new EmptyBorder(0, 0, 0, 0));
panelScientific.setPreferredSize(new Dimension(200, 185));
//Reordering the Panel Calculator
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
String c = evt.getPropertyName();
if (c.equals(Constants.SET_CALC_SCIENTIFIC)) {
System.out.println("Set the Scientific Calculator");
buildScientific();
}
}
}
And this is the main class where we build the frame:
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import com.jtattoo.plaf.bernstein.BernsteinLookAndFeel;
import com.jtattoo.plaf.fast.FastLookAndFeel;
import com.jtattoo.plaf.graphite.GraphiteLookAndFeel;
import com.jtattoo.plaf.hifi.HiFiLookAndFeel;
import com.jtattoo.plaf.luna.LunaLookAndFeel;
import com.nacher.calc.controller.Controller;
import com.nacher.calc.ui.Constants;
import com.nacher.calc.ui.ImageConstants;
import com.nacher.calc.ui.PanelCalculator;
public class Main extends JFrame implements PropertyChangeListener {
private static final long serialVersionUID = -4136829057174783241L;
private static Main mySelf;
private static PanelCalculator panelCalc;
public static Controller controller;
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
controller = new Controller();
panelCalc = new PanelCalculator(controller);
controller.addPropertyChangeListener(panelCalc);
mySelf = new Main();
try {
mySelf.setTitle("Calculator");
mySelf.setLocationRelativeTo(null);
mySelf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mySelf.setIconImage(new ImageIcon(mySelf.getClass().getResource(ImageConstants.CALC_IMAGE_THREE)).getImage());
mySelf.getContentPane().add(panelCalc);
mySelf.setResizable(false);
mySelf.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.out.println("Quitting the application.");
}
});
mySelf.pack();
mySelf.setVisible(true);
controller.addPropertyChangeListener(mySelf);
}catch(Exception ex) {
System.out.println("The application could not run.");
System.out.println(ex.getMessage());
System.exit(-1);
}
}
What commands should I use to 'unbuild' the frame, then rebuild it from scratch? Is there a more efficient way to replace one panel with another?
Upvotes: 0
Views: 44
Reputation: 324167
The Card Layout
was designed for this type of functionality. It allows you to define multiple panels to share the same space of the frame. You then just specify which panel is currently displayed.
Read the section from the Swing tutorial on How to Use CardLayout for more information and working examples.
Upvotes: 5
Reputation: 356
I don't know if I totally get your problem, but if, that would be my solution (just a simple example):
public class Main extends JFrame{
public Main(){
setTitle("Calculator");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
Panels panels = new Panels();
add(panels, BorderLayout.CENTER);
setLocationRelativeTo(null);
pack();
setVisible(true);
}
}
.
public class Panels extends JPanel{
public JPanel p1, p2;
public Panels(){
p1 = new JPanel();
add(p1);
p2 = new JPanel();
add(p2);
//p1 and p2 might be more complex Components
//place them using your preferred LayoutManager
//(set their preferredSize etc.)
}
public void updateP1(JPanel np1){
remove(p1);
p1 = np1;
add(p1);
}
public void updateP2(JPanel np2){
remove(p2);
p2 = np2;
add(p2);
}
}
I think what you're looking for is the method remove(Component comp) of a JComponent, i.e. a JPanel. Hope that helps.
Upvotes: 3