This question already has answers here:
Java Swing : why must resize frame, so that can show components have added
(2 answers)
Closed 9 years ago.
I've been rebuilding an old MS-paint copy cat that I did a few months ago, and Swing has once again been giving me some old problems. One of which has had me and a few other people stumped for a few days now. I've got a custom JFrame that I'm using to lay all of my components on, and custom JButtons that are used to represent the various colors and tools that the user can choose from. Right now, the problem is that my program isn't displaying most of my buttons. Here's my ColorButton class:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
public class ColorButton extends JButton implements ActionListener
{
private static final long serialVersionUID = 1L;
Color color;
public ColorButton(Color color, String name)
{
this.color = color;
setButtonIcon(name);
}
private void setButtonIcon(String name)
{
ImageIcon icon = new ImageIcon("images/" + name);
setIcon(icon);
System.out.println("Icon set.");
}
#Override
public void actionPerformed(ActionEvent event)
{
}
}
Basically, this class is just a better button that I could reuse and dynamically place onto the main frame. I have it set up so that it takes a Color (to set the user's cursor color) and a string (in order to get the ImageIcon from the resources folder). Here's the JFrame that I have to add everything to.
import java.awt.BorderLayout;
import java.awt.Color;
import java.util.ArrayList;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
public class PaintFrame extends JFrame // Frame to place all items on
{
private static final long serialVersionUID = 1L;
public PaintFrame()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Set the program to close if the user wishes
setVisible(true); // Set screen to visible
setSize(1150, 650); // Set screen size
setLocationRelativeTo(null); // Set frame to start in middle of screen
setResizable(false);
setLayout(new BorderLayout()); // Set a suitable layout for the panel
setTitle("Paint 2.0");
addComponents(); // Add everything to the JFrame
}
// List to hold all of the color buttons
ArrayList<ColorButton> colorButtons;
private void createColorButtons() // Create and add all color buttons
{
colorButtons = new ArrayList<ColorButton>();
colorButtons.add(new ColorButton(Color.BLACK, "black_paint.png"));
colorButtons.add(new ColorButton(Color.WHITE, "white_paint.png"));
// colorButtons.add(new ColorButton(new Color(22, 10, 255), "blue_paint.png"));
// colorButtons.add(new ColorButton(new Color(163, 92, 45), "brown_paint.png"));
// colorButtons.add(new ColorButton(new Color(19, 175, 50), "dark_green_paint.png"));
// colorButtons.add(new ColorButton(new Color(22, 255, 34), "green_paint.png"));
// colorButtons.add(new ColorButton(new Color(58, 209, 255), "light_blue_paint.png"));
// colorButtons.add(new ColorButton(new Color(255, 84, 33), "orange_paint.png"));
// colorButtons.add(new ColorButton(new Color(255, 86, 243), "pink_paint.png"));
// colorButtons.add(new ColorButton(new Color(168, 11, 121), "purple_paint.png"));
// colorButtons.add(new ColorButton(new Color(255, 0, 0), "red_paint.png"));
// colorButtons.add(new ColorButton(new Color(255, 241, 45), "yellow_paint.png"));
colorButtons.add(new ColorButton(Color.WHITE, "eraser.png"));
}
JPanel colorButtonPanel;
private void addComponents() // Add all the components to the screen
{
createColorButtons();
colorButtonPanel = new JPanel();
colorButtonPanel.setLayout(new BoxLayout(colorButtonPanel,
BoxLayout.X_AXIS));
colorButtonPanel.setBorder(new TitledBorder("Colors & Tools"));
for (ColorButton button : colorButtons)
{
colorButtonPanel.add(button);
}
// Add Panels
add(BorderLayout.SOUTH, colorButtonPanel);
}
}
So, as you can see, the class inherits from JFrame, and all the components are added to the frame in addComponents(). The method that I believe the problem lies in is in createColorButtons(). Right now, all the buttons that aren't displaying are commented out and the other ones are the only buttons that work. The problem here is very specific. If I start the program with any button implemented that doesn't work (ie. any colorButtons.add(foo) that is commented out), then the frame comes up completely empty. None of the buttons appear, just a blank frame. However, if I start the program with all of those buttons commented out, then I can still get the three buttons.
The only thing that is different from these buttons versus the others is that the buttons that won't display use custom created colors, while others use pre-set colors included in the Java API. I can't think of any reason why that should cause any problem, but let me know if you think otherwise. Also let me know if you need any more details, code, or anything else that you can think of that might help you answer the question. Thanks.
Added Main Method for added measures:
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Start // Start the program
{
public static void main(String[] args)
{
try // Get default system look & feel
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (
UnsupportedLookAndFeelException |
ClassNotFoundException |
InstantiationException |
IllegalAccessException e)
{
e.printStackTrace();
}
new PaintFrame();
}
}
EDIT: Yes, all of the images are in the correct folder and are named correctly. No worries there.
public PaintFrame()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true); // ***** telling Java to render the GUI
setSize(1150, 650);
setLocationRelativeTo(null);
setResizable(false);
setLayout(new BorderLayout());
setTitle("Paint 2.0");
addComponents(); // Add everything to the JFrame **after** rendering it! **
}
Don't call setVisible(true) until after adding all components to the GUI. Otherwise there's no guarantee that components added after calling setVisible(true) will ever be rendered.
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);
}
}
I am attempting to add another checkbox to this program but for some reason it will not display when I run the program. Only the check box for the blue pill displays. I have attempted to add a couple things or change the way the program is structured, but nothing I have done so far has helped.
Code Below:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class CMIS242WK4DonnersonAReply {
static JCheckBox red;
static JCheckBox blue;
static JButton button;
public CMIS242WK4DonnersonAReply() {
button = new JButton("submit"); // Creates submit button
widget
ButtonHandler listener = new ButtonHandler(); // Creates the handler for the button.
button.addActionListener((ActionListener) listener); // adds the handler to the button widget
JPanel content = new JPanel(); // "container"
content.setLayout(new BorderLayout());
content.add(button, BorderLayout.PAGE_END);// places submit button at the bottom of panel.
JLabel label = new JLabel("At last. Welcome, Neo. As you no doubt have guessed, I am Morpheus. This is your last chance. After this there is no turning back."); // Label in frame.
content.add(label, BorderLayout.NORTH);// places label at the top of the screen.
//Creating Check Boxes
JCheckBox red = new JCheckBox("You take the red pill, you stay in Wonderland and I show you how deep the rabbit hole goes.");
red.setBounds(100,100, 50,50);
content.add(red);
JCheckBox blue = new JCheckBox("You take the blue pill, the story ends, you wake up in your bed and believe whatever you want to believe. ");
blue.setBounds(100,100, 50,50);
content.add(blue);
//Adding Frame
JFrame window = new JFrame("Matrix Monologue"); // JFrame = Window
window.setContentPane(content);
window.setSize(750,200); // Length, Height
window.setLocation(200,200); // X/Y "OF THE ENTIRE FRAME" Not the contents
window.setVisible(true); // makes window visible
}
// Method handles what happens when button is pressed.
private static class ButtonHandler implements ActionListener{
public void actionPerformed1(ActionEvent e) {
// Checks if which pill was selected and responds to user depending on their action.
if (red.isSelected() == true) {
System.out.println("Follow me");
System.out.println();
}
if (blue.isSelected() == true) {
System.out.println("Very Well, You may go back to your world");
System.out.println();
}
else
System.out.println("You must make a choice for what pill you will take");
System.exit(0); //closes program
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
// Main/driver method that runs everything.
public static void main(String[] args) {
CMIS242WK4DonnersonAReply matrixMonologue= new CMIS242WK4DonnersonAReply();
}
}
Any pointers?
When you're stuck on a problem, it never hurts to go back and consult the documentation.
You'll find information like this:
A border layout lays out a container, arranging and resizing its
components to fit in five regions: north, south, east, west, and
center. Each region may contain no more than one component, and is
identified by a corresponding constant: NORTH, SOUTH, EAST, WEST, and
CENTER. When adding a component to a container with a border layout,
use one of these five constants...
When you add your button, you do this:
content.add(button, BorderLayout.PAGE_END);
But then, when it's time to add checkboxes, you do this:
content.add(red);
...
content.add(blue);
Are you seeing what's missing? My bet is that you only see the blue checkbox because you added it on top of (or simply displaced) the red checkbox. Remember, the doc says "Each region may contain no more than one component..."
Try specifying the region of your BorderLayout where you want to see each checkbox.
If you want them to appear in the same region, put them in a JPanel of their own and lay them out at NORTH and SOUTH or EAST and WEST and then add that checkbox panel to your content panel in the region you want them to appear.
I feel that you need some guidance with your Swing programming. I have rewritten your CMIS242WK4DonnersonAReply class. Code is below. But first some comments about the code in your question.
JCheckBox red = new JCheckBox("You take the red pill, you stay in Wonderland and I show you how deep the rabbit hole goes.");
You have created a local variable which is hiding the class member. Hence static JCheckBox red; remains null and consequently the following if statement will throw NullPointerException.
if (red.isSelected() == true) {
By the way, the == true is not necessary. The following is sufficient.
if (red.isSelected()) {
Now another point.
red.setBounds(100,100, 50,50);
Since you are using a layout manager, namely BorderLayout, method setBounds will be ignored. The layout manager determines where to place the component on the screen.
window.setContentPane(content);
By default, the content pane of JFrame is a JPanel with BorderLayout so no need to replace the default content pane.
private static class ButtonHandler implements ActionListener
No need to create a nested class. Simply make class CMIS242WK4DonnersonAReply implement the ActionListener interface.
System.out.println("Follow me");
I don't think it's a good idea to involve the console in a GUI application. I would use JOptionPane to display a message to the user.
static JCheckBox blue;
I think that JRadioButton is more appropriate than JCheckBox in your situation.
Here is my code.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class CMIS242WK4DonnersonAReply implements Runnable, ActionListener {
private JButton button;
private JRadioButton blue;
private JRadioButton red;
private JFrame window;
#Override
public void actionPerformed(ActionEvent event) {
if (red.isSelected()) {
JOptionPane.showMessageDialog(window, "Follow me.");
}
else if (blue.isSelected()) {
JOptionPane.showMessageDialog(window, "Very Well, You may go back to your world");
}
else {
JOptionPane.showMessageDialog(window, "You must make a choice for what pill you will take");
}
}
#Override
public void run() {
createAndShowGui();
}
private void createAndShowGui() {
window = new JFrame("Matrix Monologue");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("At last. Welcome, Neo. As you no doubt have guessed, I am Morpheus. This is your last chance. After this there is no turning back."); // Label in frame.
window.add(label, BorderLayout.PAGE_START);
window.add(createCheckBoxes(), BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
button = new JButton("submit");
button.addActionListener(this);
buttonPanel.add(button);
window.add(buttonPanel, BorderLayout.PAGE_END);
window.setSize(750,200); // Length, Height
window.setLocation(200,200); // X/Y "OF THE ENTIRE FRAME" Not the contents
window.setVisible(true); // makes window visible
}
private JPanel createCheckBoxes() {
JPanel panel = new JPanel();
BoxLayout layout = new BoxLayout(panel, BoxLayout.PAGE_AXIS);
panel.setLayout(layout);
red = new JRadioButton("You take the red pill, you stay in Wonderland and I show you how deep the rabbit hole goes.");
blue = new JRadioButton("You take the blue pill, the story ends, you wake up in your bed and believe whatever you want to believe.");
ButtonGroup grp = new ButtonGroup();
grp.add(red);
grp.add(blue);
panel.add(red);
panel.add(blue);
return panel;
}
public static void main(String[] args) {
EventQueue.invokeLater(new CMIS242WK4DonnersonAReply());
}
}
Here is how the app looks when I run it.
I had been frustrated with some really odd behavior in my code for a while, and after taking time to slowly widdle down my code bit by bit, I finally found the source of the issue.
General overview: using Java Swing, the following code creates a tabbed interface. The first tab that is visible to the user has a button. The second tab has a blue square in the upper left hand corner.
What should happen: Once the program is open, click the button first and then open the other tab. The button calls a function on the other tab, causing the square to move to a new location. Thus, the other tab should show the square in its new location, not the upper left hand corner.
What actually happens: If you click the button first and then open the tab, the square's position is unchanged. It remains in the upper left hand corner, as if the button was never pressed. If you open the tab first, it seems to "prime" the program somehow, so now the button works as expected.
Sure, it seems like a minor annoyance to click on the tab first to ensure the program works, but potentially this is a really big problem. Why is the tab unable to be updated until it is viewed at least once?
Observations: When debugging the code, I can step through the setUnit() function and verify that the square is, in fact, being successfully changed, completely overwriting the previous position. And yet, when I then open the second tab the square's position is now reverted back to where it was previously. If the variables are inspected at that point, it shows the square's original position has remained completely unchanged, as if the setUnit() function was never called. Knowing that these components don't visually update unless repainted, I made sure to add the repaint() function call within the setUnit() function. It really baffles me to wonder where the original values of the square's location are even stored? I can see in the debugger the values are overwritten, so they should completely cease to exist, right?
Code:
DragPanel.java:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JPanel;
class DragPanel extends JPanel
{
private static final long serialVersionUID = 1L;
boolean isFirstTime = true;
Rectangle area;
Rectangle rect = new Rectangle(0, 0, 20, 20);
private Dimension dim = new Dimension(400, 300);
public DragPanel() {
setBackground(Color.white);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
if (isFirstTime) {
area = new Rectangle(dim);
rect.setLocation(0, 0);
isFirstTime = false;
}
g2d.setColor(Color.blue);
g2d.fill(rect);
}
public void setUnit()
{
rect.setLocation(200, 50);
repaint();
}
}
ShapeMover.Java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
public class ShapeMover {
public ShapeMover() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents(frame);
}
public static void main(String s[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ShapeMover();
}
});
}
private void initComponents(JFrame frame) {
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
tabbedPane.setBounds(10, 93, 426, 527);
frame.getContentPane().add(tabbedPane);
DragPanel shaper = new DragPanel();
shaper.setBounds(0, 79, 420, 420);
JPanel input = new JPanel();
tabbedPane.addTab("Test", null, input, null);
input.setLayout(null);
JButton add = new JButton("Click this");
add.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
shaper.setUnit();
}
});
add.setBounds(201, 64, 65, 23);
input.add(add);
JPanel output = new JPanel();
tabbedPane.addTab("Second", null, output, null);
output.setLayout(null);
output.add(shaper);
frame.pack();
frame.setVisible(true);
}
}
Based on tgdavies comment, I found the solution to the situation.
paintComponent is not part of the construction of the object, but rather is only called whenever the panel is seen. That is, when it is painted. Even calling repaint() is not going to call paintComponent until the panel is seen. Thus, the first time the panel is viewed then this section of code is executed exactly once:
if (isFirstTime)
{
area = new Rectangle(dim);
rect.setLocation(0, 0);
isFirstTime = false;
}
After being executed once, isFirstTime is set to false, and thus doesn't run the section of code again. Thus, calling setUnit() does, indeed, overwrite the square's original position. And then the section of code shown above sets it back to 0,0.
Simply commenting out the line of code that reads rect.setLocation(0, 0); fixes the problem.
I am currently working on a short Java Swing project using Eclipse (Luna, Win 8.1). The aim is to display a frame that contains a menu. The menu has different pages (Main, Options, etc.), realized by JPanels with Buttons, Labels, etc. Those JPanels are organized by a CardLayout, in such a manner that calling the CardLayout.show(..)-method switches between different menu pages. When I stopped programming two days ago, everything was working perfectly. However, when I wanted to continue yesterday morning, my code seemed to completely ignore the CardLayout: Buttons situated in other cards would pop up through the first card's background when moving the mouse cursor over their positions. I tried to fix that (researching, using backups, etc.) for 17 hours straight. The problem still persists and I am pretty desperate by now =/. The following SSCCE shows the same behaviour (move mouse over bottom left corner to see the "Option" card's "Back" button pop up).
package sscce;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainFrame extends JFrame {
private CardLayout mainWindowLayout;
// mainPanel will be used as the MainFrame's main unit to manage Components
private JPanel mainPanel;
// Constructor
public MainFrame() {
setTitle("sscce");
setPreferredSize(new Dimension(800, 600));
setResizable(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout());
mainPanel = new JPanel();
mainPanel.setPreferredSize(getSize());
mainWindowLayout = new CardLayout();
mainPanel.setLayout(mainWindowLayout);
buildMainMenu();
buildOptions();
getContentPane().add(mainPanel);
mainPanel.setVisible(true);
// starting application it will "show" (container,
// contentIdentifier(String))
mainWindowLayout.show(mainPanel, "2");
pack();
setVisible(true);
}// Constructor
private void buildMainMenu() {
JPanel panelMainMenu = new JPanel(new GridBagLayout());
panelMainMenu.setBackground(Color.orange);
// 1 Button (centered) to go to Options-Card
JButton bnOptions = new JButton("Options");
// Button Functionality
bnOptions.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
mainWindowLayout.show(mainPanel, "2");
}
});
panelMainMenu.add(bnOptions);
panelMainMenu.setOpaque(true);
// container content identifier(String)
mainPanel.add(panelMainMenu, "1");
panelMainMenu.setVisible(true);
}// buildMainMenu
private void buildOptions() {
JPanel panelOptions = new JPanel();
panelOptions.setLayout(new GridBagLayout());
// standardized margins for all Elements:
final Insets gbcInsets = new Insets(5, 5, 5, 5);
panelOptions.setBackground(Color.white);
JPanel fillerRight = new JPanel();
JPanel fillerTop = new JPanel();
JButton bnOptBack = new JButton("Back");
bnOptBack.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
mainWindowLayout.show(mainPanel, "1");
}
});
// add filler panels to keep button in position
fillerRight.setBackground(Color.red);
fillerRight.setOpaque(true);
panelOptions.add(fillerRight, new GridBagConstraints(1, 1, 1, 2, 1, 0,
GridBagConstraints.NORTH, GridBagConstraints.BOTH, gbcInsets,
0, 0));
fillerRight.setVisible(true);
fillerTop.setBackground(Color.pink);
fillerTop.setOpaque(true);
panelOptions.add(fillerTop, new GridBagConstraints(0, 0, 2, 1, 0, 1,
GridBagConstraints.NORTH, GridBagConstraints.BOTH, gbcInsets,
0, 0));
fillerTop.setVisible(true);
// 1 Button in lower left hand corner, sends you back to MainMenu-card
panelOptions.add(bnOptBack, new GridBagConstraints(0, 1, 1, 1, 0, 0,
GridBagConstraints.NORTH, GridBagConstraints.BOTH, gbcInsets,
0, 0));
bnOptBack.setVisible(true);
panelOptions.setOpaque(true);
// container content identifier(String)
mainPanel.add(panelOptions, "2");
panelOptions.setVisible(true);
}// buildOptions
public static void main(String[] args) {
MainFrame m = new MainFrame();
}// main
}// MainFrame
Any help is greatly appreciated.
Thanks in advance :)
Edit: I guess you don't need to look at the "buildMainMenu" and "buildOptions" methods too closely, the setup for the single menu pages seems to work fine.
It works as expected on my machine when I comment out the following two lines
panelOptions.setVisible(true);
and
panelMainMenu.setVisible(true);
When using the CardLayout, you just add the components and use CardLayout#show to decide which one you show. Calling setVisible first seems to cause problems (for whatever reason).
Making sure that the Swing code is triggered on the EDT is also a good idea:
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MainFrame m = new MainFrame();
}
});
look at this simple code:
Main.java :
package CarManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
static int width = 400;
static int height = width / 16 * 9;
static String title = "Car Manager";
JButton viewTables = new JButton("View tables");
JButton clients = new JButton("Clients");
JButton search = new JButton("Search");
JButton viewCars = new JButton("View all");
JButton viewRent = new JButton("Rent a car");
JButton viewBuy = new JButton("Buy a car");
JButton viewAccessory = new JButton("Accessory");
public Main() {
setLayout(null);
setLocationRelativeTo(null);
setTitle(title);
setSize(width, height);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
JLabel background = new JLabel(new ImageIcon("res\\background2.jpg"));
add(background);
background.setSize(width, height);
add(viewTables);
add(clients);
add(search);
viewTables.setBounds(20, 20, 110, 30);
clients.setBounds(20, 70, 110, 30);
search.setBounds(20, 120, 110, 30);
viewTables.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
add(viewCars);
viewCars.setBounds(260, 20, 110, 20);
add(viewRent);
viewRent.setBounds(260, 50, 110, 20);
add(viewBuy);
viewBuy.setBounds(260, 80, 110, 20);
add(viewAccessory);
viewAccessory.setBounds(260, 110, 110, 20);
}
});
viewCars.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
View view = new View();
view.addWindowListener(new WindowPlug(Main.this));
setVisible(false);
}
});
}
public static void main(String args[]) {
new Main();
}
}
View.java:
package CarManager;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class View extends JFrame {
private static final long serialVersionUID = 1L;
int width = 400;
int height = width / 16 * 9;
String title = "View all Cars";
public View() {
setLayout(null);
setLocationRelativeTo(null);
setTitle(title);
setSize(width, height);
setResizable(false);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setVisible(true);
JLabel background = new JLabel(new ImageIcon("res\\background2.jpg"));
add(background);
background.setSize(width, height);
}
}
and WindowPlug.java:
package CarManager;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class WindowPlug extends WindowAdapter {
private Main mainFrame;
public WindowPlug(Main mainFrame) { // when creating an instance of this
// WindowAdapter, tell it with which
// Main Window you are working with
this.mainFrame = mainFrame;
}
public void windowClosing(WindowEvent e) {
mainFrame.setVisible(true);
mainFrame.revalidate();
}
}
when i click view tables and then view all (those are the buttons that work for now)
and the first window hides and a new window appears, now when i close the second window the first one appears visible but the buttons are not visible, i have to hover over with the mouse for them to be visible again. ive tried mainFrame.revalidate(); and
mainFrame.repaint();
but no result
im using windows 8.1 pro
One problem with your code, and I'm not sure if this is the main problem since your code works fine on my system, is that you're calling setVisible(true) on your main window before you've added all your components. It should only be called after all components have been added.
Other problems unrelated to your main question:
You should avoid using null layout. While using null layout may seem to a newbie the better way to create complex GUI's, it's a fallacy, and more you create Swing GUI's the more you learn to respect and use the layout managers and see that these creatures help immensely in creating flexible, beautiful and if need be, complex GUI's. Then you can let them size them selves appropriately by calling pack() prior to setting them visible.
It appears that you really want to use a CardLayout to swap views on one GUI rather than spitting multiple GUI's at the user.
If you absolutely must display a dialog window, then you should use a JDialog, not a JFrame. If you used a modal JDialog, you wouldn't be needing a WindowListener.
Edit
OK, a big problem I see is that you're using null layout and adding a JLabel that covers the whole contentPane, and then adding components to the same contentPane.
Instead, make the JLabel your contentPane, and then add your JButtons, etc to it.
But make sure that the JLabel's opaque property is set to true first.
Edit 2
If you need to use an image as a background image you can:
Put the Image in an ImageIcon, put the Icon in a JLabel, and again use the JLabel as your contentPane. Again, you will need to make the JLabel opaque by calling setOpaque(true) on it. This works well if you don't want to change the size of the image or the window.
If you do need to change the size of the image, better to have a JPanel draw the image in its paintComponent(Graphics g) method, and then use this JPanel as your contentPane.
Once you've created your contentPane, then set its layout and add your components to it.
Then call setContentPane(newContentPane) on your top level window and pass in the new contentPane.