I've created a Swing application with several JInternalFrames which gets added to a JDesktopPane on the event of a mouse click. I want only one instance of the same Internal frame to be present on the DesktopPane. I dont want the same frame to appear twice when the user opens the frame. If the frame is already open, then a error message should appear.!
我创建了一个Swing应用程序,其中有几个jinternalframe,在鼠标单击事件时添加到一个JDesktopPane中。我只希望在DesktopPane中显示一个相同的内部框架的实例。我不想让同一帧在用户打开框架时出现两次。如果框架已经打开,那么就会出现错误消息。
Thanks a lot :)
非常感谢:)
3 个解决方案
#1
5
Don't bother with a singleton anti-pattern. Instead simply give your class a JInternalFrame field and create one instance of your JInternalFrame in your class's constructor or at variable declaration, and don't create a new one on mouse click, but rather display the one that has been already created. For instance in the mousePressed method, simply call myInternalFrame.setVisible(true)
. This way, if it was invisible, now it's visible, and if it's already visible, then it's still visible and unchanged. Simple and straightforward.
不要麻烦于单例反模式。相反,只需给类一个JInternalFrame字段,并在类的构造函数或at变量声明中创建一个JInternalFrame实例,不要在鼠标单击时创建一个新的字段,而是显示已经创建的那个。例如,在mousePressed方法中,只需调用internmyalframe . setvisible (true)。这样,如果它是不可见的,现在它是可见的,如果它是可见的,那么它仍然是可见的,不变的。简单明了。
#2
6
I've created a Swing application with several JInternalFrames...
我创建了一个包含几个jinternalframe的Swing应用程序……
and
和
I want only one instance of the same Internal frame...
我只想要同一个内部框架的一个实例…
So apply the Singleton Pattern to each of your JInternalFrame child classes. You will be able to use only one instance of a class if the class is conforming to the singleton pattern.
因此,将单例模式应用到每个JInternalFrame子类。如果类符合单例模式,则只能使用类的一个实例。
#3
1
HovercraftFullOfEeels, a man after my own heart, says not to use the Singleton pattern, and I'm going to disagree. Singleton can be a very powerful way to streamline things and avoid boilerplate code, while keeping the system strong and easy to maintain. Further, his suggestion that you simply display an already-opened JInternalFrame
is flawed in two ways: 1) That is difficult to manage on the code level and leaves your system fragile and difficult to update in the future and 2) When end-users close and reopen a screen, they expect a new instance, with refreshed data and brand new components. It is not expected that closing and reopening would be the same instances.
在我的内心,一个人说,不要使用单例模式,我将不同意。单例可以是一种非常强大的方式来简化事情和避免样板代码,同时保持系统的强大和易于维护。进一步说,他的建议,你简单地显示一个打开JInternalFrame在两个方面是有缺陷的:1)很难管理系统在代码级别和叶子脆弱,难以在未来更新和2)终端用户关闭并重新打开屏幕时,他们期望一个新的实例,刷新数据和全新的组件。预期关闭和重新开放不会是同样的情况。
The other answerer says to use Singleton, but gives no concrete example. So, I'm going to give you the code I've developed for my application:
另一个回答者说要使用单例,但是没有给出具体的例子。我将给你们我为我的应用开发的代码:
This is the class for the Singleton JInternalFrame
(note: the reason it extends JPanel
is so that I can easily use it in a GUI Builder):
这是单例JInternalFrame的类(注意:它扩展JPanel的原因是为了方便我在GUI构建器中使用它):
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);
}
}
Here is a sample code that would implement it:
下面是实现它的示例代码:
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()
}
}
I never need the calling method to do anything with the new instance, but just incase, showPanel
returns the instance used, whether it's the old instance or the new instance. So, if you need to do something with the instance you would do this:
我从来不需要调用方法来对新实例进行任何操作,但只要是incase, showPanel就会返回所使用的实例,不管它是旧实例还是新实例。所以,如果你需要做一些事情你会这样做:
Test_VPanel panel = Test_VPanel.showPanel(new Test_VPanel());
panel.something();
...
Life has been a lot easier for me once I decided to go this route with Singleton JIFs. Highly recommended.
一旦我决定用Singleton JIFs走这条路,我的生活就变得轻松多了。强烈推荐。
#1
5
Don't bother with a singleton anti-pattern. Instead simply give your class a JInternalFrame field and create one instance of your JInternalFrame in your class's constructor or at variable declaration, and don't create a new one on mouse click, but rather display the one that has been already created. For instance in the mousePressed method, simply call myInternalFrame.setVisible(true)
. This way, if it was invisible, now it's visible, and if it's already visible, then it's still visible and unchanged. Simple and straightforward.
不要麻烦于单例反模式。相反,只需给类一个JInternalFrame字段,并在类的构造函数或at变量声明中创建一个JInternalFrame实例,不要在鼠标单击时创建一个新的字段,而是显示已经创建的那个。例如,在mousePressed方法中,只需调用internmyalframe . setvisible (true)。这样,如果它是不可见的,现在它是可见的,如果它是可见的,那么它仍然是可见的,不变的。简单明了。
#2
6
I've created a Swing application with several JInternalFrames...
我创建了一个包含几个jinternalframe的Swing应用程序……
and
和
I want only one instance of the same Internal frame...
我只想要同一个内部框架的一个实例…
So apply the Singleton Pattern to each of your JInternalFrame child classes. You will be able to use only one instance of a class if the class is conforming to the singleton pattern.
因此,将单例模式应用到每个JInternalFrame子类。如果类符合单例模式,则只能使用类的一个实例。
#3
1
HovercraftFullOfEeels, a man after my own heart, says not to use the Singleton pattern, and I'm going to disagree. Singleton can be a very powerful way to streamline things and avoid boilerplate code, while keeping the system strong and easy to maintain. Further, his suggestion that you simply display an already-opened JInternalFrame
is flawed in two ways: 1) That is difficult to manage on the code level and leaves your system fragile and difficult to update in the future and 2) When end-users close and reopen a screen, they expect a new instance, with refreshed data and brand new components. It is not expected that closing and reopening would be the same instances.
在我的内心,一个人说,不要使用单例模式,我将不同意。单例可以是一种非常强大的方式来简化事情和避免样板代码,同时保持系统的强大和易于维护。进一步说,他的建议,你简单地显示一个打开JInternalFrame在两个方面是有缺陷的:1)很难管理系统在代码级别和叶子脆弱,难以在未来更新和2)终端用户关闭并重新打开屏幕时,他们期望一个新的实例,刷新数据和全新的组件。预期关闭和重新开放不会是同样的情况。
The other answerer says to use Singleton, but gives no concrete example. So, I'm going to give you the code I've developed for my application:
另一个回答者说要使用单例,但是没有给出具体的例子。我将给你们我为我的应用开发的代码:
This is the class for the Singleton JInternalFrame
(note: the reason it extends JPanel
is so that I can easily use it in a GUI Builder):
这是单例JInternalFrame的类(注意:它扩展JPanel的原因是为了方便我在GUI构建器中使用它):
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);
}
}
Here is a sample code that would implement it:
下面是实现它的示例代码:
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()
}
}
I never need the calling method to do anything with the new instance, but just incase, showPanel
returns the instance used, whether it's the old instance or the new instance. So, if you need to do something with the instance you would do this:
我从来不需要调用方法来对新实例进行任何操作,但只要是incase, showPanel就会返回所使用的实例,不管它是旧实例还是新实例。所以,如果你需要做一些事情你会这样做:
Test_VPanel panel = Test_VPanel.showPanel(new Test_VPanel());
panel.something();
...
Life has been a lot easier for me once I decided to go this route with Singleton JIFs. Highly recommended.
一旦我决定用Singleton JIFs走这条路,我的生活就变得轻松多了。强烈推荐。