Java - How to make a set of JInternalFrame indepen

2019-08-10 14:38发布

问题:

I'm programming a short Paint program like and I'm trying to make an MDI architecture for it. To make that happen, I used JInternalFrame inside a JDesktopPane. Although I kind of obtain multiple frames, there are not really working properly. Basically, if I have 2 JInternalFrame I can draw only on the last one. The other one seems to be disabled.

Here is a short video illustrating the problem. http://bit.ly/9ydiwM

Here are some part of the code.

Panneau.java
public class Panneau extends JDesktopPane
{

    /** La liste de fenêtres ouvertes */
    private static ArrayList<Cadre> cadres;

    /** Le pannel comportant la liste des formes à dessiner*/
    private Pannel pannel;

    /** La barre d'outils */
    private ToolBox toolBox;

    public Panneau()
    {

        this.setLayout(new BorderLayout());

        // Initialisations des listes de cadres
        cadres = new ArrayList<Cadre>();

        // En haut ToolBox
        toolBox = new ToolBox();
        this.add(toolBox, BorderLayout.NORTH);

        **// Intialisation de la première internal frame
        Cadre cadre = new Cadre();
        this.add(cadre, BorderLayout.CENTER);**

        cadres.add(cadre);

        // Ajout du pannel à gauche
        pannel = new Pannel();

        this.add(pannel, BorderLayout.WEST);

    }

    /**
     * Crée une nouvelle fenêtre de dessin
     * 
     */
    **public void createNewInternalFrame()
    {
        Cadre cadre = new Cadre();
        this.add(cadre, BorderLayout.CENTER);

        cadres.add(cadre);
    }**
}

public class Cadre extends JInternalFrame
{
    /** Largeur par d'une fenêtre interne */
    private int width;

    /** Hauteur d'une fenêtre interne */
    private int height;

    /** Titre d'une fenêtre interne */
    private String title;

    /** Toile associée à la fenêtre interne */
    private Toile toile;

    public Cadre()
    {
        width = 400;
        height = 400;
        title = "Form";

        toile = new Toile();

        this.setTitle(title);

        this.setSize(width, height);

        this.setEnabled(true);

        this.setResizable(true);

        this.setAutoscrolls(true);

        this.setClosable(true);

        this.setIconifiable(true);

        this.setDoubleBuffered(true);

        this.setContentPane(toile);

        this.setVisible(true);

        this.pack();    
    }
}

Basically, Panneau is the main Window that contains all the differents parts of the GUI. I can create as much JInternalFrame that I want, using : Panneau.createNewInternalFrame(). Toile is basically where I draw my shapes.

Any idea ?

Thanks

回答1:

You are using the JDesktopPane incorrectly. The desktop pane "does not" use a layout manager on purpose. This allows you to add multiple internal frames and drag them around individually.

Your class should NOT be extending JDesktopPane since you are not adding any new functionality to it.

So in general all you logic should still deal with the JFrame. That is:

a) you create your toolbar and add it to the NORTH of the content pane.

b) you create your desktop pane and add it to the CENTER of the content pane

c) your create your internal frames and and them to the desktop pane

Read the Swing tutorial for examples of using internal frames.



回答2:

I think the problem is that you're overwriting the CENTER orientation in BorderLayout. The effect of this is that the two boxes are essentially the second added box, which plays havoc with the component which simply isn't designed for it. So, the hierarchy has two different elements, and the layout manager has the second element set the CENTER component, and the layout manager probably handles a fair bit of stuff.

Note the following code in BorderLayout (yes, it's deprecated, but it gets called by the non-deprecated method anyway):

/**
 * @deprecated  replaced by <code>addLayoutComponent(Component, Object)</code>.
 */
@Deprecated
public void addLayoutComponent(String name, Component comp) {
  synchronized (comp.getTreeLock()) {
    /* Special case:  treat null the same as "Center". */
    if (name == null) {
        name = "Center";
    }

    /* Assign the component to one of the known regions of the layout.
     */
    if ("Center".equals(name)) {
        center = comp;
    } else if ("North".equals(name)) {
        north = comp;
    } else if ("South".equals(name)) {
        south = comp;
    } else if ("East".equals(name)) {
        east = comp;
    } else if ("West".equals(name)) {
        west = comp;
    } else if (BEFORE_FIRST_LINE.equals(name)) {
        firstLine = comp;
    } else if (AFTER_LAST_LINE.equals(name)) {
        lastLine = comp;
    } else if (BEFORE_LINE_BEGINS.equals(name)) {
        firstItem = comp;
    } else if (AFTER_LINE_ENDS.equals(name)) {
        lastItem = comp;
    } else {
        throw new IllegalArgumentException("cannot add to layout: unknown constraint: " + name);
    }
  }
}

It would be cool to use a proper layout manager to do the job, but they aren't designed for mucking with MDI windows.



回答3:

See How to Use Internal Frames and InternalFrameDemo.