setUndecorated(true) content of the JFrame not displaying - java

I'm creating a gui with java swing who is supposed to be implemented on an LCD touch screen. The gui will take all the screen and is not supposed to be closable. So "setUndecorated(true)" is essential.
Problem, when I'm using it, all the content of the frame is not displaying, only the buttons appears when I'm moving my mouse over them. Then all the content appears when I maximise and minimise the frame.
Here is the code I'm using :
public static void main(String[] args) {
//Création de notre JFrame
fenetre = new JFrame();
fenetre.setTitle("IHM");
fenetre.setSize(800, 600);
fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fenetre.setLocationRelativeTo(null);
support = new JPanel();
///////Adding content to the JPanel()/////////////
fenetre.setContentPane(support);
fenetre.setUndecorated(true);
fenetre.setVisible(true);
}
The only solution I've find so far is to change the size of the frame after set the frame visible like so :
fenetre.setSize(801, 601);
fenetre.setSize(800, 600);
But I'm not really correcting the problem, just getting around it.
(EDIT)
My appologies for that uncomplete code.
Here is a complete exemple that you can test yourself.
First test it with undecorated to false, then try with undecorated to true and visualise the content of the window by maximising and minimising the gui.
Finally, try it with the Quick fix in the bottom of the code.
the code :
package test;
import java.awt.Color;
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.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class test {
//Declarations
private static JFrame fenetre;
private static JPanel support;
private static JLabel l1, l2;
private static JComboBox<String> c1, c2;
private static JButton b1, b2;
//List to initiate the comboBoxes
private static String[] listC1 = {"Peter", "Alex", "Jhon", "Bran"};
private static String[] listC2 = {"10", "20", "32", "45"};
public static void main(String[] args) {
//Initialisation of the JFrame
fenetre = new JFrame();
fenetre.setTitle("IHM");
fenetre.setSize(800, 600);
fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fenetre.setLocationRelativeTo(null);
//Initialisation of the JPanel
support = new JPanel();
support.setBackground(Color.red);
support.setPreferredSize(fenetre.getSize());
//Initialisation of the components
l1 = new JLabel("What's my name");
l2 = new JLabel("What's my age");
c1 = new JComboBox<String>(listC1);
c2 = new JComboBox<String>(listC2);
b1 = new JButton("validate name");
b2 = new JButton("validate age");
//Creating layout
support.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
//Adding components
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(20, 20, 0, 0);
gbc.gridx = 0;
gbc.gridy = 0;
support.add(l1, gbc);
gbc.gridy = 1;
support.add(c1, gbc);
gbc.insets = new Insets(20, 20, 20, 0);
gbc.gridy = 2;
support.add(b1, gbc);
gbc.insets = new Insets(20, 20, 0, 20);
gbc.gridx = 1;
gbc.gridy = 0;
support.add(l2, gbc);
gbc.gridy = 1;
support.add(c2, gbc);
gbc.insets = new Insets(20, 20, 20, 20);
gbc.gridy = 2;
support.add(b2, gbc);
//Adding Listeners
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("My name is " + c1.getSelectedItem());
}
});
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("My age is " + c2.getSelectedItem());
}
});
//Adding the JPanel to the content pane of the JFrame
fenetre.setContentPane(support);
//Setting undecorated true (switch between true and false for testing)
fenetre.setUndecorated(false);
fenetre.setVisible(true);
//Quick fix, uncomment to test
//fenetre.setSize(801, 601);
//fenetre.setSize(800, 600);
}
}

You don't add any buttons to your JPanel so how do you expect it to display them?
Either way, here's a simple example of displaying a button:
JFrame fenetre = new JFrame();
fenetre.setTitle("IHM");
fenetre.setExtendedState(JFrame.MAXIMIZED_BOTH);
fenetre.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
fenetre.setLocationRelativeTo(null);
JPanel support = new JPanel();
JButton button = new JButton("button");
support.add(button);
fenetre.setContentPane(support);
fenetre.setVisible(true);
Note that you should use a proper layout.
I also added setExtendedState(JFrame.MAXIMIZED_BOTH) to fill the screen, and setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE) as you didn't want the screen to be closable.

