Here is the minimal working application :
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class JMenuItemReuse {
public static void main(String[] args) {
SwingUtilities.invokeLater(TestFrame::new);
}
}
class TestFrame extends JFrame {
public TestFrame() {
super();
JPanel panel = new JPanel();
JPopupMenu menu1 = new JPopupMenu();
JPopupMenu menu2 = new JPopupMenu();
JMenuItem item1 = new JMenuItem("reused");
JMenuItem item2 = new JMenuItem("not reused");
menu1.add(item1);
menu2.add(item1); // works if this line is commented
menu2.add(item2);
panel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (SwingUtilities.isRightMouseButton(e)) {
menu1.show(panel, e.getX(), e.getY());
} else {
menu2.show(panel, e.getX(), e.getY());
}
}
});
panel.add(new JLabel("popup-test"));
add(panel);
setPreferredSize(new Dimension(400, 400));
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
}
The problem is that the popup menus do not work as expected when at least one menu item is reused. It is not a big issue, can be easily avoided by duplicating the reused menu item, but I am still wondering why does it happen. Any ideas?
A JMenuItem belongs to one, and only one, JPopupMenu (or any other menu). You cannot add a Swing component to more than one container; if you do, then the component will automatically be removed from the previous container.
Actaully if you want, you can create Actions. Actions can be shared and added to multiple components (JMenuItems, JButtons etc). You can even enable/disable the Action which will enable/disable all the components at the same time.
Related
I'm trying to adapt to submenus the code found at https://coderanch.com/t/343946/java/Scrolling-JMenu in order to have a scrollbar rather than buttons like suggested in the answer of Java: Creating a scrolling submenu. However I am having a some troubles for getting a "standard" behaviour:
The parent menu should not disappear when the mouse is focused/hovering on the scrollable menu (see Font menu).
The scrollable menu should disappear when the mouse is not focused/hovering on it or on its parent submenu (see Font menu).
The scrollable menu should not disappear even if the text of the submenu is long (see Help menu).
Thanks in advance for your help. Here's my code:
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
public class ScrollingMenu extends JFrame {
private final JPopupMenu fontNameMenu = new JPopupMenu();
private final JMenu[] fontMenuArray = new JMenu[] {new JMenu("Font Name"), new JMenu("Font Style")};
private JMenu menu = new JMenu("Font");
private final JMenu[] helpMenuArray = new JMenu[] {new JMenu("Very very very very very very very long Font Name Menu")};
private JMenu hmenu = new JMenu("Help");
public static void main(String[] args) {
JFrame scrollingMenu = new ScrollingMenu();
scrollingMenu.setVisible(true);
}
public ScrollingMenu() {
// Creating a long array
String[] systemFontArray = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
JCheckBoxMenuItem[] fontNameArray = new JCheckBoxMenuItem[systemFontArray.length];
// Creating the scrollable menu
GridBagLayout fontNameLayout=new GridBagLayout();
JPanel fontNamePanel = new JPanel();
fontNamePanel.setLayout(fontNameLayout);
for (int i=0;i<systemFontArray.length;i++) {
fontNameArray[i] = new JCheckBoxMenuItem(systemFontArray[i]);
fontNameLayout.setConstraints(fontNameArray[i],new GridBagConstraints(0,i,1,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0));
fontNamePanel.add(fontNameArray[i]);
}
JScrollPane fontScrollPane = new JScrollPane(fontNamePanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
this.fontNameMenu.add(fontScrollPane);
// Adding the scrollable menu to a submenu
addML(ScrollingMenu.this.fontMenuArray[0], ScrollingMenu.this.fontNameMenu, new Dimension(200, 200));
// Creating the Font Style submenu (for underlining problem 2)
this.fontMenuArray[1].add(new JCheckBoxMenuItem("Bold"));
this.fontMenuArray[1].add(new JCheckBoxMenuItem("Italic"));
this.fontMenuArray[1].add(new JCheckBoxMenuItem("Plain"));
// Adding the submenus to the Font menu
for (int i=0;i<this.fontMenuArray.length;i++) {
this.menu.add(this.fontMenuArray[i]);
}
// Adding the scrollable menu to a long text submenu (problem 3)
addML(ScrollingMenu.this.helpMenuArray[0], ScrollingMenu.this.fontNameMenu, new Dimension(200, 200));
// Adding the submenu to the Help menu
for (int i=0;i<this.helpMenuArray.length;i++) {
this.hmenu.add(this.helpMenuArray[i]);
}
JMenuBar menuBar = new JMenuBar();
menuBar.add(this.menu);
menuBar.add(this.hmenu);
this.setJMenuBar(menuBar);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
this.pack();
this.setLocationRelativeTo(null);
}
private static void addML (JMenu subMenu, JPopupMenu popupMenu, Dimension dimension) {
popupMenu.addFocusListener(new FocusAdapter() {
#Override
public void focusLost(FocusEvent focusEvent) {
if(popupMenu.isVisible() && !subMenu.isSelected())
popupMenu.setVisible(false);
}
});
popupMenu.addMouseListener(new MouseAdapter() {
#Override
public void mouseExited(MouseEvent mouseEvent) {
if(!subMenu.isSelected())
popupMenu.setVisible(false);
}
});
popupMenu.setInvoker(subMenu);
popupMenu.setPreferredSize(dimension);
subMenu.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent mouseEvent) {
if(!popupMenu.isVisible())
displayFontNameMenu(subMenu, popupMenu);
else
popupMenu.setVisible(false);
}
#Override
public void mouseEntered(MouseEvent mouseEvent) {
if(!popupMenu.isVisible() && subMenu.isSelected())
displayFontNameMenu(subMenu, popupMenu);
}
#Override
public void mouseExited(MouseEvent mouseEvent) {
if(popupMenu.isVisible() && !popupMenu.contains(mouseEvent.getPoint())) {
popupMenu.setVisible(false);
}
}
});
}
private static void displayFontNameMenu(JMenu subMenu, JPopupMenu popupMenu) {
Rectangle rectangle = subMenu.getBounds();
Point point = new Point(rectangle.x +rectangle.width, rectangle.y);
SwingUtilities.convertPointToScreen(point, subMenu.getParent());
popupMenu.setLocation(point.x, point.y);
popupMenu.setVisible(true);
}
}
I am pretty new to Swing, any help appreciated.
I have the following situation:
A "Main" Class where I define my main JPanel and default Label text.
A "GUILabel" Class (extends JLabel) where I define the look of the Text Labels.
A "popupmenu" Class (extends JPopupMenu) where I define the content of the popupmenu.
Target:
When I right-click on a panel the popupMenu should appear (this already works).
When I choose a menu item of this popupMenu, the text of the label I clicked on should change.
I guess its currently not working (I am sorry this code isn't complete - this is my 5th attempt), because I create the popup menu Once in the Main Class. Then I am adding this popup menu to each Label. So I guess thats why getInvoker() returns null in the popup menu class.
But do I really have to create a new popupmenu for each JLabel? Cant this single menu just handle all Components assigned to?
Main Frame:
package popupshit;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.border.BevelBorder;
public class Model implements ActionListener {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(0, 3));
frame.setVisible(true);
GUIPopupMenu popup = new GUIPopupMenu(9);
JLabel label1 = new GUILabel();
label1.setComponentPopupMenu(popup);
JLabel label2 = new GUILabel();
label2.setComponentPopupMenu(popup);
JLabel label3 = new GUILabel();
label3.setComponentPopupMenu(popup);
frame.add(label1);
frame.add(label2);
frame.add(label3);
frame.pack();
}
#Override
public void actionPerformed(ActionEvent e) {
((JLabel) e.getSource()).setText("" + e.getActionCommand());
}
}
PopupMenu:
package popupshit;
import java.awt.event.ActionListener;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
public class GUIPopupMenu extends JPopupMenu {
public GUIPopupMenu(int numbers) {
for (int i = 1; i < numbers; i++) {
JMenuItem popMenuItem = new JMenuItem("" + i);
popMenuItem.addActionListener ((ActionListener) this.getInvoker());
System.out.println(this.getParent());
this.add(new JMenuItem("" + i));
}
this.addSeparator();
this.add(new JMenuItem("remove"));
}
}
GUILabel:
package popupshit;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.border.BevelBorder;
import javax.swing.border.BevelBorder;
public class GUILabel extends JLabel implements ActionListener {
public GUILabel() {
this.setBorder(new BevelBorder(BevelBorder.LOWERED));
this.setVisible(true);
this.setPreferredSize(new Dimension(50, 50));
this.setText("0");
}
#Override
public void actionPerformed(ActionEvent e) {
this.setText((String) e.getActionCommand());
JOptionPane.showMessageDialog(null, "worked!" );
}
}
invoker is null because until the popup menu is a actually invoked, it has no invoker.
Instead, add a simple ActionListener to the menu item which, when invoked, uses the invoker property to determine which should occur.
My personal preference would be to create a new instance of the popup menu for each component separately, passing a reference of the component in question or some other controller as required...but that's me...
Add an ActionListener to the menu item something like:
#Override
public void actionPerformed(ActionEvent e)
{
Component c = (Component)e.getSource();
JPopupMenu popup = (JPopupMenu)c.getParent();
JLabel label = (JLabel)popup.getInvoker();
...
}
Don't extend JPopupMenu just to add a few menu items to the popup.
At the moment I write a little client application. I have a window with a JTextArea (Display area for the server output) and a user-list.
My plan is to show/hide this user-list over a menu item, but I don't know how. My ideas:
Use a BorderLayout: Without a JScrollPane for the list. It works, but I cannot change the width of the user-list (Because BorderLayout.WEST and BorderLayout.EAST ignore the width)
Use a BorderLayout with a JScrollPane for the user list and show/hide the JScrollPane -> Does not work, don't ask me why...anyway, this way is not a nice solution
Use a JSplitPane, set the resize weight to 0.9. When the user-list should disappear, I minimize the right component (aka the user list) -> How ?
My code at the moment:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
public class SplitPaneTest extends JFrame implements ActionListener
{
private JSplitPane splitPane;
private JTextArea textDisplay;
private JList<String> listUser;
private JScrollPane scrollTextDisplay;
private JScrollPane scrollListUser;
private JCheckBox itemShowUser;
public static void main(String[] args)
{
new SplitPaneTest();
}
public SplitPaneTest()
{
setTitle("Chat Client");
setMinimumSize(new Dimension(800, 500));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textDisplay = new JTextArea();
listUser = new JList<>();
DefaultListModel<String> modelUser = new DefaultListModel<>();
listUser.setModel(modelUser);
modelUser.addElement(new String("User 1"));
modelUser.addElement(new String("User 2"));
modelUser.addElement(new String("User 3"));
scrollTextDisplay = new JScrollPane(textDisplay);
scrollListUser = new JScrollPane(listUser);
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPane.setLeftComponent(scrollTextDisplay);
splitPane.setRightComponent(scrollListUser);
splitPane.setResizeWeight(0.9);
setContentPane(splitPane);
JMenuBar menubar = new JMenuBar();
JMenu menuWindow = new JMenu("Window");
itemShowUser = new JCheckBox("Show user list");
itemShowUser.addActionListener(this);
itemShowUser.setSelected(true);
menuWindow.add(itemShowUser);
menubar.add(menuWindow);
setJMenuBar(menubar);
setVisible(true);
}
public boolean isUserListEnabled()
{
return itemShowUser.isSelected();
}
public void setUserListEnabled(boolean status)
{
scrollListUser.setVisible(status);
}
#Override
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource() == itemShowUser)
{
boolean status = isUserListEnabled();
setUserListEnabled(status);
}
}
}
And the result is:
And with hidden JScrollPane scrollListUser:
Can anybody give me a tipp ? The user-list is still visible ( I thought the JSplitPane would repaint..) .I come from Qt (C++) and in Qt I could use a dock widget - but Swing does not have one and to use third libs....I don't know - maybe there is a solution.
Looks like the splitPane can't handle invisible components well - a way out is to add/remove the scrollPane as appropriate:
public void setUserListEnabled(boolean status)
{
splitPane.setRightComponent(status ? scrollListUser : null);
splitPane.revalidate();
}
I am having some problems regarding to the JMenuBar and I cant seem to figure it out.
I will start with an abriviation of the problem: The program consists of a JFrame, a JDialog and a JMenuBar. Initially, you will get to see a JFrame with the JMenuBar in the top. But at some point, the JDialog will pop up where a user can fill in some text fields. The problem that I'm having is that as soon as the focus goes to the JDialog, the JMenuBar disappears. What I want is that the JMenuBar stays in the top of the screen all the time, except if the whole program is NOT in focus. Here are 2 screenshots, in the first screen shot, the JFrame is selected and in the other one the JDialog is selected.
So what i actually want is instead of only seeing the JMenuBar when the focus is on the JFrame, i want to see the JMenuBar all the time. Since a JDialogs can not have the JMenuBar in the top, like a JFrame has, i decided not to have multiple JMenuBars, but just the one that should be visible all the time.
At last i will give a part of the code that is as small as possible (and still working) and also contains the problem:
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRootPane;
import javax.swing.KeyStroke;
/**
* #author Guus Leijsten
* #created Oct 27, 2012
*/
public class MenuBarProblem extends JFrame {
public MenuBarProblem() {
super("Frame");
this.setMinimumSize(new Dimension(270, 200));
this.setPreferredSize(new Dimension(800, 530));
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
JRootPane root = this.getRootPane();
//Menu
JMenu fileMenu = new JMenu("File");
JMenuItem file_exit = new JMenuItem("Exit");
file_exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
file_exit.setToolTipText("Exit application");
file_exit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
fileMenu.add(file_exit);
JMenuBar menu = new JMenuBar();
menu.add(fileMenu);
root.setJMenuBar(menu);
this.setVisible(true);
JDialog d = new JDialog(this, "Dialog");
d.setSize(200, 100);
d.setLocation(0, (int)root.getContentPane().getLocationOnScreen().getY());
d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
d.setVisible(true);
}
public static void main(String[] args) {
String os = System.getProperty("os.name").toLowerCase();
if(os.indexOf("mac") >= 0) {
System.setProperty("apple.laf.useScreenMenuBar", "true");
}
new MenuBarProblem();
}
}
If I can be honoust, i think that the problem lies in the part of JRootPane. But we'll see ;)
Did anyone else encountered this problem and managed to solve it alrady, or is there anybody that wants to give it a shot?
Thanks in advance!
Added content:
In the following example I will show a version that gives some functionality to the play.
This is the program i'm making:
The second image shows the state in which the right menu is undocked.
Obviously the JMenuBar should still be visible and operational because without it, a lot of functionalities of the program will be disabled.
At this point i'm starting to think that it is impossible for the JMenuBar to stay visible when the dialog (undocked menu) is undocked, and focussed on.
I know that the JMenuBar on a JDialog can not be in the mac osx style (top of screen), so are there any other techniques i can use for undocking, which does give me a mac osx style JMenuBar?
One key to solving this problem, pun intended, is to let a key binding share a common menu action, as shown below. Note how a menu item, your dialog's content and an (otherwise superfluous) button can all use the same Action instance. A few additional notes:
Kudos for using getMenuShortcutKeyMask().
Swing GUI objects should be constructed and manipulated only on the event dispatch thread (EDT).
System properties should be set before starting the EDT.
Make the dialog's setLocation() relative to the frame after its geometry is known.
A common Mac idiom uses the following predicate:
if (System.getProperty("os.name").startsWith("Mac OS X") {…}
See also this example.
For local use in the dialog itself, also consider JToolBar.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
/**
* #see https://stackoverflow.com/a/13100894/230513
*/
public class MenuBarProblem extends JFrame {
private static final int MASK =
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
private static final String exitName = "Exit";
private static final KeyStroke exitKey =
KeyStroke.getKeyStroke(KeyEvent.VK_W, MASK);
private final ExitAction exitAction = new ExitAction(exitName);
public MenuBarProblem() {
super("Frame");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
JMenu fileMenu = new JMenu("File");
JMenuItem fileExit = new JMenuItem(exitAction);
fileMenu.add(fileExit);
JMenuBar menu = new JMenuBar();
menu.add(fileMenu);
JDialog d = new JDialog(this, "Dialog");
JPanel p = new JPanel();
p.getInputMap().put(exitKey, exitName);
p.getActionMap().put(exitName, exitAction);
p.add(new JButton(exitAction));
d.add(p);
d.pack();
d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
this.setJMenuBar(menu);
this.pack();
this.setSize(new Dimension(320, 240));
this.setLocationByPlatform(true);
this.setVisible(true);
d.setLocation(this.getRootPane().getContentPane().getLocationOnScreen());
d.setVisible(true);
}
private static class ExitAction extends AbstractAction {
public ExitAction(String name) {
super(name);
this.putValue(Action.MNEMONIC_KEY, exitKey.getKeyCode());
this.putValue(Action.ACCELERATOR_KEY, exitKey);
}
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
public static void main(String[] args) {
System.setProperty("apple.laf.useScreenMenuBar", "true");
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new MenuBarProblem();
}
});
}
}
Solved!
Using a JFrame with the use of setAlwaysOnTop(true) gives me the desired effect of having a JMenuBar when the focus changes.
I have a show button to show a JTable on click but the table is not visible.
Note: when I remove the JScrollPane the code works properly but the header of the table is not shown, so any help please to make this code work properly without removing the JScrollPane
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
public class Training extends JFrame {
public Training() {
getContentPane().setLayout(new FlowLayout());
JTable table = new JTable();
table.setModel(new DefaultTableModel(new Object[][] { { "joe", "joe" },
{ "mickel", "mickel" }, }, new String[] { "LastName",
"FirstName" }));
final JScrollPane pane = new JScrollPane(table);
pane.setVisible(false);
getContentPane().add(pane);
JButton btn = new JButton("show");
add(btn);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
pane.setVisible(true);
}
});
}
public static void main(String[] args) {
Training app = new Training();
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setSize(600, 600);
app.setVisible(true);
}
}
After pane.setVisible(true); add the following:
getContentPane().validate();
getContentPane().repaint();
A few things to note:
Never extends JFrame class unnecessarily, or else you might need to extend another class which is very necessary but in java a single class may not extend more than one other class (no multiple inheritance).
Always create Swing components on Event Dispatch Thread via SwingUtilities.invokeLater(Runnable r) block.
Do not use setSize(..) call JFrame#pack() before setting JFrame visible
No need for getContentPane.add(..) or getContentPane().setLayout(..), simply call add(..) or setLayout(..) on JFrame instance as these calls are fowared to the contentPane.
The problem you have is you do not refresh you frame/container after setting pane visible. I disagree with #Dan. Do not use validate() (getContentPane() is not necesarry either) rather:
revalidate();
repaint();
as revalidate() covers validate(). Also validate is used when new JComponents are added to a visible component, whereas revalidate() is used when JComponent is removed/added from a visible component.
Here is a fixed version of the code with the above implemented:
After button pressed:
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
public class Training {
private JFrame frame;
public Training() {
frame = new JFrame();
frame.setLayout(new FlowLayout());
JTable table = new JTable();
table.setModel(new DefaultTableModel(new Object[][]{{"joe", "joe"},
{"mickel", "mickel"},}, new String[]{"LastName",
"FirstName"}));
final JScrollPane pane = new JScrollPane(table);
pane.setVisible(false);
frame.add(pane);
JButton btn = new JButton("show");
frame.add(btn);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pane.setVisible(true);
frame.pack();//this is so the frame will resize after adding pane
frame.revalidate();
frame.repaint();
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Training();
}
});
}
}
UPDATE:
Also for a more reusable Layout, why not add all components to a JPanel, and add that JPanel to the JFrame, thus if you ever need to add more stuff its simple.