Domanda

Ho creato un'applicazione swing con diversi JinternalFrames che viene aggiunto a un jdesktoppane sull'evento di un clic del mouse.Voglio Solo un'istanza del Stessa fotogramma interno per essere presente sul desktoppane. Non voglio che la stessa cornice venga visualizzata due volte quando l'utenteApre il telaio.Se il fotogramma è già aperto, dovrebbe apparire un messaggio di errore.!

Grazie mille :)

È stato utile?

Soluzione

Non preoccuparti di un anti-modello di Singleton.Invece semplicemente dare il campo di classe A JinternalFrame e creare un'istanza del tuo jinternalframe nel costruttore della tua classe o in dichiarazione variabile e non crearne uno nuovo sul clic del mouse, ma piuttosto mostra quello che hastato già creato.Ad esempio nel metodo toppressato, chiamare semplicemente myInternalFrame.setVisible(true).In questo modo, se fosse invisibile, ora è visibile, e se è già visibile, allora è ancora visibile e invariato.Semplice e diretto.

Altri suggerimenti

.

Ho creato un'applicazione Swing con diversi JinternalFrames ...

e

.

Voglio solo un'istanza della stessa struttura interna ...

Quindi applica il Singleton Pattern a ciascuna delle tue classi JinternalFrame Child Blasses. Sarai in grado di utilizzare solo un'istanza di una classe se la classe è conforme al modello Singleton.

Hovercraftfullofeeels, un uomo dopo il mio cuore, dice di non usare il modello singleton e non sono d'accordo. Singleton può essere un modo molto potente per semplificare le cose ed evitare il codice della caldaia, mantenendo il sistema forte e facile da mantenere. Inoltre, il suo suggerimento che mostra semplicemente un JInternalFrame già aperto è difettoso in due modi: 1) è difficile da gestire sul livello del codice e lascia il tuo sistema fragile e difficile da aggiornare in futuro e 2) quando chiude gli utenti finali E riapri una schermata, si aspettano un'istanza nuova , con dati aggiornati e nuovi componenti di zecca. Non si prevede che la chiusura e la riapertura siano le stesse casi.

L'altro rispondente dice di usare Singleton, ma non fornisce un esempio concreto. Quindi, ti darò il codice che ho sviluppato per la mia applicazione:

Questa è la classe per il Singleton JInternalFrame (Nota: il motivo per cui estende JPanel è in modo che io possa usurarlo facilmente in un GUI Builder):

public abstract class VPanel extends JPanel {

    public static JDesktopPane desktopPane;

    public static void installDesktopPane(JDesktopPane desktopPane) {
        VPanel.desktopPane = desktopPane;
    }

    public VPanel(String name) {
        this.name = name;
        if(desktopPane == null)
            throw new IllegalStateException("VPanel is being used with a null desktop pane.");
    }
    static LinkedHashMap<Class, VPanel> self_panel_map;

    JInternalFrame self_jif;
    protected VPanel self_panel;
    boolean loading;
    boolean showing;

    public final String name;
    public abstract void init();

    public static VPanel showPanel(VPanel newInstance) {
        if(self_panel_map == null)
            self_panel_map = new LinkedHashMap<>();
        Class newInstanceClass = newInstance.getClass();
        if(self_panel_map.containsKey(newInstanceClass)) {
            VPanel oldInstance = self_panel_map.get(newInstanceClass);
            oldInstance.showing = oldInstance.self_jif.isVisible();
            if(!oldInstance.loading && !oldInstance.showing) {
                newInstance.loading = true;
                newInstance.self_panel = newInstance;
                newInstance.self_jif = new JInternalFrame(newInstance.name, true, true, true, true);
                newInstance.self_panel.init();
                self_panel_map.put(newInstanceClass, newInstance);
                return newInstance;
            } else if(oldInstance.showing) {
                try {
                    oldInstance.self_jif.setSelected(true);
                } catch (PropertyVetoException e) {
                    handleError(e);
                }
            }
            return oldInstance;
        } else {
            newInstance.loading = true;
            newInstance.self_panel = newInstance;
            newInstance.self_jif = new JInternalFrame(newInstance.name, true, true, true, true);
            newInstance.self_panel.init();
            self_panel_map.put(newInstanceClass, newInstance);
            return newInstance;
        }
    }

    public void setVisible() {

        self_jif.add(self_panel);
        self_jif.pack();
        self_jif.setVisible(true);
        desktopPane.add(self_jif);
        centerJIF();
        try {
            self_jif.setSelected(true);
        } catch (PropertyVetoException e) {
            handleError(e);
        }
        loading = false;
    }

    private static void handleError(Exception e) {
        e.printStackTrace();
    }

    public void centerJIF() {
        Dimension desktopSize = desktopPane.getSize();
        Dimension JInternalFrameSize = self_jif.getSize();
        int width = (desktopSize.width - JInternalFrameSize.width) / 2;
        int height = (desktopSize.height - JInternalFrameSize.height) / 2;
        self_jif.setLocation(width, height);
    }
}
.

Ecco un codice di esempio che lo implente:

public static void main(String[] args) {
    JFrame jf = new JFrame("MainFrame");
    JDesktopPane jdp = new JDesktopPane();
    jf.setExtendedState( jf.getExtendedState()|JFrame.MAXIMIZED_BOTH );

    VPanel.installDesktopPane(jdp); // This only needs to happen once throughout the entire application lifecycle.

    JMenuBar menuBar = new JMenuBar();
    JMenu menu = new JMenu("Panels");
    JMenuItem menuItem = new JMenuItem("Open Test Panel");
    menuItem.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            Test_VPanel.showPanel(new Test_VPanel()); // Every time you show the panel, you create a new instance.
            // But this new instance is only used if it is needed. The init() method is only called if it is going
            // To show a new instance.
        }
    });
    menu.add(menuItem);
    menuBar.add(menu);
    jf.setJMenuBar(menuBar);


    jf.setContentPane(jdp);

    jf.setVisible(true);
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

static class Test_VPanel extends VPanel {

    public Test_VPanel() {
        super("Test Panel");
    }

    @Override
    public void init() {
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();

        JLabel label = new JLabel("JLabel");
        JTextField textField = new JTextField();

        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1;
        gbc.gridwidth = 1;
        gbc.gridy = 0;
        gbc.insets = new Insets(4,4,4,4);
        add(label, gbc);

        gbc.gridy = 1;
        add(textField, gbc);

        setVisible(); // This needs to be called at the end of init()
    }
}
.

Non ho mai avuto bisogno del metodo di chiamata per fare nulla con la nuova istanza, ma semplicemente in caso, showPanel restituisce l'istanza utilizzata, se è la vecchia istanza o la nuova istanza. Quindi, se hai bisogno di fare qualcosa con l'istanza che faresti questo:

Test_VPanel panel = Test_VPanel.showPanel(new Test_VPanel());
panel.something();
...
.

La vita è stata molto più facile per me una volta deciso di andare a questa strada con Singleton Jifs. Altamente raccomandato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top