Разрешить только один экземпляр JInternalFrame - PullRequest
2 голосов
/ 11 марта 2012

Я создал приложение Swing с несколькими JInternalFrames , которое добавляется в JDesktopPane при щелчке мышью.Я хочу, чтобы только один экземпляр того же самого Внутреннего фрейма присутствовал на Рабочем столе. Я не хочу, чтобы один и тот же фрейм появлялся дважды, когда пользователь открывает фрейм,Если рамка уже открыта, должно появиться сообщение об ошибке.!

Большое спасибо:)

Ответы [ 3 ]

6 голосов
/ 11 марта 2012

Я создал приложение Swing с несколькими JInternalFrames ...

и

Мне нужен только один экземпляр одного и того же Внутреннего кадра ...

Поэтому примените шаблон Singleton к каждому из ваших дочерних классов JInternalFrame. Вы сможете использовать только один экземпляр класса, если этот класс соответствует шаблону синглтона.

5 голосов
/ 11 марта 2012

Не беспокойтесь об одноэлементном анти-паттерне.Вместо этого просто дайте вашему классу поле JInternalFrame и создайте один экземпляр вашего JInternalFrame в конструкторе вашего класса или при объявлении переменной, и не создавайте новый по щелчку мыши, а скорее отображайте тот, который былуже создан.Например, в методе mousePressed просто вызовите myInternalFrame.setVisible(true).Таким образом, если он был невидим, теперь он видим, а если он уже виден, то он все еще видим и неизменен.Просто и понятно.

1 голос
/ 20 мая 2014

HovercraftFullOfEeels, человек по душе, говорит, что не следует использовать паттерн Синглтона, и я собираюсь не согласиться. Singleton может быть очень мощным способом упорядочить вещи и избежать стандартного кода, сохраняя при этом систему сильной и простой в обслуживании. Кроме того, его предположение о том, что вы просто отображаете уже открытую JInternalFrame, имеет два недостатка: 1) это трудно поддается управлению на уровне кода и оставляет вашу систему хрупкой и ее трудно обновлять в будущем; 2) когда пользователи закрывают и снова открывают экран, они ожидают новый экземпляр с обновленными данными и совершенно новыми компонентами. Не ожидается, что закрытие и повторное открытие будут одинаковыми.

Другой отвечающий говорит, что использует Singleton, но не дает конкретного примера. Итак, я собираюсь дать вам код, который я разработал для моего приложения:

Это класс для Singleton JInternalFrame (примечание: причина, по которой он расширяется JPanel, заключается в том, что я могу легко использовать его в 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);
    }
}

Вот пример кода, который бы его реализовал:

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

Мне никогда не нужен вызывающий метод, чтобы что-то делать с новым экземпляром, но просто incase, showPanel возвращает используемый экземпляр, будь то старый или новый экземпляр. Итак, если вам нужно что-то сделать с экземпляром, вы должны сделать это:

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

Жизнь стала намного легче для меня, когда я решил пойти по этому пути с одиночными JIF. Настоятельно рекомендуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...