Problem, when I'm using it, all the content of the frame is not displaying, only the buttons appears when I'm moving my mouse over them.
Components should be added to the panel/frame BEFORE the frame is made visible.
If you add components to a visible frame, then the basic logic is:
panel.add(...);
panel.revalidate(); // to invoke the layout manager
panel.repaint(); // make sure panel is repainted

Related

Weird problem with GUI programming in Java

I have made a simple GUI in Java. The problem is, when I add label to the frame before buttons and check-buttons I get weird flickering when hovering over buttons, and GUI doesn't look right. But when I add label after buttons and check-buttons everything is working fine. Why is this happening?
Here is my code:
package javaapplication13;
import java.awt.*;
import javax.swing.*;
public class JavaApplication13 {
public static void main(String[] args) {
ButtonFrame bf = new ButtonFrame();
}
}
class ButtonFrame extends JFrame {
public ButtonFrame() {
JButton b1 = new JButton("1. Dugme");
JButton b2 = new JButton("2. Dugme");
JLabel l1 = new JLabel();
JCheckBox c1 = new JCheckBox("Prvo dugme");
JCheckBox c2 = new JCheckBox("Drugo dugme");
Container cp = getContentPane();
setTitle("Dugme");
setSize(400,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
this.add(b1);
this.add(b2);
this.add(c1);
this.add(c2);
this.add(l1);
b1.setBounds(20, 30, 90, 20);
b2.setBounds(20,70,90,20);
l1.setBounds(70,120,90,20);
c1.setBounds(120,30,120,20);
c2.setBounds(120,70,120,20);
l1.setText("");
}
}
I did not see the flickering you claim to be getting when I copied and ran your code on my Windows 10 computer with JDK 17. However, when I changed your code and added the label to the frame before adding the buttons and check-boxes (as you stated in your question), I did see "flickering".
Although you have already accepted #Antoniossss answer, it is not recommended to not use a layout manager. Refer to the following excerpts from Doing Without a Layout Manager
Although it is possible to do without a layout manager, you should use a layout manager if at all possible.
If a container holds components whose size is not affected by the container's size or by font, look-and-feel, or language changes, then absolute positioning might make sense.
One of the layout managers that your GUI lends itself to is GridBagLayout, although that is not the only suitable one. The below code shows how. (Note that in the below code I set the text of the JLabel so that you can see it.)
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class BtnFrame {
private void createAndDisplayGui() {
JFrame frame = new JFrame("Dugme");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
createForm(frame.getContentPane());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private void createForm(Container contentPane) {
if (contentPane instanceof JComponent) {
JComponent jCmpt = (JComponent) contentPane;
jCmpt.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets.bottom = 5;
gbc.insets.left = 5;
gbc.insets.right = 5;
gbc.insets.top = 5;
JButton b1 = new JButton("1. Dugme");
contentPane.add(b1, gbc);
gbc.gridx = 1;
JCheckBox c1 = new JCheckBox("Prvo dugme");
contentPane.add(c1, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
JButton b2 = new JButton("2. Dugme");
contentPane.add(b2, gbc);
gbc.gridx = 1;
JCheckBox c2 = new JCheckBox("Drugo dugme");
contentPane.add(c2, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.CENTER;
JLabel l1 = new JLabel("label");
contentPane.add(l1, gbc);
}
public static void main(String[] args) {
final BtnFrame gui = new BtnFrame();
EventQueue.invokeLater(() -> gui.createAndDisplayGui());
}
}
Here is a screen capture of the application.
When setting the layout manager to null in your code (as #Antoniossss said in his answer), the GUI looks like the below screen capture. (Again, I also set the text of the JLabel so that you can see it.)
As you can see, the two screen captures are practically identical.
For completeness, here is your code, with my changes, that produce the above screen capture. As you can see, I moved the line this.add(l1) and also added the line cp.setLayout(null).
import java.awt.Container;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ButtonFrame extends JFrame {
public ButtonFrame(){
JButton b1 = new JButton("1. Dugme");
JButton b2 = new JButton("2. Dugme");
JLabel l1 = new JLabel();
JCheckBox c1 = new JCheckBox("Prvo dugme");
JCheckBox c2 = new JCheckBox("Drugo dugme");
Container cp = getContentPane();
cp.setLayout(null); // Added this line.
setTitle("Dugme");
setSize(400,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
this.add(l1);
this.add(b1);
this.add(b2);
this.add(c1);
this.add(c2);
// this.add(l1);
b1.setBounds(20, 30, 90, 20);
b2.setBounds(20,70,90,20);
l1.setBounds(70,120,90,20);
c1.setBounds(120,30,120,20);
c2.setBounds(120,70,120,20);
l1.setText("label");
}
public static void main(String[] args) {
ButtonFrame bf = new ButtonFrame();
}
}
It is because of the default LayoutManager which you dont want to use anyway since you are using strict bounds on your components. Remove layout manager with
setLayout(null);
And it will work as intended
public ButtonFrame(){
setLayout(null); //this will do the trick
JButton b1 = new JButton("1. Dugme");
...rest of your code
}

GridBagLayout not moving components no matter what values entered?

I currently have a jpanel with layout set to GridBagLayout, with gbc = new GridBagConstraints();, However for whatever value of x, y or gridwidth,gridheight the items don't move at all.
I would greatly appreciate an expert eye to look over my code to see what I am missing, Thanks in advance.
Edit: Added the imports and the main method
Edit 2: turns out I was thinking the x and y values were pixels and that was the reason it wasn't working
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class HomeScreenUI {
public void addobjects(Component componente, Container yourcontainer, GridBagLayout layout, GridBagConstraints gbc, int gridx, int gridy, int gridwidth, int gridheight){
gbc.gridx = gridx;
gbc.gridy = gridy;
gbc.gridwidth = gridwidth;
gbc.gridheight = gridheight;
layout.setConstraints(componente, gbc);
yourcontainer.add(componente);
}
HomeScreenUI(){
//frame
JFrame frame = new JFrame("Opisa");
//panels, one before button click and one after
JPanel panel = new JPanel();
JPanel panelAfterButtonClick = new JPanel();
GridBagLayout ourlayout;
ourlayout = new GridBagLayout();
panel.setLayout(ourlayout);
panelAfterButtonClick.setLayout(ourlayout);
GridBagConstraints gbc = new GridBagConstraints();
//jlabel that isnt displaying + dimensions
JLabel label = new JLabel("Opisa");
label.setFont(new Font("Helvetica", Font.PLAIN, 70));
//second jlabel that isn't displaying
JLabel label2 = new JLabel("Home");
label2.setFont(new Font("Helvetica", Font.PLAIN, 70));
//adding the labels to the panels
panel.add(label);
panelAfterButtonClick.add(label2);
//button that is displaying both before and after
JButton button = new JButton("Click Me..");
JButton buttonAfterClick = new JButton("Clicked Me..");
//adding the buttons to the jpanel
this.addobjects(label, panel, ourlayout, gbc, 0,0, 3, 1);
this.addobjects(button, panel, ourlayout, gbc, 700, 100, 2, 0);
this.addobjects(label2, panelAfterButtonClick, ourlayout, gbc, 200, 200, 1, 1);
this.addobjects(buttonAfterClick, panelAfterButtonClick, ourlayout, gbc, 700, 10, 2, 0);
//function that changes the panel after the button is clicked
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
frame.setContentPane(panelAfterButtonClick);
frame.invalidate();
frame.validate();
}
});
//adding the panel to the frame and setting the size
frame.add(panel);
frame.setSize(720,1280);
frame.setVisible(true);
}
}
public static void main (String args[]) {
HomeScreenUI hs = new HomeScreenUI();
}
It seems you are using GridBagLayout completely different than it was designed for.
Note you have one instance of GridBagLayout but want to use it for two panels. Each panel needs to have it's own LayoutManager instance.
Then look how many GridBagConstraints you have. Each Component that shall be added needs it's own instance to be properly managed.
Then there are strange values you are passing into GridBagConstraints. I suggest you take the time and go through How to Use GridBagLayout.
I modified your code to create the following GUI.
Here's what it looks like after you left-click the button.
You can swap back and forth between the two panels.
Here are the major changes I made to your code.
Code should be organized like an essay. The most important code should come first, followed by the less important code.
Break your code up into methods and classes. Each method should do one thing and do it well. This is called separation of concerns and it helps you to focus on one part of your code at a time.
To start the Swing application, I made a call to the SwingUtilities invokeLater method. This method ensures that all Swing components are created and executed on the Event Dispatch Thread.
The JFrame code is in the class constructor. The JFrame code has to be called in a certain order. This is the order I use for most of my Swing applications. Don't forget to call the setDefaultCloseOperation method. The JFrame.EXIT_ON_CLOSE parameter exits the application when you close the JFrame.
I used a CardLayout to hold the two subordinate JPanels. I created the CardLayout in its own method.
I created each subordinate JPanel in its own method. I used a GridBagLayout for both subordinate JPanels. As you can see in the code, you have to set quite a few GridBagConstraints parameters.
I created an anonymous ActionListener for each of the JButtons. The ActionListeners swap the two subordinate JPanels in the CardLayout.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Font;
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.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class HomeScreenUI {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new HomeScreenUI();
}
});
}
private CardLayout cardLayout;
private JPanel cardPanel;
public HomeScreenUI() {
JFrame frame = new JFrame("Opisa");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.cardPanel = createCardPanel();
frame.add(cardPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createCardPanel() {
cardLayout = new CardLayout();
JPanel panel = new JPanel(cardLayout);
panel.add(createOpisaPanel(), "Opisa");
panel.add(createHomePanel(), "Home");
return panel;
}
private JPanel createOpisaPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridx = 0;
gbc.gridy = 0;
// jlabel that isnt displaying + dimensions
JLabel label = new JLabel("Opisa");
label.setFont(new Font("Helvetica", Font.PLAIN, 72));
panel.add(label, gbc);
gbc.gridy++;
JButton button = new JButton("Click Me..");
// function that changes the panel after the button is clicked
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
cardLayout.show(cardPanel, "Home");
}
});
panel.add(button, gbc);
return panel;
}
private JPanel createHomePanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridx = 0;
gbc.gridy = 0;
// second jlabel that isn't displaying
JLabel label2 = new JLabel("Home");
label2.setFont(new Font("Helvetica", Font.PLAIN, 72));
panel.add(label2, gbc);
gbc.gridy++;
JButton buttonAfterClick = new JButton("Clicked Me..");
buttonAfterClick.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
cardLayout.show(cardPanel, "Opisa");
}
});
panel.add(buttonAfterClick, gbc);
return panel;
}
}

