'How can I open a JInternalFrame inside a panel (inside parent) from another child JInternalFrame?
I have 3 frames, Main (as the parent) and 2 JInternalFrames (F1 and F2 as children). When a button (inside parent) is pressed, I make an instance of F1 and send it as a parameter to ShowIntrlFrame() so F1 can be displayed inside frmContainter. My question here is, how can I open F2 from F1 and display it on frmContrainer (which is in the Main frame)?
public class Main extends javax.swing.JFrame{
public Main(){
}
private void btnOpenFrmActionPerformed(java.awt.event.ActionEvent evt) {
F1 f1 = new F1();
frmContainer(f1);
}
}
public void ShowIntrlFrame(JInternalFrame f){
f.setSize(1100, 620);
f.setLocation(0, 0);
f.setVisible(true);
frmContainer.removeAll();
frmContainer.add(f, BorderLayout.CENTER);
frmContainer.revalidate();
frmContainer.repaint();
}
Solution 1:[1]
What I would do is follow a delegation pattern via dependency injection.
This is, I would "delegate" the functionality need to generate and show the window to some other class and then "inject" that into the workflow as required
I'd start with a concept of a "window manager"...
public interface WindowManager {
enum Window {
FIRST, SECOND;
}
public void openWindow(Window window);
}
At the moment, this is pretty basic and just opens a specified window. The nice thing about this, is we don't care if it's a JInternalFrame or JFrame which gets generated, that's not the callers responsibility.
Next, we make a implementation which supports JDesktopPane
public class DesktopWindowManage implements WindowManager {
private JDesktopPane desktopPane;
private int initialX = 0;
private int initialY = 0;
public DesktopWindowManage(JDesktopPane desktopPane) {
this.desktopPane = desktopPane;
}
public JDesktopPane getDesktopPane() {
return desktopPane;
}
@Override
public void openWindow(Window window) {
JInternalFrame frame = new JInternalFrame(window.name(), true, true, true, true);
frame.setContentPane(makeContentFor(window));
frame.pack();
frame.setLocation(initialX, initialY);
frame.setVisible(true);
try {
frame.setSelected(true);
} catch (PropertyVetoException ex) {
}
desktopPane.add(frame);
frame.toFront();
initialX += 20;
initialY += 20;
}
protected JPanel makeContentFor(Window window) {
switch (window) {
case FIRST: return new FirstPane(this);
case SECOND: return new SecondPane();
}
return null;
}
}
Now, important to note, this class is acting as kind of factory, in that it's generating the content view and JInternalFrame. I'd probably consider making a "content factory" which could be injected into this which would then create the content based on the desired destination, but that's probably getting a little more complicated then is required right now.
Now, before you ask, the actual content is based on JPanel, for example...
public class FirstPane extends JPanel {
public FirstPane(WindowManager windowManager) {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = gbc.REMAINDER;
add(new JLabel("I am first"), gbc);
JButton showSecond = new JButton("Show second");
showSecond.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
windowManager.openWindow(WindowManager.Window.SECOND);
}
});
add(showSecond, gbc);
}
}
public class SecondPane extends JPanel {
public SecondPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
add(new JLabel("I am second"));
}
}
Why? Because it's a JPanel can be added to any container and, generally, we don't care if it's a JInternalFrame or JFrame.
And finally, some kind of "starting point"....
public class MainPane extends JPanel {
private WindowManager windowManager;
private JDesktopPane desktopPane;
public MainPane() {
setLayout(new BorderLayout());
JButton open = new JButton("Open");
desktopPane = new JDesktopPane() {
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
};
windowManager = new DesktopWindowManage(desktopPane);
add(open, BorderLayout.NORTH);
add(desktopPane);
open.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
windowManager.openWindow(WindowManager.Window.FIRST);
}
});
}
}
Runnable example...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface WindowManager {
enum Window {
FIRST, SECOND;
}
public void openWindow(Window window);
}
public class DesktopWindowManage implements WindowManager {
private JDesktopPane desktopPane;
private int initialX = 0;
private int initialY = 0;
public DesktopWindowManage(JDesktopPane desktopPane) {
this.desktopPane = desktopPane;
}
public JDesktopPane getDesktopPane() {
return desktopPane;
}
@Override
public void openWindow(Window window) {
JInternalFrame frame = new JInternalFrame(window.name(), true, true, true, true);
frame.setContentPane(makeContentFor(window));
frame.pack();
frame.setLocation(initialX, initialY);
frame.setVisible(true);
try {
frame.setSelected(true);
} catch (PropertyVetoException ex) {
}
desktopPane.add(frame);
frame.toFront();
initialX += 20;
initialY += 20;
}
protected JPanel makeContentFor(Window window) {
switch (window) {
case FIRST: return new FirstPane(this);
case SECOND: return new SecondPane();
}
return null;
}
}
public class MainPane extends JPanel {
private WindowManager windowManager;
private JDesktopPane desktopPane;
public MainPane() {
setLayout(new BorderLayout());
JButton open = new JButton("Open");
desktopPane = new JDesktopPane() {
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
};
windowManager = new DesktopWindowManage(desktopPane);
add(open, BorderLayout.NORTH);
add(desktopPane);
open.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
windowManager.openWindow(WindowManager.Window.FIRST);
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
public class FirstPane extends JPanel {
public FirstPane(WindowManager windowManager) {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = gbc.REMAINDER;
add(new JLabel("I am first"), gbc);
JButton showSecond = new JButton("Show second");
showSecond.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
windowManager.openWindow(WindowManager.Window.SECOND);
}
});
add(showSecond, gbc);
}
}
public class SecondPane extends JPanel {
public SecondPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
add(new JLabel("I am second"));
}
}
}
But wait, there's more...
Currently, if you tap "Open" or "Show second" multiple times, you get a bunch of new windows. This may or may not be desirable, but could be easily fixed via the WindowManager, in fact, you could create different WindowManagers based on your needs, for example...
public class DesktopWindowManage implements WindowManager {
private JDesktopPane desktopPane;
private int initialX = 0;
private int initialY = 0;
private Map<Window, JInternalFrame> windowCache = new HashMap<>();
public DesktopWindowManage(JDesktopPane desktopPane) {
this.desktopPane = desktopPane;
}
public JDesktopPane getDesktopPane() {
return desktopPane;
}
@Override
public void openWindow(Window window) {
JInternalFrame frame = windowCache.get(window);
if (frame == null) {
frame = new JInternalFrame(window.name(), true, true, true, true);
frame.setContentPane(makeContentFor(window));
windowCache.put(window, frame);
frame.pack();
frame.setLocation(initialX, initialY);
frame.setVisible(true);
desktopPane.add(frame);
initialX += 20;
initialY += 20;
}
try {
frame.setSelected(true);
} catch (PropertyVetoException ex) {
}
frame.toFront();
}
protected JPanel makeContentFor(Window window) {
switch (window) {
case FIRST:
return new FirstPane(this);
case SECOND:
return new SecondPane();
}
return null;
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MadProgrammer |

