I want to put FlowLayout with lets say 5 labels inside BorderLayout as north panel (BorderLayout.NORTH), and when I resize my window/frame I want the labels to not disappear but instead move to new line.
I have been reading about min, max values and preferredLayoutSize methods. However they do not seem to help and I am still confused.
Also, I would not like to use other layout like a wrapper or something.
One of the annoying things about FlowLayout is that it doesn't "wrap" it's contents when the available horizontal space is to small.
Instead, take a look at WrapLayout, it's FlowLayout with wrapping...
The following code does exactly what you asked.
The program has a frame whose contentPane is set for BorderLayout. It contains another panel flowPanel that has a flow layout and is added to the BorderLayout.NORTH.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class PanelFun extends JFrame {
final JPanel flowPanel;
public PanelFun() {
setPreferredSize(new Dimension(300,300));
getContentPane().setLayout(new BorderLayout());
flowPanel = new JPanel(new FlowLayout());
addLabels();
getContentPane().add(flowPanel, BorderLayout.NORTH);
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
PanelFun.this.getContentPane().remove(flowPanel); //this statement is really optional.
PanelFun.this.getContentPane().add(flowPanel);
}
});
}
void addLabels(){
flowPanel.add(new JLabel("One"));
flowPanel.add(new JLabel("Two"));
flowPanel.add(new JLabel("Three"));
flowPanel.add(new JLabel("Four"));
flowPanel.add(new JLabel("Five"));
}
public static void main(String[] args) {
final PanelFun frame = new PanelFun();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame.setVisible(true);
}
});
}
}
So, how does it work?
The key to having the components inside flowPanel realign when the frame is resized is this piece of code
PS: Let me know if you are new to Swing and do not understand some part of the code.
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
PanelFun.this.getContentPane().remove(flowPanel);
PanelFun.this.getContentPane().add(flowPanel);
}
});
Without this code the flowPanel will not realign its components as it is not its normal behaviour to reposition components when the containing frame is resized.
However, it is also its behaviour that when flowPanel is added to a panel, it would position components as per the available space. So, if we add the flowPanel everytime the frame resizes, the inner elements will be repositioned to use the available space.
Update:
As camickr pointed out correctly, this method will not work in case you add anything to the center (BorderLayout.CENTER)
Related
I have the following code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Main
{
public static void main(String[] args)
{
Window window = new Window("This is a title", 450, 350);
JButton buttonExit = new Button("Exit", 75, 25);
window.addElement(buttonExit);
window.build();
}
}
class Window // extend the current class
{
public Window window;
public JFrame frame;
public JPanel panel;
public String title;
// instantiate object with the constructor
public Window(String title, int width, int height)
{
this.frame = new JFrame(title);
this.frame.setPreferredSize(new Dimension(width, height));
this.frame.setLocationRelativeTo(null); // centers the main window relative to the center of the screen dimension
this.panel = new JPanel();
this.panel.setPreferredSize(new Dimension(width, height));
//this.panel.setLayout(new FlowLayout());
this.frame.add(panel);
}
public void build()
{
this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.frame.pack(); // removes all unnecessary pixel space from the form
this.frame.setVisible(true);
this.frame.setSize(frame.getPreferredSize());
}
public void addElement(JButton element)
{
this.panel.add(element);
}
}
class Button extends JButton // extend the current class
{
public Button(String text, int width, int height)
{
JButton button = new JButton();
button.setPreferredSize(new Dimension(width, height));
button.setText(text);
button.setVisible(true);
new ButtonHandler(button);
}
}
class ButtonHandler implements ActionListener
{
public ButtonHandler(JButton button)
{
button.addActionListener(this);
}
public void actionPerformed(ActionEvent actionEvent) {
System.exit(0);
}
}
I have two problems with this:
The button is compressed and won't show its text
I cannot get the event handler to work and don't appear to get why
As a side note, I know that I don't specify a LayoutManager here, but I had this implemented before and it didn't solve my issue (I tried the FlowLayoutManager and the GridBagLayout [this would be my desired one, due to its flexibility]).
Can someone tell me, what I am doing wrong here? I've only worked with C# and WPF/WinForms before...
Issue 1:
Your custom Button class is-a JButton but also has-a JButton (named button) in the constructor.
The problem here is you install the ButtonHandler class to the button of the constructor, not the custom Button itself (which is referred to as this inside the constructor).
Issue 2:
When you set the [preferred] size of the JFrame property named frame (in the custom class named Window), you are not setting the frame's contents' [preferred] size, but the size of the whole JFrame, which includes the bar located at the top of the frame (which has the title of the frame).
That lets the contents of the frame to have a space less than the preferred size, because the preferred size is set to the whole frame.
I know, you are also setting the preferred size of the JPanel named panel, which is added to the frame, but when you pack the frame, then the preferred size of the frame is prioritized rather than the preferred size of the contents of the frame, so that's probably why you are seeing the button compressed.
Let me demonstrate what I mean, with a bit of code:
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestFramePrefSz {
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> {
final JFrame frame = new JFrame("Testing JFrame preferred size");
final JPanel contents = new JPanel();
contents.setPreferredSize(new Dimension(200, 200));
frame.setPreferredSize(new Dimension(200, 200));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(contents);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
System.out.println(contents.getSize());
});
}
}
As you can see, the dimension object printed (which is the actual size of the panel) is about 184x161 rather than 200x200 requested, because the preferred size of the frame is also set to 200x200 (which includes the title of the frame etc...).
The solution, is to only set the preferred size of the contents, not the frame (in this particular scenario at least).
So you should:
Remove the line this.frame.setSize(frame.getPreferredSize()); inside the build method.
Remove the line this.frame.setPreferredSize(new Dimension(width, height)); inside the constructor of the custom class named Window.
Issue 3:
The line this.frame.setLocationRelativeTo(null); inside the constructor of the custom class named Window, is not effective in that place.
Imagine that, when you call this method, it has to determine the location of the frame to set it.
So it needs to know first of the size of the screen and then the size of the frame itself.
But what is the size of the frame at the point where you call this method? It is about 0x0. Not the preferred size as you might expect.
That makes the calculation of the frame's location to be such that the frame will not be centered at the screen.
That's because the preferred size is a property of the frame, which is a different property than the size.
So you either have to setSize prior making the call, or better to set the preferred size of the contents of the frame (ie this.panel), then call pack on the frame and finally call the method this.frame.setLocationRelativeTo(null).
Then you are free to set the frame to visible to see where it is located in the screen (ie should be centered).
So the solution is to follow a pattern like the following:
Create the frame, add the contents of the frame to it and set the contents' preferred size.
Call pack on the frame (remember this call will change the size of the frame, according to the preferred sizes of the contents of the frame or the frame's itself).
Call setLocationRelativeTo(null) on the frame.
Call setVisible(true) on the frame.
If you take a look at your code, you are instead doing:
Create the frame.
Set the preferred size of the frame.
Call setLocationRelativeTo(null) on the frame (but the size of the frame is not set yet).
Add the contents of the frame to it (ie the panel).
Call addElement which adds more content to the panel.
Call pack on the frame (remember the preferred size of the frame is set up to this point, so it will override any other preferred sizes, such as the contents' preferred size).
Call setVisible(true) on the frame.
Call setSize on the frame, with the preferred size of it. So you are overwriting the size the frame has had from step 6.
I don't know what you're using as a tutorial. I recommend the Oracle tutorial, Creating a GUI With JFC/Swing. You can skip the Netbeans section, but I recommend going through the rest of the sections.
I created the following GUI.
The Exit button works, disposing of the GUI. The X in the upper right also disposes of the GUI.
Here's the runnable example code. The explanation follows the code.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class JButtonExample implements Runnable{
public static void main(String[] args) {
SwingUtilities.invokeLater(new JButtonExample());
}
private JFrame frame;
#Override
public void run() {
frame = new JFrame("This is a title");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
exitProcedure();
}
});
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setPreferredSize(new Dimension(300, 200));
panel.setBorder(BorderFactory.createEmptyBorder(
75, 100, 75, 100));
JButton button = new JButton("Exit");
button.addActionListener(new ExitListener(this));
panel.add(button, BorderLayout.CENTER);
return panel;
}
public void exitProcedure() {
frame.setVisible(false);
frame.dispose();
System.exit(0);
}
public class ExitListener implements ActionListener {
private JButtonExample example;
public ExitListener(JButtonExample example) {
this.example = example;
}
#Override
public void actionPerformed(ActionEvent event) {
example.exitProcedure();
}
}
}
I make a call to the SwingUtilities invokeLater method from the main method. This method makes sure that the Swing components are created and executed on the Event Dispatch Thread.
I separate the JFrame code from the JPanel code. This is so I can focus on one part of the GUI at a time.
The JFrame methods have to be called in a specific order. This is the order that I use for most of my Swing applications.
The WindowListener (WindowAdapter) gives my code control over the closing of the JFrame. This will allow the Exit button actionListener to close the JFrame. A WindowListener is not a simple concept.
The JFrame defaultCloseOperation is usually set to EXIT_ON_CLOSE. In order for the WindowListener to work, I had to set the defaultCloseOperation to DO_NOTHING_ON_CLOSE.
I let the JFrame determine its own size by using the pack method.
I set the preferred size of the JPanel.
I created an empty border for the JPanel, so the JButton would expand to fill the rest of the JPanel. That's what happens to the component placed in the center of a BorderLayout.
I created an ExitListener class. Because it's an inner class, I didn't have to create a constructor or pass the JButtonExample instance. I created a constructor so you can see how it's done, and how the actionListener method can execute the exitProcedure method of the JButtonExample class.
I hope this JButton example is helpful. The WindowListener is a bit advanced for a simple example, but you can see how it's done.
I have a JFrame, and within it, a JLabel that is filled by an image of a Map. I want to have clickable square “Tiles” in a grid over the image of the map. To do this, I made a large grid of JButtons that I have added to the JLabel containing the Map. However, the Map cannot be seen, so I have made the JButtons completely transparent. However, when they are Transparent, I can’t see where one JButton ends, and where another one starts. I want to create a JButton that is totally transparent on the inside, but still has a visible border around it. I have tried setOpaque(false) and then setBorderPainted(true) but that makes them opaque again. I have tried everything I could find, but nothing happens. Any suggestions?
Once again, all I want is a Transparent JButton with Visible Borders
You should be able to replace border with you own...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBackground(Color.RED);
setLayout(new GridBagLayout());
JButton btn = new JButton("Hello");
btn.setOpaque(false);
btn.setContentAreaFilled(false);
btn.setBorderPainted(true);
btn.setBorder(new LineBorder(Color.BLUE));
add(btn);
}
}
}
You might need to use a CompoundBorder with a EmptyBorder on the inside to provide some padding (I tried using setMargins but it didn't seem to work)
I am trying to make a basic program where whenever you press a button, a JCheckbox is generated and added below the other JCheckbox on a panel. I figured out how to generate the JCheckbox with a ActionListener but I can't figure out how to get each new check box to appear below the previous one. Everything else seems to be working but I can't get this location thing to work.
box.setVisible(true);
_p.add(box);
int i = 0;
int u = i++;
box.setAlignmentX(0);
box.setAlignmentY(u);
Here is a sample of my code. I've been stuck on this problem for a very long time and would greatly appreciate any and all help.
Check out the Swing tutorial on Using Layout Managers. You could use a vertical BoxLayout or a GridBagLayout or maybe a GridLayout.
Whatever layout you choose to use the basic code for adding components to a visible GUI is:
panel.add(...);
panel.revalidate();
panel.repaint();
The other statements in your code are not necessary:
//box.setVisible(true); // components are visible by default
The following methods do not set a grid position.
//box.setAlignmentX(0);
//box.setAlignmentY(u);
JCheckbox lives in a container like a JPanel (that means that you add checkbox to a panel) . A JPanel have a layoutManager. Take a look about Using Layout Managers
You could use BoxLayout with Y_AXIS orientation or a GridLayout with 1 column and n rows.
Example:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class CheckBoxTest {
private JPanel panel;
private int counter=0;
public CheckBoxTest(){
panel = new JPanel();
panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
JButton button = new JButton(" Add checkbox ");
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent evt){
panel.add(new JCheckBox("CheckBox"+Integer.toString(counter++)));
//now tell the view to show the new components added
panel.revalidate();
panel.repaint();
//optional sizes the window again to show all the checkbox
SwingUtilities.windowForComponent(panel).pack();
}
});
panel.add(button);
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Checkbox example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationByPlatform(Boolean.TRUE);
CheckBoxTest test = new CheckBoxTest();
frame.add(test.panel);
//sizes components
frame.pack();
frame.setVisible(Boolean.TRUE);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
I'm working on a project, there are JInternalFrames in the mainframe. Now, we need to let them to be JFrame. I'm considering using a JFrame to hold on JInternalFrame. The problem is that the titlebar of Internalframe is there, and user can drag it around.
Is there any way to make the Internal frame work like a pane in the JFrame?
After searching on the Internet, I found somebody removes the titlepane.
Do you have any good idea on this?
Thanks you!
update:
Maybe I was on the wrong track. The real problem is the JInternal frame can not get out of the main Frame, or any way to make it look like it's out side of the frame?
Is there any way to make the Internal frame work like a pane in the
JFrame
Im not sure by what you mean by pane, but I guess like a JPanel? Of course you can but why, would be my question, unless you want some sort of quick floating panel, but than you say you dont want it draggable? So Im bit unsure of your motives and makes me weary to answer....
The problem is that the titlebar of Internalframe is there
Well Here is code to remove the titlepane (found it here):
//remove title pane http://www.coderanch.com/t/505683/GUI/java/JInternalframe-decoration
BasicInternalFrameTitlePane titlePane =(BasicInternalFrameTitlePane)((BasicInternalFrameUI)jInternalFrame.getUI()).getNorthPane();
jInternalFrame.remove(titlePane);
and user can drag it around.
And I found this to make JInternalFrame unmovable by removing the MouseListeners which make it movable, but it is important to note its not necessary to remove the MouseListeners as the method used to make it undraggable will remove the NorthPane which the MouseListener is added too thus its unnecessary for us to remove it ourselves.:
//remove the listeners from UI which make the frame move
BasicInternalFrameUI basicInternalFrameUI = ((javax.swing.plaf.basic.BasicInternalFrameUI) jInternalFrame.getUI());
for (MouseListener listener : basicInternalFrameUI.getNorthPane().getMouseListeners()) {
basicInternalFrameUI.getNorthPane().removeMouseListener(listener);
}
And as per your title:
how to make JInternalFrame fill the Container
Simply call setSize(int width,int height) on JInternalFrame with parameters of the JDesktopPanes width and height (JDesktopPane will be sized via overriding getPreferredSize()).
Which will give us this:
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.event.MouseListener;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
import javax.swing.plaf.basic.BasicInternalFrameUI;
/**
*
* #author David
*/
public class Test {
public Test() {
createAndShowGUI();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
private void createAndShowGUI() throws HeadlessException {
JFrame frame = new JFrame();
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
final JDesktopPane jdp = new JDesktopPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
};
frame.setContentPane(jdp);
frame.pack();
createAndAddInternalFrame(jdp);
frame.setVisible(true);
}
private void createAndAddInternalFrame(final JDesktopPane jdp) {
JInternalFrame jInternalFrame = new JInternalFrame("Test", false, false, false, false);
jInternalFrame.setLocation(0, 0);
jInternalFrame.setSize(jdp.getWidth(), jdp.getHeight());
//remove title pane http://www.coderanch.com/t/505683/GUI/java/JInternalframe-decoration
BasicInternalFrameTitlePane titlePane = (BasicInternalFrameTitlePane) ((BasicInternalFrameUI) jInternalFrame.getUI()).getNorthPane();
jInternalFrame.remove(titlePane);
/*
//remove the listeners from UI which make the frame move
BasicInternalFrameUI basicInternalFrameUI = ((javax.swing.plaf.basic.BasicInternalFrameUI) jInternalFrame.getUI());
for (MouseListener listener : basicInternalFrameUI.getNorthPane().getMouseListeners()) {
basicInternalFrameUI.getNorthPane().removeMouseListener(listener);
}
*/
jInternalFrame.setVisible(true);
jdp.add(jInternalFrame);
}
}
Given your requirements, I suggest you just use a simple JPanel inside your JFrame content pane.
I'm trying to write custom JFrame and JPanel for my Java application. Currently, I just want to have a JPanel with a start button in the very middle of the screen. So, here's the code I have:
package gui;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class SubitizingFrame extends JFrame implements KeyListener {
public SubitizingFrame() {
super("Subitizing");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addKeyListener(this);
add(new LaunchPanel());
pack();
setVisible(true);
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_F5)
System.out.println("F5 pressed");
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
and here is my panel:
package gui;
import instructions.Settings;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class LaunchPanel extends JPanel implements ActionListener {
private JButton startButton;
public LaunchPanel() {
int width = Settings.getScreenSizeX(), height = Settings.getScreenSizeY();
setPreferredSize(new Dimension(width, height));
setLayout(null);
startButton = new JButton("Start");
startButton.setLocation((width/2) - (startButton.getWidth()/2), (height/2) - (startButton.getHeight()/2));
add(startButton);
}
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
But when the application launches, I don't see anything. Just a big gray screen.
Do not use a null layout. If you simply use the default layout manager of JPanel (i.e. FlowLayout), the JButton with "automagically" be placed in the center. Also, in order to place the JFrame in the middle of the screen, invoke setLocationRelativeTo(null).
Since it's hard to tell what you mean by "screen", this example shows how you center a JButton in a JPanel in a JFrame, that is then centered on the monitor.
public final class CenterComponentsDemo {
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI(){
final JFrame frame = new JFrame("Center Components Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ButtonPane());
frame.setSize(new Dimension(300, 100)); // Done for demo
//frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static class ButtonPane extends JPanel{
public ButtonPane(){
super();
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setBackground(Color.PINK);
final JButton button = new JButton("Start");
button.setAlignmentX(Component.CENTER_ALIGNMENT);
add(Box.createVerticalGlue());
add(button);
add(Box.createVerticalGlue());
}
}
}
Recommendations:
Avoid using null layout as this makes your app difficult to upgrade and maintain and makes it potentially very ugly or even non-usable on boxes with different OS's or screen resolutions.
If you have your JPanel use a GridBagLayout and add a single component to it without using GridBagConstraints, it will be placed in the center of the JPanel.
You almost never have to or should extend JFrame and only infrequently need to extend JPanel. Usually it's better to enhance your GUI classes through composition rather than inheritance.
Avoid having your "view" or gui classes implement your listener interfaces. This is OK for "toy" programs, but as soon as your application gains any appreciable size or complexity, this gets hard to maintain.
If you don't use any LayoutManager (which btw you probably should), then you'll need to set the size of the panel as well (along with its position).
Although we strongly recommend that you use layout managers, you can perform layout without them. By setting a container's layout property to null, you make the container use no layout manager. With this strategy, called absolute positioning, you must specify the size and position of every component within that container. One drawback of absolute positioning is that it does not adjust well when the top-level container is resized. It also does not adjust well to differences between users and systems, such as different font sizes and locales.
From: http://download.oracle.com/javase/tutorial/uiswing/layout/using.html
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class LaunchPanel extends JPanel {
private JButton startButton;
public LaunchPanel() {
int width = 200, height = 100;
setPreferredSize(new Dimension(width, height));
setLayout(new GridBagLayout());
startButton = new JButton("Start");
add(startButton);
setBorder( new LineBorder(Color.RED, 2));
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JOptionPane.showMessageDialog(null, new LaunchPanel());
}
});
}
}
addKeyListener(this);
Don't use KeyListeners. Swing was designed to be used with Key Bindings. Read the section from the Swing tutorial on How to Use Key Bindings for more information.
The tutorial also has a section on Using Layout Manager which you should read. You should not create GUI's with a null layout.