Set Image to Button and process ActionListener in Puzzle Game using Java

I only learn Java Swing 1 week so I tried complete some exercises. This is my code. I set 9 icon to 9 button but it doesn't show on button.
package mypack;
import java.awt.Color;
import javax.swing.*;
public class PuzzleGame extends JFrame{
static JButton bt1,bt2,bt3,bt4,bt5,bt6,bt7,bt8,bt9,btNew,btExit;
static JLabel move, moveNum, time, timeNum;
public PuzzleGame(){
createMyGUI();
}
public static void createMyGUI(){
JFrame jf = new JFrame("Game Puzzle Java");
JPanel jpl = new JPanel();
Icon icSpace = new ImageIcon("images/0.png");
Icon ic1 = new ImageIcon("images/1.png");
Icon ic2 = new ImageIcon("images/2.png");
Icon ic3 = new ImageIcon("images/3.png");
Icon ic4 = new ImageIcon("images/4.png");
Icon ic5 = new ImageIcon("images/5.png");
Icon ic6 = new ImageIcon("images/6.png");
Icon ic7 = new ImageIcon("images/7.png");
Icon ic8 = new ImageIcon("images/8.png");
jpl.setSize(100,100);
jpl.setBounds(480, 50, 200, 200);
jpl.setBackground(Color.BLUE);
move = new JLabel("Move:");
move.setBounds(480,10,50,20);
moveNum = new JLabel("0");
moveNum.setBounds(530, 10, 50, 20);
time = new JLabel("Time:");
time.setBounds(580, 10, 50, 20);
timeNum = new JLabel("0");
timeNum.setBounds(630,10,50,20);
btNew = new JButton("New Game");
btNew.setBounds(480, 270, 200, 80);
btExit = new JButton("Exit");
btExit.setBounds(480, 370, 200, 80);
jf.add(move);
jf.add(moveNum);
jf.add(time);
jf.add(timeNum);
jf.add(btNew);
jf.add(btExit);
jf.add(jpl);
jf.setSize(700, 500);
jf.setLocation(300,20);
jf.setLayout(null);
jf.setResizable(false);
jf.setVisible(true);
bt1 = new JButton();
bt1.setBounds(10, 10, 150, 150);
bt1.setIcon(ic1);
bt2 = new JButton();
bt2.setBounds(160, 10, 150, 150);
bt2.setIcon(ic2);
bt3 = new JButton();
bt3.setBounds(310, 10, 150, 150);
bt3.setIcon(ic3);
bt4 = new JButton();
bt4.setBounds(10, 160, 150, 150);
bt4.setIcon(ic4);
bt5 = new JButton();
bt5.setBounds(160, 160, 150, 150);
bt5.setIcon(ic5);
bt6 = new JButton();
bt6.setBounds(310, 160, 150, 150);
bt6.setIcon(ic6);
bt7 = new JButton();
bt7.setBounds(10, 310, 150, 150);
bt7.setIcon(ic7);
bt8 = new JButton();
bt8.setBounds(160, 310, 150, 150);
bt8.setIcon(ic8);
bt9 = new JButton();
bt9.setBounds(310, 310, 150, 150);
bt9.setIcon(icSpace);
jf.add(bt1);
jf.add(bt2);
jf.add(bt3);
jf.add(bt4);
jf.add(bt5);
jf.add(bt6);
jf.add(bt7);
jf.add(bt8);
jf.add(bt9);
}
public static void main(String[] args){
PuzzleGame.createMyGUI();
}
}
I think method setIcon is not apply for Button. Besides, someone show me how to set a action to arrange mess picture into a complete picture in Puzzle Game with my code.
I see some issues in your code:
You're extending JFrame and creating a new JFrame object inside your class. You're never using the JFrame of your class (the extended one). So it's wise to just remove it.
You should avoid extending JFrame because that means that your class is a JFrame, JFrame is a rigid container, instead make your programs based on JPanels and add them to other Containers. For reference see: Using extends JFrame vs calling it inside of class.
You're over using the static keyword. static is not a cross method passing word, it will harm you a lot, stop using it. Instead create instances of your class and call your methods that way.
You have multiple objects that do the same:
Icon ic1 = new ImageIcon("images/1.png");
Icon ic2 = new ImageIcon("images/2.png");
...
Why not have an Icon[] icons and iterate over it?
You're using the evil null layout and setBounds(...), stop using it and instead make use of the layout managers along with EmptyBorders for extra spacing between components.
While pixel perfect positioning might be like the easiest way to Swing newbies to create complex GUIs, the more you use it, the more problems you'll find regarding this. Swing has to deal with different platforms, screen sizes, resolutions, PLAFs, etc. That's why pixel perfect GUIs are just an illusion. For reference see Null layout is evil and the answers in this question for a further explanation on why you should avoid null layout.
You're making your JFrame visible before you have added all your components, this could cause your GUI to not be painted fully before it's shown and could cause a "bug" that the components don't display until you hover where they should be. JFrame#setVisible(...) should be one of the last lines to be called.
You're calling JFrame#setSize(...), you should instead override the getPreferredSize of your inner JPanels and then call JFrame#pack(), so your JFrame reduces its size to the minimum size where all your components are visible on their preferred sizes. See Should I avoid the use of setPreferred|Maximum|MinimumSize in Java Swing? (The general consensus says "yes").
You're not placing your program on the Event Dispatch Thread (EDT), Swing is not Thread safe and this could make your program to freeze sometimes, you can solve this by changing your main(...) method like this one:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Your constructor here
}
});
}
Your images probably aren't located, but they'll become embedded resources once you package your program as a JAR file, and thus, it's wise to start treating the files (or images) as if they already were.
You can change for example:
Icon ic1 = new ImageIcon("images/1.png");
To this:
Icon ic1 = null;
try {
ic1 = new ImageIcon(ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/1.png")));
} catch (IOException e) {
e.printStackTrace();
}
That will make your image to be loaded. See this question and the accepted answer for reference.
That should solve your question, and your GUI (I did it with 2 icons) shoudl look like this one:
But if you want to follow my above recommendations you could try this code, which uses layout managers, empty borders, overrides getPreferredSize() methods and uses pack(), etc and generates a really similar GUI like the one you already have:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ImagesInResourcesExample {
private JFrame frame;
private JPanel buttonsPane;
private JPanel rightPane;
private JPanel scorePanel;
private JPanel colorPanel;
private BufferedImage img;
private JButton[][] buttons;
private JLabel moveLabel;
private JLabel timeLabel;
private JButton newGameButton;
private JButton exitButton;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ImagesInResourcesExample().createAndShowGui();
}
});
}
#SuppressWarnings("serial")
public void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
buttons = new JButton[3][3];
moveLabel = new JLabel("Move: 0");
timeLabel = new JLabel("Time: 0");
colorPanel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
};
colorPanel.setBackground(Color.BLUE);
colorPanel.setOpaque(true);
newGameButton = new JButton("New Game");
exitButton = new JButton("Exit");
try {
img = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/arrow.png"));
} catch (IOException e) {
e.printStackTrace();
}
buttonsPane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
};
buttonsPane.setLayout(new GridLayout(3, 3));
buttonsPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
for (int i = 0; i < buttons.length; i++) {
for (int j = 0; j < buttons.length; j++) {
buttons[i][j] = new JButton(new ImageIcon(img));
buttonsPane.add(buttons[i][j]);
}
}
rightPane = new JPanel();
rightPane.setLayout(new GridBagLayout());
scorePanel = new JPanel();
scorePanel.setLayout(new GridLayout(1, 2, 10, 10));
scorePanel.add(moveLabel);
scorePanel.add(timeLabel);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(10, 10, 10, 10);
rightPane.add(scorePanel, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
rightPane.add(colorPanel, gbc);
gbc.gridy = 2;
gbc.ipadx = 30;
gbc.ipady = 80;
rightPane.add(newGameButton, gbc);
gbc.gridy = 3;
rightPane.add(exitButton, gbc);
rightPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
frame.add(buttonsPane, BorderLayout.CENTER);
frame.add(rightPane, BorderLayout.EAST);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
As you can see, the code is at most 20 lines longer than the one you already have, but if you keep adding elements to both programs, the one I did will, in a future, be shorter than the one you'll end up by using null layout.
I hope you follow the above recommendations and take this example and try to understand it and improve it.

How do I use GridBagConstraints setRows and setColumns?

How do I use setRows and setColumns to change the amount of rows and columns in my window?
Here's a copy of my code and where I tried to implement the set rows and columns:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.*;
#SuppressWarnings("unused")
public class GUI
{
public static void main(String[] args)
{
new GUI();
}
public GUI()
{
JFrame AG = new JFrame("Adventure Game");
AG.setExtendedState(JFrame.MAXIMIZED_BOTH);
AG.setResizable(true);
AG.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p=new JPanel();
p.setLayout (new GridBagLayout());
AG.add(p);
GridBagConstraints GBC = new GridBagConstraints();
GridLayout.setRows(100);//heres the set rows<<<<<<<<<<<<<<<<<<<
GridLayout.setColumns(100);//heres the set columns<<<<<<<<<<<<<<<<<<<
AG.getContentPane().add(p, BorderLayout.NORTH);
JButton saveButton =new JButton("Save");
JButton loadButton =new JButton("Load");
JButton optionsButton = new JButton("Options");
JLabel textBox= new JLabel("Story line will go here.");
JLabel label11 = new JLabel("Test 1");
GBC.gridx = 0;
GBC.gridy = 1;
p.add(label11,GBC);
JLabel label12 = new JLabel("Test 2");
GBC.gridx = 0;
GBC.gridy = 2;
p.add(label12,GBC);
JLabel label13 = new JLabel("Test 3");
GBC.gridx = 0;
GBC.gridy = 3;
p.add(label13,GBC);
JLabel label14 = new JLabel("Test 4");
GBC.gridx = 0;
GBC.gridy = 5;
p.add(label14,GBC);
AG.setVisible(true);
}
}
GridBagConstraints work with the GridBagLayout, not the GridLayout. Your call to GridLayout doesn't do anything.
To set the rows and columns with GridBagConstraints, you need to use GBC.gridx = ...; and GBC.gridy = ...;
If you are trying to place gaps between your buttons, empty GridBag cells are not the way to do it; use the insets of your GridBagConstraints for that.
To make a component in a GridBagLayout disappear without the other components shifting around, place the button in a JPanel with a CardLayout, and make sure you add that JPanel to your GridBagLayout instead of the button:
private JButton optionalButton;
private void buildWindow() {
// ...
optionalButton = new JButton("Optional Action");
JPanel optionalButtonPanel = new JPanel(new CardLayout());
optionalButtonPanel.add(optionalButton, "BUTTON");
optionalButtonPanel.add(new JLabel(), "BLANK");
// ...
}
private void setOptionalButtonVisible(boolean visible) {
Container optionalButtonPanel = optionalButton.getParent();
CardLayout layout = (CardLayout) optionalButtonPanel.getLayout();
layout.show(optionalButtonPanel, visible ? "BUTTON" : "BLANK");
}
CardLayout always displays one and only one of its components, but it sizes its associated container to fit all the components, including the invisible ones.

JButton size and JScrollPane not working well together

I am thoroughly confused. I have a pretty decent understanding of how each layout manger works and what each one is used for, but I'm not understanding what combination of layout managers and JPanels are necessary to make what I need work.
What I am trying to accomplish
I have a top bar, and a bottom bar of a container panel NORTH and SOUTH of a BorderLayout.
Within the Center panel, I want an unknown number of buttons 1 or more. Regardless of how many buttons there are they all need to be the same size, if there are dozens then scrolling should start happening once the buttons pass the window size limit.
What I am getting
Depending on the combination of layout mangers and how many nested JPanels I use and all sorts of trouble shooting, I get one massive button filling the entire CENTER element. I get 2 buttons that are the right size, but spread way apart (gap filling the CENTER space), or I get a dozen buttons that are the right size with no scroll.
I can solve any one of these, but then the other breaks. IE if I get a bunch of correctly sized buttons that properly scroll, then when I replace them with a single button its one massive button. Or if I get a single properly sized button then the larger quantity won't scroll etc.
My Code
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.io.*;
public class TestCode extends JFrame {
private final JFrame frame;
public TestCode(){
frame = new JFrame();
JLabel title = new JLabel("Test Title");
JPanel windowContainer = new JPanel();
JPanel topPanel = new JPanel();
final JPanel middlePanel = new JPanel();
JPanel bottomPanel = new JPanel();
JButton searchButton = new JButton("Search");
JButton browseButton = new JButton("Browse...");
JButton testButton = new JButton("Button 1");
JButton exitButton = new JButton("Exit");
final JTextField searchBar = new JTextField("Search database...");
topPanel.setLayout(new GridLayout(2,0));
topPanel.add(title);
title.setHorizontalAlignment(JLabel.CENTER);
topPanel.setPreferredSize(new Dimension(getWidth(), 100));
// This is a subset of the top section. Top part is two panels, bottom panel is two cells (grid)
JPanel topPanelSearch = new JPanel();
topPanelSearch.setLayout(new GridLayout(0,2));
topPanelSearch.add(searchBar);
topPanelSearch.add(searchButton);
topPanel.add(topPanelSearch);
// PROBLEM AREA STARTS
// middlePanel.setLayout(new FlowLayout());
middlePanel.setLayout(new GridLayout(0, 1, 10, 10));
// middlePanel.setLayout(new BoxLayout(middlePanel, BoxLayout.PAGE_AXIS));
JPanel innerContainer = new JPanel();
innerContainer.setLayout(new BoxLayout(innerContainer, BoxLayout.PAGE_AXIS));
// innerContainer.setLayout(new FlowLayout());
// innerContainer.setLayout(new GridLayout(0, 1, 10, 10));
for(int i = 0; i < 2; i++){
JButton button = new JButton("Button ");
button.setPreferredSize(new Dimension(400, 100));
JPanel test = new JPanel();
test.add(button);
innerContainer.add(test);
}
JScrollPane midScroll = new JScrollPane(innerContainer);
middlePanel.add(midScroll);
// PROBLEM AREA ENDS
bottomPanel.setLayout(new GridLayout(0, 3));
bottomPanel.setPreferredSize(new Dimension(getWidth(), 100));
bottomPanel.add(testButton);
bottomPanel.add(browseButton);
bottomPanel.add(exitButton);
windowContainer.setLayout(new BorderLayout());
windowContainer.add(topPanel, BorderLayout.NORTH);
windowContainer.add(middlePanel, BorderLayout.CENTER);
windowContainer.add(bottomPanel, BorderLayout.SOUTH);
frame.add(windowContainer);
frame.setTitle("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(480, 800);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args){
TestCode test = new TestCode();
}
}
Visual of some of the fail results
I want the leftmost picture, but buttons should be stacked neatly (like the middle picture) when there are only a few results, and scrollable when there are lots.
What am I doing wrong?
Try with GridBagLayout and a filler component that takes the remaining vertical space and therefore forces the buttons upwards.
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.Box.Filler;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class GridbagButtons extends JFrame {
private final JScrollPane jscrpButtons;
private final JPanel jpButtons;
public GridbagButtons() {
setLayout(new BorderLayout());
jpButtons = new JPanel(new GridBagLayout());
jscrpButtons = new JScrollPane(jpButtons);
add(jscrpButtons, BorderLayout.CENTER);
// add a custom number of buttons
int numButtons = 10;
for (int i = 0; i < numButtons; i++) {
JButton jbButton = new JButton("Button");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = i;
jpButtons.add(jbButton, gbc);
}
// add a vertical filler as last component to "push" the buttons up
GridBagConstraints gbc = new GridBagConstraints();
Filler verticalFiller = new Filler(
new java.awt.Dimension(0, 0),
new java.awt.Dimension(0, 0),
new java.awt.Dimension(0, Integer.MAX_VALUE));
gbc.gridx = 0;
gbc.gridy = numButtons;
gbc.fill = java.awt.GridBagConstraints.VERTICAL;
gbc.weighty = 1.0;
jpButtons.add(verticalFiller, gbc);
setSize(300, 200);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GridbagButtons().setVisible(true);
}
});
}
}

Categories