Weird problem with GUI programming in Java - 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
}

Related

setUndecorated(true) content of the JFrame not displaying

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

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.

Why so much room to the left of my labels in java?

Here is what I have:
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 java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.LineBorder;
public class Main {
// Field members
static JPanel panel = new JPanel();
static Integer indexer = 1;
static List<JLabel> listOfLabels = new ArrayList<JLabel>();
static List<JTextField> listOfTextFields = new ArrayList<JTextField>();
static JScrollPane scrollPane;
public static void main(String[] args) {
// Construct frame
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
//frame.setPreferredSize(new Dimension(990, 990));
frame.setTitle("My Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Frame constraints
//GridBagConstraints frameConstraints = new GridBagConstraints();
// Construct button
JButton addButton = new JButton("Add");
addButton.addActionListener(new ButtonListener());
// Add button to frame
//frameConstraints.gridx = 0;
//frameConstraints.gridy = 0;
//frame.add(addButton, frameConstraints);
frame.add(addButton);
// Construct panel
panel.setPreferredSize(new Dimension(1000, 1000));
panel.setLayout(new GridBagLayout());
panel.setBorder(LineBorder.createBlackLineBorder());
scrollPane = new JScrollPane(panel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setPreferredSize(new Dimension(600, 600));
// Add panel to frame
//frameConstraints.gridx = 0;
//frameConstraints.gridy = 1;
//frameConstraints.weighty = 1;
//frame.add(panel, frameConstraints);
frame.add(scrollPane);
// Pack frame
frame.pack();
// Make frame visible
frame.setVisible(true);
}
static class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent arg0) {
// Clear panel
panel.removeAll();
// Create label and text field
//JTextField jTextField = new JTextField();
//jTextField.setSize(100, 200);
//listOfTextFields.add(jTextField);
listOfLabels.add(new JLabel("" + indexer));
// Create constraints
//GridBagConstraints textFieldConstraints = new GridBagConstraints();
GridBagConstraints labelConstraints = new GridBagConstraints();
// Add labels and text fields
for (int i = 0; i < indexer; i++) {
// Text field constraints
//textFieldConstraints.gridx = 1;
//textFieldConstraints.fill = GridBagConstraints.HORIZONTAL;
//textFieldConstraints.weightx = 0.5;
//textFieldConstraints.insets = new Insets(10, 10, 10, 10);
//textFieldConstraints.gridy = i;
// Label constraints
labelConstraints.gridx = 0;
labelConstraints.gridy = i;
labelConstraints.insets = new Insets(0, 0, 0, 0);
// Add them to panel
panel.add(listOfLabels.get(i), labelConstraints);
//panel.add(listOfTextFields.get(i), textFieldConstraints);
}
// Align components top-to-bottom
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = indexer;
c.weighty = 1;
c.ipady = 0;
panel.add(new JLabel(), c);
System.out.println("indexer is " + indexer);
// Increment indexer
indexer++;
panel.updateUI();
if(indexer ==2){
listOfLabels.set(0, new JLabel("Test"));
}
}
private int getWidth() {
// TODO Auto-generated method stub
return 0;
}
}
}
Here is the output:
What Am I doing wrong? I want the labels to be justified all the way to the left. I don't have any padding set to the left so I am confused.
FYI, I found this code on stackoverflow and my goal is to have labels that I can dynamically add and update, hence I commented out the textboxes.
Don't call setPreferredSize on the scroll pane, this isn't what you should setting, use GridBagConstraints weightx/y and fill properties.
Don't call updateUI, it doesn't do what you think it does, call revalidate instead, if you have to
The main reasons you're having problems is
You're call setPreferredSize on the panel. When adding components to a GridBagLayout, it will attempt to lay out components around the centre of the container
You've not specified a weightx or anchor property for the GridBagConstraints when adding the labels

java: dynamically generated textbox by clicking on button

I have cretaed textfields and labels on clicking 'add' button. I have given x and y coordinates, but textbox appearing is in improper manner.
how to correct it? and also how to increase width of textbox ???
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;
public class SS
{
// Field members
static JPanel panel = new JPanel();
static Integer indexer = 1;
static List<JLabel> listOfLabels = new ArrayList<JLabel>();
static List<JTextField> listOfTextFields = new ArrayList<JTextField>();
public static void main(String[] args)
{
// Construct frame
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
frame.setPreferredSize(new Dimension(800, 800));
frame.setTitle("My Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Frame constraints
GridBagConstraints frameConstraints = new GridBagConstraints();
// Construct button
JButton addButton = new JButton("Add");
addButton.addActionListener(new ButtonListener());
// Add button to frame
frameConstraints.gridx = 0;
frameConstraints.gridy = 0;
frame.add(addButton, frameConstraints);
// Construct panel
panel.setPreferredSize(new Dimension(400, 400));
panel.setLayout(new GridBagLayout());
panel.setBorder(LineBorder.createBlackLineBorder());
// Add panel to frame
frameConstraints.gridx = 0;
frameConstraints.gridy = 1;
frameConstraints.weighty = 20;
frame.add(panel, frameConstraints);
// Pack frame
frame.pack();
// Make frame visible
frame.setVisible(true);
}
static class ButtonListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent arg0)
{
// Clear panel
panel.removeAll();
// Create label and text field
listOfTextFields.add(new JTextField());
listOfLabels.add(new JLabel("Name " + indexer));
// Create constraints
GridBagConstraints textFieldConstraints = new GridBagConstraints();
GridBagConstraints labelConstraints = new GridBagConstraints();
// Add labels and text fields
for(int i = 0; i < indexer; i++)
{
// Text field constraints
textFieldConstraints.gridx = 20;
textFieldConstraints.gridy = i;
// Label constraints
labelConstraints.gridx = 1;
labelConstraints.gridy = i;
// Add them to panel
panel.add(listOfTextFields.get(i), textFieldConstraints);
panel.add(listOfLabels.get(i), labelConstraints);
}
// Align components top-to-bottom
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = indexer;
c.weighty = 1;
panel.add(new JLabel(), c);
// Increment indexer
indexer++;
}
}
}
To get the frame to refresh with the text box you need to call pack at the bottom of your actionPerformed method.
frame.pack();
For this you need to have frame as a class variable.
static JFrame frame;
For the size the grid bag layout will override your setSize so you can give it a weight and make it stretch to fill in the space. This can go just after your other textFieldContraints calls.
textFieldConstraints.weightx = 1;
textFieldConstraints.fill = GridBagConstraints.HORIZONTAL;
This should make the text boxes appear when you hit the button and take up the box.
Increase width of textfield.
listOfTextFields.add(new JTextField(null,10));

Categories