I'm developing a swing application. In that I've a JFrame which add JTextfield and JButton dynamically on the button click.and remove the created components if the user clicks the same button.
In the below screen image , when user clicks ADD button new row was added, and text was changed to REMOVE like in 2nd image.
New Row added and previous button text changed to REMOVE.
Now, if I click the REMOVE button, then the newly added row has to dispose and then button has to change the text again to ADD.
I've tried till adding the components, but I stuck up with removing the newly added row.
Anyone please guide me to achieve this.
Below is my code.
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ButtonAddDynamic implements ActionListener {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ButtonAddDynamic().createAndShowGUI();
}
});
}
private JFrame frame;
private JPanel panel = new JPanel(new GridBagLayout());
private GridBagConstraints constraints = new GridBagConstraints();
private List fields = new ArrayList();
private List fieldButton = new ArrayList();
private List fieldFile = new ArrayList();
private static int countReport = 0;
String files = null;
int y = 2;
protected void createAndShowGUI() {
try {
UIManager
.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
String[] labels = { "VALIDATION FORM" };
for (String label : labels)
addColumn(label);
frame = new JFrame("Add Button Dynamically");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(panel));
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
// Set the default button to button1, so that when return is hit, it
// will hit the button1
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
}
private void addColumn(String labelText) {
constraints.gridx = fields.size();
constraints.gridy = 1;
panel.add(new JLabel(labelText), constraints);
constraints.gridy = 2;
final JTextField field = new JTextField(40);
field.setEditable(false);
panel.add(field, constraints);
fields.add(field);
// constraints.gridy=3;
constraints.gridx = fields.size() + fieldButton.size();
final JButton button = new JButton("ADD");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (button.getText().equals("ADD")) {
button.setText("REMOVE");
addRowBelow();
frame.pack();
} else if (button.getText().equals("REMOVE")) {
button.setText("ADD");
frame.pack();
}
}
});
panel.add(button, constraints);
fieldButton.add(button);
panel.revalidate(); // redo layout for extra column
}
private void addRowBelow() {
y++;
constraints.gridy = y;
// System.out.println(fields.size());
for (int x = 0; x < fields.size(); x++) {
constraints.gridx = x;
final JTextField field = new JTextField(40);
field.setEditable(false);
panel.add(field, constraints);
constraints.gridx = x + 1;
final JButton button = new JButton("ADD");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (button.getText().equals("ADD")) {
button.setText("REMOVE");
addRowBelow();
frame.pack();
} else if (button.getText().equals("REMOVE")) {
button.setText("ADD");
frame.pack();
}
}
});
panel.add(button, constraints);
}
}
public void actionPerformed(ActionEvent ae) {
if ("Add Another TextField and Button".equals(ae.getActionCommand())) {
addRowBelow();
frame.pack();
frame.setLocationRelativeTo(null);
}
}
}
Trying to use GridBagLayout is making this very complicated for you. A nested layout scheme is much easier to work with when you are doing this type of thing.
See this MCVE:
I'm not sure I understood your intended functionality 100% correct but I don't think it's as important as the layouts.
My layout scheme is as follows:
This is nice because BoxLayout will handle the vertical listing without much hullabaloo. Instead of having to wrangle with GridBagConstraints, the text field and button are contained together by a panel.
import javax.swing.*;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Insets;
public class FieldList implements Runnable, ActionListener {
public static void main(String... args) {
SwingUtilities.invokeLater(new FieldList());
}
final int maxFields = 2;
JFrame frame;
JPanel listing;
#Override
public void run() {
frame = new JFrame("Text Field Listing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel content = new JPanel(new BorderLayout());
content.add(new JLabel("Input Form", JLabel.CENTER), BorderLayout.NORTH);
listing = new JPanel();
listing.setLayout(new BoxLayout(listing, BoxLayout.Y_AXIS));
content.add(listing, BorderLayout.CENTER);
frame.setContentPane(content);
addNewField();
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
void addNewField() {
FieldButtonPair field = new FieldButtonPair();
field.button.addActionListener(this);
listing.add(field);
frame.pack();
}
void removeLastField() {
listing.remove(listing.getComponentCount() - 1);
frame.pack();
}
#Override
public void actionPerformed(ActionEvent ae) {
AddRemoveButton source = (AddRemoveButton)ae.getSource();
if(source.state == AddRemoveButton.State.ADD) {
if(listing.getComponentCount() < maxFields) {
addNewField();
source.setState(AddRemoveButton.State.REMOVE);
}
} else if(source.state == AddRemoveButton.State.REMOVE) {
removeLastField();
source.setState(AddRemoveButton.State.ADD);
}
}
}
class FieldButtonPair extends JPanel {
JTextField field;
AddRemoveButton button;
FieldButtonPair() {
super(new BorderLayout());
field = new JTextField();
add(field, BorderLayout.CENTER);
button = new AddRemoveButton();
add(button, BorderLayout.EAST);
}
#Override
public Dimension getPreferredSize() {
Dimension pref = super.getPreferredSize();
pref.width = Math.max(480, pref.width);
return pref;
}
}
class AddRemoveButton extends JButton {
enum State { ADD, REMOVE }
State state = State.ADD;
AddRemoveButton() {
setText(state.name());
}
void setState(State state) {
setText(state.name());
this.state = state;
}
#Override
public Dimension getPreferredSize() {
Dimension pref = super.getPreferredSize();
Font f = getFont();
FontMetrics fm = getFontMetrics(f);
int w = fm.stringWidth(State.REMOVE.name());
Insets ins = getInsets();
pref.width = (ins.left + w + ins.right);
return pref;
}
}
Related
The idea is to have one "global" JFrame which I can then add/remove JPanels as needed to make a smooth flowing application. Currently, when I try changing from the first JPanel to the second, the second won't display. My code is below:
Handler (class to run the app):
package com.example.Startup;
import com.example.Global.Global_Frame;
public class Handler
{
public Handler()
{
gf = new Global_Frame();
gf.getAccNum();
gf.setVisible(true);
}
public static void main(String[] args)
{
new Handler();
}
Global_Frame gf = null;
}
public static void main(String[] args)
{
new Handler();
}
Global_Vars gv = null;
Global_Frame gf = null;
}
Global Frame:
package com.example.Global;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import com.example.FirstRun.AccDetails;
import com.example.FirstRun.FirstTimeRun;
public class Global_Frame extends JFrame
{
private static final long serialVersionUID = 1L;
ActionListener val = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
getUserDetails();
}
};
public Global_Frame()
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); // get look and feel based on OS
}
catch (ClassNotFoundException ex) // catch all errors that may occur
{
Logger.getLogger(Global_Frame.class.getName()).log(Level.SEVERE, null, ex);
}
catch (InstantiationException ex)
{
Logger.getLogger(Global_Frame.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IllegalAccessException ex)
{
Logger.getLogger(Global_Frame.class.getName()).log(Level.SEVERE, null, ex);
}
catch (UnsupportedLookAndFeelException ex)
{
Logger.getLogger(Global_Frame.class.getName()).log(Level.SEVERE, null, ex);
}
EventQueue.invokeLater(new Runnable()
{
public void run() //run the class's constructor, therefore starting the UI being built
{
initComponents();
}
});
}
public void initComponents()
{
setPreferredSize(new Dimension(600, 400)); // setting measurements of jframe
revalidate(); // revalidate the elements that will be displayed
repaint(); // repainting what is displayed if going coming from a different form
pack(); // packaging everything up to use
setLocationRelativeTo(null); // setting form position central
}
public void getAccNum()
{
setPreferredSize(new Dimension(600, 400)); // setting measurements of jframe
FirstTimeRun panel1 = new FirstTimeRun(val);
add(panel1);
revalidate();
repaint();
pack();
}
public void getUserDetails()
{
getContentPane().removeAll();
resizing(750, 500);
AccDetails panel2 = new AccDetails();
add(panel2);
revalidate();
repaint();
pack();
}
private void resizing(int width, int height)
{
timer = new Timer (10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0)
{
getContentPane().removeAll();
setPreferredSize(new Dimension(sizeW, sizeH));
revalidate();
repaint();
pack();
if (!wToggle)
sizeW += 2;
if (!hToggle)
sizeH += 2;
if (toggle)
{
setLocationRelativeTo(null);
toggle = false;
}
else
toggle = true;
if (sizeW == width)
wToggle = true;
if (sizeH == height)
hToggle = true;
if (hToggle && wToggle)
timer.stop();
}
});
timer.start();
}
//variables used for window resizing
private Timer timer;
private int sizeW = 600;
private int sizeH = 400;
private boolean toggle = false;
private boolean wToggle = false;
private boolean hToggle = false;
public int accNum = 0;
}
First Panel:
package com.example.FirstRun;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
public class FirstTimeRun extends JPanel
{
private static final long serialVersionUID = 1L;
public FirstTimeRun()
{
}
public FirstTimeRun(ActionListener val)
{
initComponents(val);
}
private void initComponents(ActionListener val) // method to build initial view for user for installation
{
pnlStart = new JPanel[1];
btnNext = new JButton();
pnlStart[0] = new JPanel();
btnNext.setText("Next"); // adding text to button for starting
btnNext.setPreferredSize(new Dimension(80, 35)); //positioning start button
btnNext.addActionListener(val);
pnlStart[0].add(btnNext); // adding button to JFrame
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(pnlStart[0]);
}
// objects used in UI
private JPanel[] pnlStart;
private JButton btnNext;
}
Second Panel:
package com.example.FirstRun;
import java.awt.BorderLayout;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class AccDetails extends JPanel
{
private static final long serialVersionUID = 1L;
public AccDetails()
{
accAssets();
}
private void accAssets()
{
// instantiating elements of the GUI
pnlAccDetails = new JPanel[2];
lblWelcome = new JLabel();
lblMain = new JLabel();
for (int i = 0; i < 2; i++)
pnlAccDetails[i] = new JPanel();
lblWelcome.setText("Welcome to Example_App"); // label welcoming user
pnlAccDetails[0].setLayout(new BoxLayout(pnlAccDetails[0], BoxLayout.LINE_AXIS));
pnlAccDetails[0].add(lblWelcome); // adding label to form
lblMain.setText("<html>The following information that is collected will be used as part of the Example_App process to ensure that each user has unique Example_App paths. Please fill in all areas of the following tabs:</html>"); // main label that explains what happens, html used for formatting
pnlAccDetails[1].setLayout(new BorderLayout());
pnlAccDetails[1].add(Box.createHorizontalStrut(20), BorderLayout.LINE_START);
pnlAccDetails[1].add(lblMain, BorderLayout.CENTER); //adding label to JFrame
pnlAccDetails[1].add(Box.createHorizontalStrut(20), BorderLayout.LINE_END);
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(pnlAccDetails[0]);
add(pnlAccDetails[1]);
}
private JLabel lblWelcome;
private JLabel lblMain;
private JPanel[] pnlAccDetails;
}
I have tried using both a CardLayout and the "revalidate();" "repaint();" and "pack();" options and I'm stumped as to why it's not showing. Thanks in advance for any help that can be offered.
EDIT:
While cutting down my code, if the "resizing" method is removed, the objects are shown when the panels change. I would like to avoid having to remove this completely as it's a smooth transition for changing the JFrame size.
#John smith it is basic example of switch from one panel to other panel I hope this will help you to sort out your problem
Code:
package stack;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class RemoveAndAddPanel implements ActionListener{
JFrame frame;
JPanel firstPanel;
JPanel secondPanel;
JPanel controlPanel;
JButton nextButton;
public RemoveAndAddPanel() {
JFrame.setDefaultLookAndFeelDecorated(true);
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
firstPanel = new JPanel();
firstPanel.add(new JLabel("FirstPanel"));
firstPanel.setPreferredSize(new Dimension(100,100));
secondPanel = new JPanel();
secondPanel.add(new JLabel("Second panel"));
secondPanel.setPreferredSize(new Dimension(100,100));
nextButton = new JButton("Next panel");
controlPanel = new JPanel();
nextButton.addActionListener(this);
controlPanel.add(nextButton);
frame.setLayout(new BorderLayout());
frame.add(firstPanel,BorderLayout.CENTER);
frame.add(controlPanel, BorderLayout.SOUTH);
frame.setVisible(true);
frame.setSize(300,100);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == nextButton) {
frame.remove(firstPanel);
frame.add(secondPanel);
nextButton.setEnabled(false);
}
frame.validate();
}
public static void main(String args[]) {
new RemoveAndAddPanel();
}
}
As mentioned in the edit, the problem lay within the resizing method. When the timer stopped, it wouldn't go anywhere, causing the UI to not load. The fix to the code is clearing the screen and adding the call to resizing to the actionlistener. Then adding a call to the next method after:
timer.stop();
Thanks for getting me to remove the mess around it and find the source of the problem #matt & #Hovercraft Full of Eels upvotes for both of you.
The main thing to consider while changing panel in a jframe is the layout, for a body(main) panel to change to any other panel the parent panel must be of type CardLayout body.setLayout(new java.awt.CardLayout());
After that you can now easily switch between panels wiht the sample code below
private void updateViewLayout(final HomeUI UI, final JPanel paneeelee){
final JPanel body = UI.getBody(); //this is the JFrame body panel and must be of type cardLayout
System.out.println("Page Loader Changing View");
new SwingWorker<Object, Object>() {
#Override
protected Object doInBackground() throws Exception {
body.removeAll();//remove all visible panel before
body.add(paneeelee);
body.revalidate();
body.repaint();
return null;
}
#Override
protected void done() {
UI.getLoader().setVisible(false);
}
}.execute();
}
The idea is to have one "global" JFrame which I can then add/remove JPanels as needed to make a smooth flowing application. Currently, when I try changing from the first JPanel to the second, the second won't display. My code is below:
Handler (class to run the app):
package com.example.Startup;
import com.example.Global.Global_Frame;
public class Handler
{
public Handler()
{
gf = new Global_Frame();
gf.getAccNum();
gf.setVisible(true);
}
public static void main(String[] args)
{
new Handler();
}
Global_Frame gf = null;
}
public static void main(String[] args)
{
new Handler();
}
Global_Vars gv = null;
Global_Frame gf = null;
}
Global Frame:
package com.example.Global;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import com.example.FirstRun.AccDetails;
import com.example.FirstRun.FirstTimeRun;
public class Global_Frame extends JFrame
{
private static final long serialVersionUID = 1L;
ActionListener val = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
getUserDetails();
}
};
public Global_Frame()
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); // get look and feel based on OS
}
catch (ClassNotFoundException ex) // catch all errors that may occur
{
Logger.getLogger(Global_Frame.class.getName()).log(Level.SEVERE, null, ex);
}
catch (InstantiationException ex)
{
Logger.getLogger(Global_Frame.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IllegalAccessException ex)
{
Logger.getLogger(Global_Frame.class.getName()).log(Level.SEVERE, null, ex);
}
catch (UnsupportedLookAndFeelException ex)
{
Logger.getLogger(Global_Frame.class.getName()).log(Level.SEVERE, null, ex);
}
EventQueue.invokeLater(new Runnable()
{
public void run() //run the class's constructor, therefore starting the UI being built
{
initComponents();
}
});
}
public void initComponents()
{
setPreferredSize(new Dimension(600, 400)); // setting measurements of jframe
revalidate(); // revalidate the elements that will be displayed
repaint(); // repainting what is displayed if going coming from a different form
pack(); // packaging everything up to use
setLocationRelativeTo(null); // setting form position central
}
public void getAccNum()
{
setPreferredSize(new Dimension(600, 400)); // setting measurements of jframe
FirstTimeRun panel1 = new FirstTimeRun(val);
add(panel1);
revalidate();
repaint();
pack();
}
public void getUserDetails()
{
getContentPane().removeAll();
resizing(750, 500);
AccDetails panel2 = new AccDetails();
add(panel2);
revalidate();
repaint();
pack();
}
private void resizing(int width, int height)
{
timer = new Timer (10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0)
{
getContentPane().removeAll();
setPreferredSize(new Dimension(sizeW, sizeH));
revalidate();
repaint();
pack();
if (!wToggle)
sizeW += 2;
if (!hToggle)
sizeH += 2;
if (toggle)
{
setLocationRelativeTo(null);
toggle = false;
}
else
toggle = true;
if (sizeW == width)
wToggle = true;
if (sizeH == height)
hToggle = true;
if (hToggle && wToggle)
timer.stop();
}
});
timer.start();
}
//variables used for window resizing
private Timer timer;
private int sizeW = 600;
private int sizeH = 400;
private boolean toggle = false;
private boolean wToggle = false;
private boolean hToggle = false;
public int accNum = 0;
}
First Panel:
package com.example.FirstRun;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
public class FirstTimeRun extends JPanel
{
private static final long serialVersionUID = 1L;
public FirstTimeRun()
{
}
public FirstTimeRun(ActionListener val)
{
initComponents(val);
}
private void initComponents(ActionListener val) // method to build initial view for user for installation
{
pnlStart = new JPanel[1];
btnNext = new JButton();
pnlStart[0] = new JPanel();
btnNext.setText("Next"); // adding text to button for starting
btnNext.setPreferredSize(new Dimension(80, 35)); //positioning start button
btnNext.addActionListener(val);
pnlStart[0].add(btnNext); // adding button to JFrame
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(pnlStart[0]);
}
// objects used in UI
private JPanel[] pnlStart;
private JButton btnNext;
}
Second Panel:
package com.example.FirstRun;
import java.awt.BorderLayout;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class AccDetails extends JPanel
{
private static final long serialVersionUID = 1L;
public AccDetails()
{
accAssets();
}
private void accAssets()
{
// instantiating elements of the GUI
pnlAccDetails = new JPanel[2];
lblWelcome = new JLabel();
lblMain = new JLabel();
for (int i = 0; i < 2; i++)
pnlAccDetails[i] = new JPanel();
lblWelcome.setText("Welcome to Example_App"); // label welcoming user
pnlAccDetails[0].setLayout(new BoxLayout(pnlAccDetails[0], BoxLayout.LINE_AXIS));
pnlAccDetails[0].add(lblWelcome); // adding label to form
lblMain.setText("<html>The following information that is collected will be used as part of the Example_App process to ensure that each user has unique Example_App paths. Please fill in all areas of the following tabs:</html>"); // main label that explains what happens, html used for formatting
pnlAccDetails[1].setLayout(new BorderLayout());
pnlAccDetails[1].add(Box.createHorizontalStrut(20), BorderLayout.LINE_START);
pnlAccDetails[1].add(lblMain, BorderLayout.CENTER); //adding label to JFrame
pnlAccDetails[1].add(Box.createHorizontalStrut(20), BorderLayout.LINE_END);
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(pnlAccDetails[0]);
add(pnlAccDetails[1]);
}
private JLabel lblWelcome;
private JLabel lblMain;
private JPanel[] pnlAccDetails;
}
I have tried using both a CardLayout and the "revalidate();" "repaint();" and "pack();" options and I'm stumped as to why it's not showing. Thanks in advance for any help that can be offered.
EDIT:
While cutting down my code, if the "resizing" method is removed, the objects are shown when the panels change. I would like to avoid having to remove this completely as it's a smooth transition for changing the JFrame size.
#John smith it is basic example of switch from one panel to other panel I hope this will help you to sort out your problem
Code:
package stack;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class RemoveAndAddPanel implements ActionListener{
JFrame frame;
JPanel firstPanel;
JPanel secondPanel;
JPanel controlPanel;
JButton nextButton;
public RemoveAndAddPanel() {
JFrame.setDefaultLookAndFeelDecorated(true);
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
firstPanel = new JPanel();
firstPanel.add(new JLabel("FirstPanel"));
firstPanel.setPreferredSize(new Dimension(100,100));
secondPanel = new JPanel();
secondPanel.add(new JLabel("Second panel"));
secondPanel.setPreferredSize(new Dimension(100,100));
nextButton = new JButton("Next panel");
controlPanel = new JPanel();
nextButton.addActionListener(this);
controlPanel.add(nextButton);
frame.setLayout(new BorderLayout());
frame.add(firstPanel,BorderLayout.CENTER);
frame.add(controlPanel, BorderLayout.SOUTH);
frame.setVisible(true);
frame.setSize(300,100);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == nextButton) {
frame.remove(firstPanel);
frame.add(secondPanel);
nextButton.setEnabled(false);
}
frame.validate();
}
public static void main(String args[]) {
new RemoveAndAddPanel();
}
}
As mentioned in the edit, the problem lay within the resizing method. When the timer stopped, it wouldn't go anywhere, causing the UI to not load. The fix to the code is clearing the screen and adding the call to resizing to the actionlistener. Then adding a call to the next method after:
timer.stop();
Thanks for getting me to remove the mess around it and find the source of the problem #matt & #Hovercraft Full of Eels upvotes for both of you.
The main thing to consider while changing panel in a jframe is the layout, for a body(main) panel to change to any other panel the parent panel must be of type CardLayout body.setLayout(new java.awt.CardLayout());
After that you can now easily switch between panels wiht the sample code below
private void updateViewLayout(final HomeUI UI, final JPanel paneeelee){
final JPanel body = UI.getBody(); //this is the JFrame body panel and must be of type cardLayout
System.out.println("Page Loader Changing View");
new SwingWorker<Object, Object>() {
#Override
protected Object doInBackground() throws Exception {
body.removeAll();//remove all visible panel before
body.add(paneeelee);
body.revalidate();
body.repaint();
return null;
}
#Override
protected void done() {
UI.getLoader().setVisible(false);
}
}.execute();
}
I'm writing a GUI in java. I have a JXTable in which I currently only have static data, but I want allow the user to input data by using a template panel that I have created.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableModel;
public class Template_StackOverflowExample extends JPanel{
private JPanel diagPanel = new dialogTemplate();
Object[] columnIdentifiers = {
"id",
"imei",
};
Object[][] data = {
{"1", "123"},
{"2", "123"},
{"3", "123"}
};
private JDialog dialog;
private static DefaultTableModel model;
public Template_StackOverflowExample(){
setLayout(new BorderLayout());
JPanel pane = new JPanel(new BorderLayout());
JButton addRow = new JButton("Add Row");
addRow.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
openRowPane("Add Row");
}
});
JButton editRow = new JButton("Edit Row");
editRow.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
openRowPane("Edit Row");
}
});
JPanel buttonPane = new JPanel(new GridLayout(0, 1));
TitledBorder buttonBorder = new TitledBorder("Buttons");
buttonPane.setBorder(buttonBorder);
buttonPane.add(addRow);
buttonPane.add(editRow);
model = new DefaultTableModel();
model.setColumnIdentifiers(columnIdentifiers);
JTable table = new JTable(model);
for(int i = 0; i < data.length; i++){
model.insertRow(i, data[i]);
}
JScrollPane scrollPane = new JScrollPane(table);
pane.add(buttonPane, BorderLayout.LINE_END);
pane.add(scrollPane, BorderLayout.CENTER);
add(pane, BorderLayout.CENTER);
}
public void openRowPane(String name){
if(dialog == null){
Window win = SwingUtilities.getWindowAncestor(this);
if(win != null){
dialog = new JDialog(win, name, ModalityType.APPLICATION_MODAL);
dialog.getContentPane().add(diagPanel);
dialog.pack();
dialog.setLocationRelativeTo(null);
}
}
dialog.setVisible(true);
}
public static void createAndShowGUI(){
JFrame frame = new JFrame("MCVE");
Template_StackOverflowExample mainPanel = new Template_StackOverflowExample();
frame.add(mainPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}
class dialogTemplate extends JPanel{
private JComponent[] content;
private String[] labelHeaders = {
"ID:",
"IMEI:",
};
public dialogTemplate(){
JPanel diagTemplate = new JPanel();
diagTemplate.setLayout(new BorderLayout());
JPanel rowContent = new JPanel(new GridLayout(0, 2));
JLabel idLabel = null;
JLabel imeiLabel = null;
JLabel[] labels = {
idLabel,
imeiLabel,
};
JTextField idTextField = new JTextField(20);
JTextField imeiTextField = new JTextField(20);
content = new JComponent[] {
idTextField,
imeiTextField,
};
for(int i = 0; i < labels.length; i++){
labels[i] = new JLabel(labelHeaders[i]);
rowContent.add(labels[i]);
rowContent.add(content[i]);
labels[i].setLabelFor(content[i]);
}
JButton save = new JButton("Save");
save.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
closeWindow();
}
});
JButton cancel = new JButton("Cancel");
cancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
closeWindow();
}
});
JPanel buttonPane = new JPanel(new GridLayout(0, 1, 5, 5));
buttonPane.add(save);
buttonPane.add(cancel);
buttonPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
diagTemplate.add(buttonPane, BorderLayout.PAGE_END);
diagTemplate.add(rowContent, BorderLayout.CENTER);
add(diagTemplate);
}
public void closeWindow(){
Window win = SwingUtilities.getWindowAncestor(this);
if(win != null) {
win.dispose();
}
}
}
As you might see both of the buttons in the pane creates the dialog that is created first ("Add Row" or "Edit Row"). I want them to create different dialogs so that the editing of data doesn't conflict with the addition of data.
Thanks in advance.
Assign a different dialog-creating method to each button so you can open two dialogs:
public void openRowPane(String name){
if(dialog == null){
Window win = SwingUtilities.getWindowAncestor(this);
//change modality
dialog = new JDialog(win, name, ModalityType.MODELESS);
dialog.getContentPane().add(diagPanel);
dialog.pack();
dialog.setLocationRelativeTo(null);
}
dialog.setVisible(true);
}
public void openRowPane2(String name){
if(dialog2 == null){
Window win = SwingUtilities.getWindowAncestor(this);
//change modality
dialog2 = new JDialog(win, name, ModalityType.MODELESS);
dialog2.getContentPane().add(diagPanel2);
dialog2.pack();
dialog2.setLocationRelativeTo(null);
}
dialog2.setVisible(true);
}
The next function of my cardlayout is working properly, but previous isnt. As far as I'm concerned, just having "layout.previous(_);" in the actionPerformed method body in my makePanel() method should work, but when I run my program and click the prev button, nothing happens. What am I doing wrong? –
import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.awt.event.*;
public class Temp
{
public static void main (String[] args)
{
new MakeAQuiz();
}
static class MakeAQuiz
{
private JPanel start, base, fields, buttonz, question;
private String [] labels = {"Enter your question: ", "Answer 1: ", "Answer 2: ", "Answer 3: ", "Answer 4: "};
private JButton [] buttons = {new JButton("<<Go back"), new JButton("I'm done"), new JButton("Next>>")};
private JFrame makeFrame;
public MakeAQuiz()
{
start = new JPanel(new CardLayout());
start.add(makePanel(),"1");
makeFrame = new JFrame();
makeFrame.setSize(500,600);
makeFrame.add(start);
makeFrame.setVisible(true);
makeFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public JFrame getJFrame()
{
return makeFrame;
}
public JPanel makePanel()
{
question = new JPanel(new FlowLayout());
fields = new JPanel(new GridBagLayout());
buttonz = new JPanel(new FlowLayout());
base = new JPanel(new BorderLayout());
GridBagConstraints c = new GridBagConstraints();
c.weighty=0.5; //adds padding between the fields vertically
for (int i = 1; i<5; i++)
{
c.gridy++; //puts each field in a seperate line/row
JLabel label = new JLabel(labels[i]);
// c.fill = GridBagConstraints.HORIZONTAL;
fields.add(label,c);
JTextField textField = new JTextField(20);
fields.add(textField,c);
}
final CardLayout layout = (CardLayout)start.getLayout();
buttons[1].addActionListener(new ActionListener() {
// #Override
public void actionPerformed(ActionEvent e) {
buttons[0].setEnabled(false);
buttons[2].setEnabled(false);
// for(Component comp : cardPanel.getComponents()) {
// if(comp instanceof Page) {
// Page page = (Page)comp;
// page.printData();
// }
// }
}
});
buttons[2].addActionListener(new ActionListener()
{
// #Override
public void actionPerformed(ActionEvent e)
{
start.add(makePanel(), String.valueOf(start.getComponentCount() + 1));
layout.next(start);
}
});
buttons[0].addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
layout.previous(start);
}
});
buttonz.add(buttons[0]);
buttonz.add(buttons[1]);
buttonz.add(buttons[2]);
JLabel l = new JLabel(labels[0]);
JTextField t = new JTextField(30);
question.add(l);
question.add(t);
base.add(question,BorderLayout.NORTH);
base.add(buttonz,BorderLayout.SOUTH);
base.add(fields,BorderLayout.CENTER);
return base;
}
}
}
I have no issue (with your code), once I added some additional components to the start panel.
You will, however, have issues because you've added the buttons to the panel been displayed in the CardLayout.
A better solution would be to put the buttons at the bottom of the main screen and separate it from the cards.
You would need to maintain some kind of counter or reference to the current page, as CardLayout doesn't provide any way to obtain a reference to the current card. This would allow you to enabled/disable the next/previous buttons approritaly...
Updated with runnable example...
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MakeAQuiz {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
new MakeAQuiz();
}
});
}
private JPanel start, base, fields, buttonz, question;
private String[] labels = {"Enter your question: ", "Answer 1: ", "Answer 2: ", "Answer 3: ", "Answer 4: "};
private JButton[] buttons = {new JButton("<<Go back"), new JButton("I'm done"), new JButton("Next>>")};
private JFrame makeFrame;
public MakeAQuiz() {
start = new JPanel(new CardLayout());
start.add(makePanel(), "1");
makeFrame = new JFrame();
makeFrame.add(start);
buttonz = new JPanel(new FlowLayout());
final CardLayout layout = (CardLayout) start.getLayout();
buttons[1].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
buttons[0].setEnabled(false);
buttons[2].setEnabled(false);
}
});
buttons[2].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int count = start.getComponentCount();
start.add(new JLabel(Integer.toString(count), JLabel.CENTER), Integer.toString(count));
layout.next(start);
}
});
buttons[0].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
layout.previous(start);
}
});
buttonz.add(buttons[0]);
buttonz.add(buttons[1]);
buttonz.add(buttons[2]);
makeFrame.add(buttonz, BorderLayout.SOUTH);
makeFrame.pack();
makeFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
makeFrame.setVisible(true);
}
public JFrame getJFrame() {
return makeFrame;
}
public JPanel makePanel() {
question = new JPanel(new FlowLayout());
fields = new JPanel(new GridBagLayout());
base = new JPanel(new BorderLayout());
GridBagConstraints c = new GridBagConstraints();
c.weighty = 0.5; //adds padding between the fields vertically
for (int i = 1; i < 5; i++) {
c.gridy++; //puts each field in a seperate line/row
JLabel label = new JLabel(labels[i]);
// c.fill = GridBagConstraints.HORIZONTAL;
fields.add(label, c);
JTextField textField = new JTextField(20);
fields.add(textField, c);
}
JLabel l = new JLabel(labels[0]);
JTextField t = new JTextField(30);
question.add(l);
question.add(t);
base.add(question, BorderLayout.NORTH);
base.add(fields, BorderLayout.CENTER);
return base;
}
}
No. I think its not gonna work that way. Simply clicking the previous button will not bring anything back. You should save your entries somewhere else and load them to corresponding fields when clicking on the previous button.
I tried to use a JSlider to set text in three JTextFields.
My condition is the slider should work for textfield_1, only when a textfield_1 get its focus, similarly for the other two textfields.
When I tried to use the same slider with other textfield, only the first text field values getting changed.
Expecting valuable suggestions Thanks in Advance.
JSlider slider;
JTextField tf;
tf.addFocusListener(new FoucusListener(){
public void foucusGained(FocusEvent fe){
slider.addChangeListener(new ChangeListener()){
public void stateChanged(ChangeEvent ce){
JSlider slider =(JSlider)ce.getSource();
if(slider.getValueisAdjusting())
tf.setText(String.valueOf(slider.getValue()))
}
});
});
The basic idea is you need to know what field was last selected. The problem is, when you select the slider, it will fire a focus gained event...
The simplest idea would be to use a FocusListener registered only to the text fields and maintain a reference to the last field selected.
When the slider changes, you would simply interact with the last selected field (if it's not null)
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class SliderControl {
public static void main(String[] args) {
new SliderControl();
}
public SliderControl() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JSlider slider;
private JTextField[] fields;
private JTextField selectedField;
public TestPane() {
setLayout(new GridBagLayout());
fields = new JTextField[3];
FocusHandler focusHandler = new FocusHandler();
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
for (int index = 0; index < 3; index++) {
fields[index] = new JTextField(3);
fields[index].addFocusListener(focusHandler);
add(fields[index], gbc);
gbc.gridy++;
}
gbc.fill = GridBagConstraints.HORIZONTAL;
slider = new JSlider();
slider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if (selectedField != null) {
selectedField.setText(String.valueOf(slider.getValue()));
}
}
});
add(slider, gbc);
}
protected class FocusHandler extends FocusAdapter {
#Override
public void focusGained(FocusEvent e) {
if (e.getComponent() instanceof JTextField) {
selectedField = (JTextField) e.getComponent();
}
}
}
}
}