开发者

Base and extended windows in Java using inheritance

I've got one class called WindowTemplate that is the base for other (more complex) windows. It is an abstract class and then I'm trying to use the "extend" trick to add more stuff开发者_如何学编程 to the new window, keeping the original "skeleton".

That is my problem though, because if I run WindowTemplate.createWindow(); or a_Welcome.createWindow(); (they should be point to the same thing), I get my "base" window. But when I run a_Welcome window = new a_Welcome(); (what should be the base + new stuff) I get only the extra bits that I added without the original features.

Here is my code:

package windows;

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

public abstract class WindowTemplate extends JFrame {

/**
 * Create the GUI and show it. For thread safety, this method should be
 * invoked from the event-dispatching thread.
 */
public static void createWindow() {

    JFrame myFrame = new JFrame("My first window");
    myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    myFrame.setVisible(true);
    myFrame.setSize(550, 450);
    myFrame.setLocationRelativeTo(null);

    // JLabel emptyLabel = new JLabel("");
    // emptyLabel.setPreferredSize(new Dimension(550, 450));

    // myFrame.getContentPane().setLayout(new CardLayout());
    // myFrame.getContentPane().add(emptyLabel, BorderLayout.CENTER);

    // myFrame.pack();

}

} 

the class with new window and some extra stuff (ignore a_):

package windows;

import java.awt.*;

import javax.swing.*;

public class a_Welcome extends WindowTemplate {

public a_Welcome() {

    JPanel area = new JPanel();

    JLabel text = new JLabel("One line another line and another line"); // , JLabel.CENTER);

    // text.setBounds(80, 400, 400, 50);
    add(area);

    // area.setLayout(null);
    area.add(text, new CardLayout());

    // area.add(text); // , BorderLayout.CENTER);

    Font font = new Font("SansSerif", Font.BOLD, 30);
    text.setFont(font);
    text.setForeground(Color.green);
    area.setBackground(Color.darkGray);
    area.setSize(550, 450);

}

}

// timer-after 5 seconds-go to the next window (countdown in the bottom right corner)

and the main:

package windows;

public class Launcher {

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() {

            // WindowTemplate.createWindow();
            // a_Welcome.createWindow();

             a_Welcome window = new a_Welcome();
             window.setVisible(true);
        }
    });

}

}

Thanks for your help!


Static method createWindow() always creates a new JFrame which is not a superclass of the WindowTemplate. Constructor of the a_Window is adding components to the WindowTemplate which hasn't been initialized since the static createWindow() creates an independent frame.

I would suggest you to change the static createWindow() into WindowTemplate constructor and try running main once again.

package windows;

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

public abstract class WindowTemplate extends JFrame {

/**
 * Create the GUI and show it. For thread safety, this method should be
 * invoked from the event-dispatching thread.
 */
public WindowTemplate () {

    JFrame myFrame = new JFrame("My first window");
    myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    myFrame.setVisible(true);
    myFrame.setSize(550, 450);
    myFrame.setLocationRelativeTo(null);

    // JLabel emptyLabel = new JLabel("");
    // emptyLabel.setPreferredSize(new Dimension(550, 450));

    // myFrame.getContentPane().setLayout(new CardLayout());
    // myFrame.getContentPane().add(emptyLabel, BorderLayout.CENTER);

    // myFrame.pack();

}

}


You have another JFrame defined in the static createWindow() method. This means that you are adding the components to this frame that is scoped to the createWindow() method only and in the constructor you are adding to the a_Welcome instance.

You should do something like this

public class BaseWindow() {

  //Constructor
  public BaseWindow() {
    init();
  }

  public void init() {
    //add basic components
  }
}


public class SubClassWindow() {
  public SubClassWindow() {
    super();
  }

  @Override
  public void init() {
    super.init(); //important so you get the base stuff
    //add other components
  }
}

Code not tested.


Another approach you might consider would be to have a JFrame that is just a wrapper and compose the window by adding a panel. Let's say you want a toolbar at the top of every window you're creating. Each window would have different buttons on the toolbar and a different set of components at the bottom. This way you are doing composition instead of inheritance, because inheritance can get ugly later on. (For discussions on that point, see this, this, and this for starters)

That would look something like:

public interface AppPanel {
  List<JButton> getToolbarButtons();
  boolean okToClose();
  JPanel getGui();
}

public MyPanel extends JPanel implements AppPanel {
  //standard swing components stuff set up here

  public List<JButton> getToolbarButtons() {
    //set up buttons and their actions
    return buttonList;
  }

  public boolean okToClose() {
    //ask user if they want to save, etc.
    return true;
  }

  public JPanel getGui() {
    return this;
  }
}

public AppFrame extends JFrame {
  private AppPanel panel;

  public static AppFrame createFrame(AppPanel panel) {
    AppFrame frame = new AppFrame(panel);
    return frame;
  }

  public AppFrame(AppPanel panel) {
    super();
    this.panel = panel;
    add(panel.getGui(), someLayoutConstraints);

    panel.getToolbarButtons(); //do stuff with the buttons

    //...
    this.addWindowListener(new WindowAdapter() {
      public void WindowClosing(WindowEvent e) {
        if (panel.isOkToClose()) {
          setVisible(false);
        }
      }
    });
  }


}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