I am new to Jframes and I wanted to design a window with a textbox and two buttons. I am able to get this working except for the scrollbar part.
I have written the below piece of code to enable scrollbar to the textarea.
private JTextArea outputPane;
outputPane = new JTextArea();
outputPane.setColumns(20);
outputPane.setRows(5);
outputPane.setFont(new Font("Monospaced", Font.PLAIN, 18));
outputPane.setBounds(12, 13, 408, 189);
contentPane.add(outputPane);
JScrollPane scrollPane = new JScrollPane(outputPane);
jScrollPane1.setBounds(399, 13, 21, 189);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
Now the problem is I am getting a disabled scrollbar on the window but I cannot see my Text Area.
Please help me out with the problem. I even tried using WindowsBuilder but I cannot figure it out.
Detailed explanation with the corrected code will be appreciated as I am still in the learning stage.
Thanks in advance.
Start by having a look at Laying Out Components Within a Container and How to Use Scroll Panes and How to Use Text Areas probably wouldn't hurt
Now the problem is I am getting a disabled scrollbar on the window but I cannot see my Text Area.
The likely problem is, you are seeing your JTextArea, the "disabled" scroll bar is simply because you're using scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, which will always display the scroll bar, even when there is nothing to be scrolled, so it probably looks empty.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
// Swing is not thread safe, so need to get started in the
// Event Dispatching Thread before we do anything
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
// I simply hate the default look and feel
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
// Always better to create an instance of a window
// to display you content then to extend from one
// directly...
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
// Our main UI, I do it this way so I'm not locked into a single
// use case and can decide how I want to use the view
public class TestPane extends JPanel {
public TestPane() {
// The default layout is a FlowLayout, so we want to change
// this will allow the main component to occupy the whole
// available space
setLayout(new BorderLayout());
// Providing "sizing" hints, 10 rows, 20 columns, this is
// platform independent, so it will size accordingly
JTextArea ta = new JTextArea(10, 20);
JScrollPane sp = new JScrollPane(ta);
add(sp);
}
}
}
Related
Background
I want to create a GUI application using the java swing library. For layout I require it to be a GridLayout as the program outline requires this.
Aim
To render a panel with text inside it.
What I have tired
Using setBounds to move the text - this worked and the text did render, however it does not work with the GridLayout therefore does not meet the required specs.
Reading atricles and documentation on GridLayout and rendering of JLabels - Tried the examples - failed.
Using intellij debugger - results show the JLabel is not null, and the text is set to the correct value, along with the enabled and visible properties being true.
Increasing and decreasing GirdLayout rows and columns - failed.
Altering the size of the panel - failed.
Changing the foreground colour to something like green - failed.
Code
public class MainPanel extends JPanel {
public MainPanel(JFrame frame) {
setBounds(40,40,200,200);
setBackground(Color.BLUE);
JLabel label = new JLabel("Hello World", SwingConstants.CENTER);
label.setFont(new Font("Tahoma", Font.PLAIN, 25));
label.setVisible(true);
add(label);
setLayout(new GridLayout(1, 1));
}
}
Result
Conclusion
As you can see, the panel does render (the blue square), however there is no text inside of it. I'm rather confused as code very similar to this has worked on aother project, and there is no obvious reason this shouldn't work.
Your code is essentially OK with the provisos I mentioned. Proof: (obviously you can separate out your own class as a top level one later):
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class F extends JFrame {
private void setGui() {
try {
setLocation(0, 100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setContentPane(new MainPanel());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
EventQueue.invokeAndWait(() -> {
F f = new F();
f.setGui();
f.setSize(200, 200);
f.setVisible(true);
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MainPanel extends JPanel {
public MainPanel() {
setLayout(new GridLayout(1, 1));
setBounds(40,40,200,200);
setBackground(Color.BLUE);
JLabel label = new JLabel("Hello World", SwingConstants.CENTER);
label.setFont(new Font("Tahoma", Font.PLAIN, 25));
add(label);
}
}
When running below simple app and changing font anti-aliasing (WIN+R "sysdm.cpl" -> System Properties -> Advanced -> Performance Settings -> Smooth edges of screen fonts) one can see that the JTextArea gets the wrong font (and stays with it also if toggle anti-aliasing again):
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class Main
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
JPanel mainPanel = new JPanel();
JLabel label = new JLabel("labelMessage:");
mainPanel.add(label);
final JTextArea textArea = new JTextArea("textAreaMessage")
{
// #Override
// public void setFont(Font f)
// {
// super.setFont(label.getFont());
// }
};
textArea.setEditable(false);
textArea.setOpaque(false);
textArea.setFont(label.getFont());
mainPanel.add(textArea);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setVisible(true);
}
}
Only, when uncommenting the override of setFont it works like one would expect.
When setting there a breakpoint one can see that when the font anti-aliasing is changed there is a AATextListener fired:
Where at some point the defaults are installed:
editor.setFont(UIManager.getFont(prefix /*TextArea*/ + ".font"));
So it is clear why it is happening but I do not know how to solve it in a good fashion.
Possible solutions:
Override the methods like shown above in the code
Use e.g. -Dswing.useSystemFontSettings=false (or -Dswing.aatext=true or awt.useSystemAAFontSettings) BUT then the font looks ugly so not acceptable without further enhancements
Set via UIManager the defaults
Remove/disable the listener? Seems to be hard coded and not be doable easy?
or 3. could be a solution but would require much work in a big legacy app.
NOTE: This is just a simple example. In our app the problem is much bigger as not only set fonts are lost, but almost everything, like borders of buttons, the custom ComponentUIs etc. And the described way how to reproduce it was just to have it easy reproducible, means we encounter this issue also spontaneously when e.g. the app runs for some hours. We then see that some windows event is firing the listener and destroying the look and feel of our app (often the PC was not used at all for almost an hour when this suddenly happens).
Maybe I will also ask the OpenJDK community the next days, as well. If so, I will link the ticket ID here.
Windows version: Windows Enterprise 10 Version 20H2 (Build 19042.1348)
Java version: zulu11.50.19-ca-jdk11.0.12-win_x64
Demo which listens for change like proposed by #VGR. When font anti aliasing is changed the UI will be re-rendered.
import java.awt.Toolkit;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class Main
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(() -> {
final JFrame frame = new JFrame();
final JPanel mainPanel = new JPanel();
Toolkit tk = Toolkit.getDefaultToolkit();
tk.addPropertyChangeListener("awt.font.desktophints"/*SunToolkit.DESKTOPFONTHINTS*/, new PropertyChangeListener()
{
#Override
public void propertyChange(PropertyChangeEvent evt)
{
SwingUtilities.invokeLater(() -> render(mainPanel));
}
});
render(mainPanel);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setVisible(true);
});
}
private static void render(JPanel parent)
{
parent.removeAll();
final JPanel panel = new JPanel();
final JLabel label = new JLabel("labelMessage:");
panel.add(label);
final JTextArea textArea = new JTextArea("textAreaMessage");
textArea.setEditable(false);
textArea.setOpaque(false);
textArea.setFont(label.getFont());
panel.add(textArea);
parent.add(panel);
parent.revalidate();
parent.repaint();
}
}
It's an old question but I'd like to explain what's going on here.
textArea.setFont(label.getFont());
You use the font of the label for textArea. Since you didn't change the font, the font is a UIResource, therefore the font gets reset to the default font whenever UI components are updated because of a desktop property change or any other update, like Look-and-Feel change.
When such an event occurs, the UI of all the components is updated using updateUI() method of JComponent.
Creating a new instance of Font removes the magic of UIResource:
Font labelFont = label.getFont();
textArea.setFont(labelFont.deriveFont(labelFont.getStyle()));
The font of the textArea is not reset by updateUI. Yet the font will not change even when you want it to change, for example when the Look-and-Feel of your app is updated to another LaF.
A better solution is to override updateUI method and set the font for textArea there:
final JTextArea textArea = new JTextArea("textAreaMessage") {
#Override
public void updateUI() {
super.updateUI();
setFont(UIManager.getFont("Label.font"));
}
};
This approach handles both the initial setup as well as any updates. This can be a new reusable component which is used to display selectable text, if you also set the background and foreground colors and make the text non-editable by default. (If you set the background and foreground colors, which I recommend doing, you won't need textArea.setOpaque(false);, it makes paint and repaint faster.)
The runnable example:
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class UIFontUpdate {
private final JFrame frame;
public static void main(String[] args) {
SwingUtilities.invokeLater(UIFontUpdate::new);
}
private UIFontUpdate() {
frame = new JFrame("UI Font Update");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
JLabel label = new JLabel("labelMessage:");
mainPanel.add(label);
final JTextArea textArea = new JTextArea("textAreaMessage") {
#Override
public void updateUI() {
super.updateUI();
setFont(UIManager.getFont("Label.font"));
}
};
textArea.setEditable(false);
textArea.setOpaque(false);
mainPanel.add(textArea);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
new Thread(this::callUpdateUI).start();
}
public void callUpdateUI() {
try {
Thread.sleep(2000);
} catch (InterruptedException ignored) { }
System.out.println("UI updating...");
SwingUtilities.invokeLater(() ->
SwingUtilities.updateComponentTreeUI(frame));
}
}
I'm simulating update to properties without actually changing system settings. I'm using callUpdateUI which is run on another thread, and after 2 seconds it updates the UI.
To test that the approach works when changing the Look-and-Feel, change the code callUpdateUI to:
SwingUtilities.invokeLater(() -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException
| UnsupportedLookAndFeelException ignored) {
}
SwingUtilities.updateComponentTreeUI(frame);
});
This is a simplified version of my code, if this is not enough to diagnose the problem, comment and I'll post more code:
//All Necessary Imports
JFrame window;
Container container;
JPanel mainTextPanel;
JScrollPane scrollPane;
JTextArea mainText;
Font normalFont = new Font("Times New Roman", Font.PLAIN,30);
ChoiceHandler choiceHandler = new ChoiceHandler();
//Unrelated Variables
public class setUp()
{
public setUp()
{
window = new JFrame();
window.setSize(825,600);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().setBackground(Color.white);
window.setLayout(null);
container = window.getContentPane();
mainTextPanel = new JPanel();
mainTextPanel.setBounds(100,100,600,250);
mainTextPanel.setBackground(Color.white);
container.add(mainTextPanel);
//more code goes here
}
}
public class mainText extends setUp
{
public mainText()
{
mainText = new JTextArea("Tons of text here");
mainText.setBounds(100,100,600,250);
mainText.setBackground(Color.white);
mainText.setForeground(Color.black);
mainText.setFont(normalFont);
mainText.setLineWrap(true);
scrollPane = new
JScrollPane(mainText,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
mainTextPanel.add(scrollPane);
mainTextPanel.revalidate();
mainTextPanel.repaint();
mainTextPanel.setVisible(true);
//more code goes here
}
}
My problem is that when I run the code, everything works except that the ScrollPane apparently cannot detect the fact that the text is out of bounds. The scrollbar is there, the only problem is that you cannot scroll with it, it looks like a scroll bar from when the text does not exceed the limit.
When I removed the ALWAYS modifier in creating the scrollbar, the scrollbar disappears, again demonstrating that the scrollbar simply does not detect the out-of-bounds text.
I'd just like to point out to you why null layouts suck ... code
This is how your code appears on my system. To be honest, there is scroll bar there, but your attempt to do away with the layout management API has caused the JScrollPane to exceed the physical bounds of the parent container.
You also don't seem to understand how the coordinate system works in Swing, in relationship to the parent component's context, but if you work with a layout manager instead, you wouldn't need to.
So, after updating your code a bit to use a layout managers
You know have a solution which can be scrolled...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
mainText mt = new mainText();
mt.window.pack();
mt.window.setLocationRelativeTo(null);
mt.window.setVisible(true);
}
});
}
public class setUp {
JFrame window;
Container container;
JPanel mainTextPanel;
JScrollPane scrollPane;
JTextArea mainText;
Font normalFont = new Font("Times New Roman", Font.PLAIN, 30);
public setUp() {
window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().setBackground(Color.white);
container = window.getContentPane();
mainTextPanel = new JPanel(new BorderLayout());
mainTextPanel.setBackground(Color.white);
container.add(mainTextPanel);
//more code goes here
}
}
public class mainText extends setUp {
public mainText() {
mainText = new JTextArea("Tons of text here");
mainText.setBackground(Color.white);
mainText.setForeground(Color.black);
mainText.setFont(normalFont);
mainText.setLineWrap(true);
scrollPane = new JScrollPane(mainText, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
mainTextPanel.add(scrollPane);
mainTextPanel.revalidate();
mainTextPanel.repaint();
//more code goes here
}
}
}
But where is the horizontal scroll bar?
mainText.setLineWrap(true); would have removed the need for it
But the JTextArea is to small!
So? Supply some appropriate sizing hints which the component can use to make better determinations about how large it might like to be.
Something like mainText = new JTextArea("Tons of text here", 1, 10); produces
So, the long and short answer is, use the layout management API, Swing has been designed around it's use and it will save you a lot of head scratching and stupid edge cases
But on my system the scroll bars don't appear!?
😓 Go back to the start, do not collect $200 and read it again. The reason why it would appear differently is because of the lack of layout support
But I don't want to use/understand layout managers!
Tough. If you want to avoid these kind of "weird" issues, then the layout management API is the right direction to head in. Take the time to experiment with the different layout managers and try different combinations, you're not stuck to using just one, almost all complex UIs will make use a at least two if not more layout managers in a single compound UI
I'm learning Java and Swing, but my JButton doesn't work.
import javax.swing.JFrame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Programma {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e){
e.printStackTrace();
}
JFrame frame = new JFrame("DIG");
JPanel panel = new JPanel();
JButton button = new JButton("Click Me");
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button.setBounds(100, 100, 130, 35);
panel.add(button);
frame.add(panel);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
JLabel label = new JLabel("Hello World");
label.setVisible(true);
panel.add(label);
}
});
}
}
The frame and button are visible, nut when I click it, the label doesn't appear. How can I fix this?
Do I write this before the other component like JPanel, JButton, etc., or do I write this at the end of code:
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
What is the difference ?
By the way, button.setBounds(100, 100, 130, 35) doesn't work, either.
I see some issues in your code:
button.setBounds(100, 100, 130, 35); that line will be ignored and you shouldn't be manually be determining the position of the components. See Null layout is evil and Why is it frowned upon to use a null layout in swing? altough you're not using null layout, there is explained why you shouldn't be manually determining the positions of the components.
You're running everything in your program in the main method, that will be hard to maintain later.
You're calling frame.setVisible(true) before you've added all your elements to it, that will cause you random issues.
You're not running your program on the Event Dispatch Thread (EDT), you can solve this by starting your program with the following code, which places it in the EDT. It's recommended as Swing is not thread safe.
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//Your constructor here
}
});
}
You're setting the size of the JFrame with setSize(...), instead call frame.pack() and override the getPreferredSize() method of the JPanel.
After all the above has been said, you need to call revalidate() and repaint() on your ActionListener so your program paints its new state.
This program follows all the above recommendations and produces the following outputs (before clicking and after clicking the button 3 times), I on purpose to not make the images so large, made the GUI shorter (200 x 200 instead of 400 x 400)
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Programma {
private JFrame frame;
private JPanel panel;
private JButton button;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Programma().createAndShowGui();
}
});
}
public void createAndShowGui() {
frame = new JFrame("DIG");
panel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
};
button = new JButton("Click Me");
panel.add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JLabel label = new JLabel("Hello World");
panel.add(label);
panel.revalidate();
panel.repaint();
}
});
frame.add(panel);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Do i write this before the other componente like JPanel,JButton... or do i write this at the end of code ?
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
What is the difference ?
Altough I answered this on the recommendations, the difference is that if you call setVisible before adding all your elements to the frame, then you'll find yourself with some random issues where the components are not all visible until you pass your mouse over them (or where they should be). frame.pack() and setVisible should be the last ones to be called in your program, and frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); can be at the start or the end, it doesn't affects, but I prefer to have it at the end too.
button.setBounds(100, 100, 130, 35); doesn't work too.
Well, that's because of you're using a layout manager (and that's the right way to do your GUIs) instead of a null-layout (which you shouldn't be using anyway) (See point #1).
Edit
What is the difference between frame.setSize(); and frame.setpack() ?
If you read the docs for pack():
Causes this Window to be sized to fit the preferred size and layouts of its subcomponents. The resulting width and height of the window are automatically enlarged if either of dimensions is less than the minimum size as specified by the previous call to the setMinimumSize method.
So, it will calculate the minimum size for your JFrame where all the elements are visible and in their preferred size while setSize will only set the window size, but if you place a JScrollBar inside it for example this will reduce the window size, because of that, that's why you should override the getPreferredSize(...) method of your container, so it will calculate its preferred size including the width of the JScrollBar or some other elements that could modify its size. See Should I avoid the use of setPreferred|Maximum|MinimumSize in Swing? (the general consensus says yes)
When you add components dynamically to panel, you need to repain it.
Do this
panel.revalidate();
after
panel.add(label);
I am writing a program that attempts to simulate the evolution of a species, and it has a window that looks like this:
Originally the empty area in the bottom right was a Panel, and it is intended to draw a visual representation of the specimens, locations, and travel paths(doesn't really matter). However, you will be able to open some sort of window that allows you to create/edit different items(like species, locations, and travel paths). Originally I planned for those to simply be popup windows. But, I was thinking I would perhaps use JInternal panes for the popups, and the visual representation screen.
So in my JFrames constructor:
JDesktopPane pane = new JDesktopPane();
this.setContentPane(pane);
setLayout(new BorderLayout());//To layout the menubar, and the items on the left
panel = new GraphicsPanel(manager);
panel.setVisible(true);
And in Graphics Panel constructor:super("Graphic Project View",true,false,true,true);
This locks the Panel to BorderLayout.CENTER, and it fills up the entire space, not allowing for anything else. My guess this is because JDesktopPanes use an OverlayLayout, and when I set the layout to BorderLayout that overrides the OverlayLayout, and so my InternalFrame just gets added to the center.
So the question is:
How do I layout the things like the JMenuBar, and the left ward Panel as they are now, whilst still maintaining the capability to have JInternalFrames?
For now I am going to add the JMenuBar via JFrame.setJMenuBar(JMenuBar) instead of JFrame.add(menuBar,BorderLayout.NORTH), and then change the panel on the left into a JInternal frame, but if possible I'd rather have it as is. I would like it if I could just have the DesktopPane be added to the JFrame at BorderLayout.CENTER, and then just add the frame to the Desktop pane. If the InternalFrame were limited to that region I wouldn't care, as long as it's still mobile, ect.
EDIT: How I add JInternalFrame(Sorry it still says panel, but it has been converted to a JInternalFrame):
panel = new GraphicsPanel(manager);
panel.setSize(desktop.getSize());
panel.setLocation(0,0);
panel.setVisible(true);
desktop.add(panel);
I would start with a single JPanel (lets all it the base pane), which will house the other containers.
Using a border layout, I would add a "controls" panel to the WEST position of the base pane. Onto the CENTER position I would add the JDesktopPane.
I would set the main windows layout to BorderLayout and add the base pane to it. This will allow you to use JFrame#setJMenuBar to manage the menu bar while maintaining the result of the layout.
This will allow you to contain to use the JInternalFrames on the desktop without effecting the rest of the layout...
Simple Example
This is an overly simplified example used to demonstrate the basic concept described above...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SimpleLayout {
public static void main(String[] args) {
new SimpleLayout();
}
public SimpleLayout() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JMenuBar mb = new JMenuBar();
mb.add(new JMenu("File"));
mb.add(new JMenu("Add"));
mb.add(new JMenu("Edit"));
mb.add(new JMenu("Analize"));
mb.add(new JMenu("About"));
JFrame frame = new JFrame("Testing");
frame.setJMenuBar(mb);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new BasePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BasePane extends JPanel {
private JTextArea species;
private JTextArea locations;
private JTextArea travelPaths;
private JDesktopPane desktopPane;
public BasePane() {
setLayout(new BorderLayout());
desktopPane = new JDesktopPane();
species = new JTextArea("Species");
locations = new JTextArea("Locations");
travelPaths = new JTextArea("TravelPaths");
JPanel controls = new JPanel(new GridLayout(3, 0));
controls.add(new JScrollPane(species));
controls.add(new JScrollPane(locations));
controls.add(new JScrollPane(travelPaths));
add(controls, BorderLayout.WEST);
add(desktopPane);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Your requirements might be slightly difference, but the basic concept should get you moving.
Depending on the structure of your application, I might be tempted to separate the Controls pane into a separate class as well.