java - How would I dynamically add swing component to gui on click?
Sample code to add Buttons on the fly dynamically.
panel.add(new JButton("Button"));
validate();
Full code:
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.FlowLayout;
import java.awt.BorderLayout;
public class AddComponentOnJFrameAtRuntime extends JFrame implements ActionListener {
JPanel panel;
public AddComponentOnJFrameAtRuntime() {
super("Add component on JFrame at runtime");
setLayout(new BorderLayout());
this.panel = new JPanel();
this.panel.setLayout(new FlowLayout());
add(panel, BorderLayout.CENTER);
JButton button = new JButton("CLICK HERE");
add(button, BorderLayout.SOUTH);
button.addActionListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 500);
setVisible(true);
}
public void actionPerformed(ActionEvent evt) {
this.panel.add(new JButton("Button"));
this.panel.revalidate();
validate();
}
public static void main(String[] args) {
AddComponentOnJFrameAtRuntime acojfar = new AddComponentOnJFrameAtRuntime();
}
}
- Resource
Dynamically add swing component to gui on click?
there are several ways to reach dynamicaly added components to swing tree:
1st approach:
panel.getComponent(n);
returns n'th component in the panel (Container). (n is the order, that component added to its parent (parent is panel
here) ) (you need to know component's index) this way you can use ((JComboBox)panel.getComponent(3)).getSelectedIndex()
2nd approach
directly add some listeners when dynamically adding your components;
JButton b1 = new JButton("add");
b1.addActionListener(e -> {
JComboBox<String> color = new JComboBox<String>();
color.addActionListener(x -> { myFormBean.setColor(color.getSelectedItem();) });
panel.add(color);
JTextField name = new JTextField();
name.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
myFormBean.setName(name.getText());
}
@Override
public void insertUpdate(DocumentEvent e) {
myFormBean.setName(name.getText());
}
@Override
public void changedUpdate(DocumentEvent e) {
myFormBean.setName(name.getText());
}
});
panel.add(name);
panel.revalidate();
panel.repaint();
});
this way you do not need to reach your dynamically added components.
3rd approach may be using a framework for data binding,
4rd approach ...
how to dynamically add swing components to gui on click and make it permanent
This has little to do with Swing per se and all to do with persistence: What you are trying to do is set the state of an object (or group of objects) and have it persist when the program exits. There are several ways to do this including serialization, XML serialization (which I favor) using XML beans or JAXB, or properties. I suggest checking out JAXB and persisting your class's state with this by marshalling and unmarshalling the state to XML. Otherwise if you have a lot of information that must persist, then consider using a database.
dynamically add JLabel to UI in java on button click using a single object
Calling revalidate and repaint on the container after adding your JLabel will tell the GUI to position the new component and to repaint the container so that it shows. e.g.,
public void actionPerformed(ActionEvent ae) {
if (!text.getText().equals(defaultMessage)) {
if (!text.getText().isEmpty()) {
label = new JLabel(text.getText());
label.setBounds(10, y, 380, 20);
y = y - 20;
frame.add(label);
frame.revalidate();
frame.repaint();
}
}
}
In your case, the revalidate isn't absolutely necessary since you're not using a layout manager, but still it's a good idea to include it, since you should be using layout managers as null layouts are dangerous and fragile.
Better though to use a JList.
e.g.,
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class ChatClient2 extends JPanel {
private static final int VISIBLE_ROW_COUNT = 30;
private DefaultListModel<String> listModel = new DefaultListModel<>();
private JList<String> chatList = new JList<>(listModel);
private SendAction sendAction = new SendAction("Send");
private JTextField textField = new JTextField(20);
private JButton sendButton = new JButton(sendAction);
public ChatClient2() {
chatList.setFocusable(false);
chatList.setVisibleRowCount(VISIBLE_ROW_COUNT);
JScrollPane scrollPane = new JScrollPane(chatList);
textField.setAction(sendAction);
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.LINE_AXIS));
bottomPanel.add(textField);
bottomPanel.add(sendButton);
setLayout(new BorderLayout());
add(scrollPane);
add(bottomPanel, BorderLayout.PAGE_END);
}
private class SendAction extends AbstractAction {
public SendAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
String text = textField.getText();
listModel.add(0, text);
textField.selectAll();
textField.requestFocusInWindow();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Chat Client2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ChatClient2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Java dynamically create buttons and pass a parameter to action performed
One of the issues you're having is creating a monolithic action listener, and then expecting to delegate actions from that. One nice feature of java are anonymous classes, or since java 7 lambdas.
JButton button = new JButton("Click " + i);
panel.add(button);
int id = i;
button.addActionListener( evt->{
performActionOnId( id );
});
Now instead of having the main class be an action listener, the main class has methods that are descriptive.
public void addUser( User a ){
//just showing delete button.
JButton delete = new JButton("X");
delete.addActionListener( evt ->{
removeUser( a );
//clean up gui.
});
}
This puts some of the steps of delegation at the creation of the user. Otherwise you'll have to delegate in your action performed.
public void actionPerformed( ActionEvent evt ){
//has to be a new class to have id attribute.
CustomButton b = (CustomButton)evt.getSource();
int id = b.getId();
User u = getUserById(id);
removeUser(u);
}
Dynamically adding components to JPanel
Call validate()
on the parent container, as shown in the Nested Layout Example. Those labels on the lower left are added dynamically. Note that calling pack()
might cause the size of the GUI to change, whereas calling validate()
won't. If you need to get the GUI to resize - call pack()
, else call validate()
.
Java dynamically add a button to a panel
Here's a SSCCE that does what you desire.
It uses BoxLayout to ensure that the buttons are displayed in a single row.
It sets each button to the same, particular size.
There is the same size gap between each, adjacent button.
It uses a JScrollPane so that once you add more buttons that can fit into the width of the JScrollPane
, you can scroll to see the other buttons. This is instead of increasing the size of the JPanel
(or creating a new row) each time you add a button.
More explanations after the code.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.WindowConstants;
public class AdButton implements ActionListener, Runnable {
private static final String ADD = "Add";
private static final String EXIT = "Exit";
private int counter;
private JFrame frame;
private JPanel panel;
@Override // java.awt.event.ActionListener
public void actionPerformed(ActionEvent event) {
String actionCommand = event.getActionCommand();
switch (actionCommand) {
case ADD:
addButton();
break;
case EXIT:
System.exit(0);
default:
JOptionPane.showMessageDialog(frame,
actionCommand,
"Unhandled",
JOptionPane.WARNING_MESSAGE);
}
}
@Override // java.lang.Runnable
public void run() {
createGui();
}
private void addButton() {
panel.add(Box.createHorizontalStrut(10));
JButton button = new JButton(String.valueOf(++counter));
Dimension size = new Dimension(50, 30);
button.setMaximumSize(size);
button.setMinimumSize(size);
button.setPreferredSize(size);
panel.add(button);
panel.revalidate();
}
private JButton createButton(String text, int mnemonic, String tooltip) {
JButton button = new JButton(text);
button.setMnemonic(mnemonic);
button.setToolTipText(tooltip);
button.addActionListener(this);
return button;
}
private JPanel createButtonsPanel() {
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(createButton(ADD, KeyEvent.VK_A, "Add button to panel"));
buttonsPanel.add(createButton(EXIT, KeyEvent.VK_X, "Exit the application"));
return buttonsPanel;
}
private void createGui() {
frame = new JFrame("Add Buttons");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createPanel(), BorderLayout.CENTER);
frame.add(createButtonsPanel(), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JScrollPane createPanel() {
panel = new JPanel();
LayoutManager mgr = new BoxLayout(panel, BoxLayout.LINE_AXIS);
panel.setLayout(mgr);
JScrollPane scrollPane = new JScrollPane(panel,
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setPreferredSize(new Dimension(500, 100));
return scrollPane;
}
public static void main(String[] args) {
EventQueue.invokeLater(new AdButton());
}
}
You should use an ActionListener rather than a MouseListener
when you want an action to be performed as a result of clicking in a JButton
.
The important part in the addButton()
method is the call to revalidate()
which makes the JPanel
layout all its components and draw them on the screen. You need to do this since you have added another component to the JPanel
.
Related Topics
How to Get a Date Without Time in Java
Noclassdeffounderror on Maven Dependency
Why Does the Ternary Operator Unexpectedly Cast Integers
How to Set an Image as a Background for Frame in Swing Gui of Java
Should I Return a Collection or a Stream
Regex to Split Camelcase or Titlecase (Advanced)
How to Read and Understand the Java Stack Trace
Behaviour of Final Static Method
What's the Difference Between <> and <? Extends Object> in Java Generics
How to Create Custom Methods for Use in Spring Security Expression Language Annotations
How Do Shift Operators Work in Java
Java.Awt.Eventqueue.Invokelater Explained
Calling Method from Constructor
Drawing Multiple Jcomponents to a Frame
Java Garbage Collection Log Messages
How to Get Out of While Loop in Java with Scanner Method "Hasnext" as Condition