I'd like to have a GUI that can adapt to user input, rather than making a different panel for each option.
The first panel has a number of buttons to choose from, each will bring you to the next panel that will contain text entry fields.
Option A: Has 2 components and should open a panel with 4 text fields.
Option B: Has 3 components and should open a panel with 6 text fields.
Specifically, option A is a recipe with two components, and option B is a recipe with 3 components. Each component has a lot number and an expiration date. So both panels will have the same two types of fields: lot number and expiration date. The number and names of components is what will change.
Can I have the same panel be able to adapt to a number of components sent to it based on which of the two options was selected? Or do I have to make two separate panels, one with 4 fields and one with 6?
Here's one idea:
Map<String, JTextField> fieldMap = new HashMap<String, JTextField>()
for(int i = 0; i < recipe.length; i++)
{
fieldMap.put("field" + i, new JTextField());
}
Idea derived from Creating a variable name using a String value
The code below addresses specifically your question statement, although I can't help thinking that you probably want something more generic, i.e. where there are more than two options. Also, the below code is only one possible implementation of your stated requirements.
The idea in the below code is to initially create all the required GUI components in a single container and simply change the visibility of the [optional] components depending on the selected option.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerDateModel;
public class Opciones implements ActionListener {
private JFrame frame;
private JLabel expiryThirdLabel;
private JLabel lotThirdLabel;
private JRadioButton twoRadioButton;
private JRadioButton threeRadioButton;
private JSpinner expiryFirstSpinner;
private JSpinner expirySecondSpinner;
private JSpinner expiryThirdSpinner;
private JTextField lotFirstTextField;
private JTextField lotSecondTextField;
private JTextField lotThirdTextField;
public void actionPerformed(ActionEvent event) {
Object src = event.getSource();
boolean flag;
if (twoRadioButton == src) {
flag = false;
}
else if (threeRadioButton == src) {
flag = true;
}
else {
flag = false;
JOptionPane.showMessageDialog(frame,
"Unrecognized source.",
"WARNING",
JOptionPane.WARNING_MESSAGE);
}
expiryThirdLabel.setVisible(flag);
expiryThirdSpinner.setVisible(flag);
lotThirdLabel.setVisible(flag);
lotThirdTextField.setVisible(flag);
frame.pack();
}
private void createAndDisplayGui() {
frame = new JFrame("Options");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTopPanel(), BorderLayout.PAGE_START);
frame.add(createForm(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createForm() {
JPanel form = new JPanel(new GridBagLayout());
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;
JLabel lotFirstLabel = new JLabel("Lot Number");
form.add(lotFirstLabel, gbc);
gbc.gridx = 1;
lotFirstTextField = new JTextField(6);
form.add(lotFirstTextField, gbc);
gbc.gridx = 2;
JLabel expiryFirstLabel = new JLabel("Expiry");
form.add(expiryFirstLabel, gbc);
gbc.gridx = 3;
expiryFirstSpinner = createSpinner();
form.add(expiryFirstSpinner, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
JLabel lotSecondLabel = new JLabel("Lot Number");
form.add(lotSecondLabel, gbc);
gbc.gridx = 1;
lotSecondTextField = new JTextField(6);
form.add(lotSecondTextField, gbc);
gbc.gridx = 2;
JLabel expirySecondLabel = new JLabel("Expiry");
form.add(expirySecondLabel, gbc);
gbc.gridx = 3;
expirySecondSpinner = createSpinner();
form.add(expirySecondSpinner, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
lotThirdLabel = new JLabel("Lot Number");
lotThirdLabel.setVisible(false);
form.add(lotThirdLabel, gbc);
gbc.gridx = 1;
lotThirdTextField = new JTextField(6);
lotThirdTextField.setVisible(false);
form.add(lotThirdTextField, gbc);
gbc.gridx = 2;
expiryThirdLabel = new JLabel("Expiry");
expiryThirdLabel.setVisible(false);
form.add(expiryThirdLabel, gbc);
gbc.gridx = 3;
expiryThirdSpinner = createSpinner();
expiryThirdSpinner.setVisible(false);
form.add(expiryThirdSpinner, gbc);
return form;
}
private JSpinner createSpinner() {
SpinnerDateModel sdm = new SpinnerDateModel();
JSpinner spinner = new JSpinner(sdm);
spinner.setEditor(new JSpinner.DateEditor(spinner, "MM/dd/yyyy")); // USA format
return spinner;
}
private JPanel createTopPanel() {
JPanel topPanel = new JPanel();
JLabel label = new JLabel("Number of Components");
topPanel.add(label);
ButtonGroup buttonGroup = new ButtonGroup();
twoRadioButton = new JRadioButton("Two");
twoRadioButton.addActionListener(this);
twoRadioButton.setSelected(true);
buttonGroup.add(twoRadioButton);
topPanel.add(twoRadioButton);
threeRadioButton = new JRadioButton("Three");
threeRadioButton.addActionListener(this);
buttonGroup.add(threeRadioButton);
topPanel.add(threeRadioButton);
return topPanel;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new Opciones().createAndDisplayGui());
}
}
Initially, the GUI looks like this
And after selecting Three radio button
Refer to the following.
How to Use Buttons, Check Boxes, and Radio Buttons
How to Make Frames (Main Windows)
How to Use Spinners
How to Use GridBagLayout
How to Write an Action Listener
Related
I need to create a simple GUI app using Swing in Eclipse. I've decided that I wanted to make a simple Car Rental service app.
I'm not too sure on how to attach prices to the car models and days that are in two separate combo boxes. I'm also not too sure on how to make the combined price of the car model and day appear in a text box once a hire button is pressed.
Below is a picture of my GUI just so you guys can see what I'm working with. I've also added my code that I have so far.
Picture of my GUI
private JLabel l0 = new JLabel(" Car Rental ");
private JLabel l1 = new JLabel("Name ");
private JTextField t1=new JTextField(" ",8);
private JLabel l2 = new JLabel("Email ");
private JTextField t2=new JTextField(" ",8);
private JLabel l3 = new JLabel("Phone Number ");
private JTextField t3=new JTextField("0",8);
private JLabel l4 = new JLabel("Car Model ");
private String [] models={"BMW","Mercedes","Audi"};
private JComboBox c1=new JComboBox(models);
private JLabel l5 = new JLabel("Days ");
private String [] days={"1","2","3","4","5","6","7"};
private JComboBox c2=new JComboBox(days);
private JButton b1=new JButton("Hire");
private JTextField t4=new JTextField("0",8);
private JButton b2=new JButton("Print Receipt");
private JButton b3=new JButton("Exit");
private JPanel p1=new JPanel();
public MyFrame2(String s){
super(s);
Container content=getContentPane();
content.setLayout(new FlowLayout());
Font f=new Font("TimesRoman", Font.BOLD,20);
p1.setLayout(new GridLayout(7,2));
l0.setFont(f); l1.setFont(f);
content.add(l0);
p1.add(l1); p1.add(t1);
p1.add(l2); p1.add(t2);
p1.add(l3); p1.add(t3);
p1.add(l4); p1.add(c1);
p1.add(l5); p1.add(c2);
p1.add(b1); p1.add(t4);
p1.add(b2); p1.add(b3);
content.add(p1);
b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
setSize(270,320); setVisible(true);}
public void actionPerformed(ActionEvent e){
Object target=e.getSource();
if (target==b1)
if (target==b2){
System.out.println("====Receipt====");
System.out.println("Name: " + t1.getText());
System.out.println("Phone Number: " + t3.getText());
System.out.println("Car Model: " + c1.getSelectedItem());
System.out.println("Days: " + c2.getSelectedItem());}
if (target==b3) {
System.exit(1);}
}
}
The below code should get you started. It is incomplete since I didn't find all the requirements in your question.
Explanations after the code.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.math.BigDecimal;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
public class CarsHire implements ActionListener, Runnable {
private JButton exitButton;
private JButton hireButton;
private JButton receiptButton;
private JComboBox<Car> carModelsCombo;
private JComboBox<Integer> daysCombo;
private JFrame frame;
private JTextField emailTextField;
private JTextField nameTextField;
private JTextField phoneTextField;
private JTextField priceTextField;
#Override // java.awt.event.ActionListener
public void actionPerformed(ActionEvent event) {
Object src = event.getSource();
if (exitButton == src) {
System.exit(0);
}
else if (hireButton == src) {
displayPrice();
}
else if (receiptButton == src) {
System.out.println("====Receipt====");
System.out.println("Name: " + t1.getText());
System.out.println("Phone Number: " + t3.getText());
System.out.println("Car Model: " + c1.getSelectedItem());
System.out.println("Days: " + c2.getSelectedItem());
}
}
#Override // java.lang.Runnable
public void run() {
createAndShowGui();
}
private void createAndShowGui() {
frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createHeaderPanel(), BorderLayout.PAGE_START);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.add(createButtonsPanel(), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButtonsPanel() {
JPanel buttonsPanel = new JPanel();
receiptButton = new JButton("Print Receipt");
receiptButton.setMnemonic(KeyEvent.VK_R);
receiptButton.addActionListener(this);
buttonsPanel.add(receiptButton);
exitButton = new JButton("Exit");
exitButton.setMnemonic(KeyEvent.VK_X);
exitButton.addActionListener(this);
buttonsPanel.add(exitButton);
exitButton.setPreferredSize(receiptButton.getPreferredSize());
return buttonsPanel;
}
private JPanel createHeaderPanel() {
JPanel headerPanel = new JPanel();
JLabel headerLabel = new JLabel("Car Rental");
Font f = new Font("TimesRoman", Font.BOLD, 20);
headerLabel.setFont(f);
headerPanel.add(headerLabel);
return headerPanel;
}
private JPanel createMainPanel() {
JPanel mainPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets.bottom = 5;
gbc.insets.left = 5;
gbc.insets.right = 5;
gbc.insets.top = 5;
gbc.anchor = GridBagConstraints.LINE_START;
// First row of form.
JLabel nameLabel = new JLabel("Name");
nameLabel.setDisplayedMnemonic(KeyEvent.VK_N);
mainPanel.add(nameLabel, gbc);
gbc.gridx = 1;
nameTextField = new JTextField(10);
mainPanel.add(nameTextField, gbc);
nameLabel.setLabelFor(nameTextField);
// Second row of form.
gbc.gridx = 0;
gbc.gridy = 1;
JLabel emailLabel = new JLabel("Email");
emailLabel.setDisplayedMnemonic(KeyEvent.VK_E);
mainPanel.add(emailLabel, gbc);
gbc.gridx = 1;
emailTextField = new JTextField(10);
mainPanel.add(emailTextField, gbc);
emailLabel.setLabelFor(emailTextField);
gbc.gridx = 0;
gbc.gridy = 2;
JLabel phoneLabel = new JLabel("Phone Number");
phoneLabel.setDisplayedMnemonic(KeyEvent.VK_P);
mainPanel.add(phoneLabel, gbc);
gbc.gridx = 1;
phoneTextField = new JTextField(10);
mainPanel.add(phoneTextField, gbc);
phoneLabel.setLabelFor(phoneTextField);
gbc.gridx = 0;
gbc.gridy = 3;
JLabel carModelLabel = new JLabel("Car Model");
carModelLabel.setDisplayedMnemonic(KeyEvent.VK_M);
mainPanel.add(carModelLabel, gbc);
gbc.gridx = 1;
Car[] carModels = new Car[]{new Car("BMW", new BigDecimal(36295)),
new Car("Mercedes", new BigDecimal(33795)),
new Car("Audi", new BigDecimal(34295))};
carModelsCombo = new JComboBox<>(carModels);
carModelsCombo.setSelectedIndex(-1);
mainPanel.add(carModelsCombo, gbc);
carModelLabel.setLabelFor(carModelsCombo);
gbc.gridx = 0;
gbc.gridy = 4;
JLabel daysLabel = new JLabel("Days");
daysLabel.setDisplayedMnemonic(KeyEvent.VK_D);
mainPanel.add(daysLabel, gbc);
gbc.gridx = 1;
daysCombo = new JComboBox<>(new Integer[]{1, 2, 3, 4, 5, 6, 7});
daysCombo.setSelectedIndex(-1);
mainPanel.add(daysCombo, gbc);
daysLabel.setLabelFor(daysCombo);
gbc.gridx = 0;
gbc.gridy = 5;
hireButton = new JButton("Hire");
hireButton.setMnemonic(KeyEvent.VK_H);
hireButton.addActionListener(this);
mainPanel.add(hireButton, gbc);
gbc.gridx = 1;
priceTextField = new JTextField(10);
mainPanel.add(priceTextField, gbc);
return mainPanel;
}
private void displayPrice() {
Car car = (Car) carModelsCombo.getSelectedItem();
if (car != null) {
BigDecimal price = car.getPrice();
priceTextField.setText(price.toString());
}
}
/**
* #param args
*/
public static void main(String[] args) {
EventQueue.invokeLater(new CarsHire());
}
}
class Car {
private String model;
private BigDecimal price;
public Car(String model, BigDecimal price) {
this.model = model;
this.price = price;
}
public String getModel() {
return model;
}
public BigDecimal getPrice() {
return price;
}
public String toString() {
return model;
}
}
Swing code is executed on the Event Dispatch Thread (EDT). The JFrame constructor will launch the EDT but there was a time where Oracle recommended explicitly launching the EDT via method invokeLater() of class EventQueue. That method takes a single argument which is an instance of a class that implements the Runnable interface.
Swing uses the Model-View-Controller (MVC) paradigm so each Swing component has a model that stores the data that the component displays. JComboBox model is its list of items. That list can contain objects of any class. The value displayed by the JComboBox is the value returned by the toString() method of the class. Hence I created a Car class that contains the car's model and its price. Hence what is displayed in the JComboBox is just the [car] model, but the selected item is actually an instance of class Car. So in the displayPrice() method, I know that the value returned by getSelectedItem() must be an instance of Car (or null if nothing is selected). From there it's simple to obtain the [car] price and display it in the priceTextField.
Initially, I thought the price meant the actual price of the car, that's why I used BigDecimal for the price in class Car.
As I said in my comment to your question, I use GridBagLayout since it is very suitable for laying out forms. There are other layout managers that are also suitable for laying out forms. I am just used to using GridBagLayout.
I also use mnemonics. For example if you press the keys Alt+H it will activate the Hire button and if you press Alt+N, the Name text field will become the focused field.
Refer to Using Top-Level Containers which is part of Oracle's java tutorials. The default content pane for a JFrame is a JPanel whose layout manager is BorderLayout. When you program in Swing you need to look at the source code a lot to understand what's going on and how best to utilize the framework.
I am new to JFrame and I am having problems with the layout in NetBean, how to solve this layout problem? I tried to resize, but the position of the elements will become mess. I am trying to display each detail to the specified text areas .
Am i using the wrong layout or my coding are having problems? help...><
This is my output now
And this is the output i want
These are my codings :
public class PokemonJournal extends JFrame
implements ActionListener {
JTextArea FirstName = new JTextArea(1, 10);
JTextArea LastName = new JTextArea(1, 10);
JTextArea Level = new JTextArea(1, 10);
JTextArea Gender = new JTextArea(1, 10);
JButton showPokemon = new JButton("Show");
JButton showRaid = new JButton("Show");
JButton showPokestop = new JButton("Show");
DBHandler db = new DBHandler();
ImageIcon image = new ImageIcon("p1.jpg");
JLabel imageLabel = new JLabel(image);
public static void main(String[] args) {
PokemonJournal jf = new PokemonJournal();
}
public PokemonJournal() {
setLayout(new FlowLayout());
setSize(300, 600);
setTitle(" Pokemon Journal ");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLocationRelativeTo(null);
setResizable(false);
JPanel top = new JPanel();
add("north", top);
top.add(new Label("Pokemon Journal"));
JPanel side = new JPanel();
add("West", side);
side.setLayout(new GridLayout());
side.add(imageLabel);
JPanel line1 = new JPanel();
add("center", line1);
line1.setLayout(new GridLayout());
line1.add(new Label("First Name :"));
line1.add(FirstName);
JPanel line2 = new JPanel();
add("Center", line2);
FirstName.setEditable(false);
line2.setLayout(new GridLayout());
line2.add(new Label("Last Name :"));
line2.add(LastName);
LastName.setEditable(false);
JPanel line3 = new JPanel();
add("Center", line3);
line3.setLayout(new GridLayout());
line3.add(new Label("Level :"));
line3.add(Level);
Level.setEditable(false);
JPanel line4 = new JPanel();
add("Center", line4);
line4.setLayout(new GridLayout());
line4.add(new Label("Gender : "));
line4.add(Gender);
Gender.setEditable(false);
JPanel line5 = new JPanel();
add("Center", line5);
line5.setLayout(new GridLayout());
line5.add(new Label("Pokemon Caught:"));
line5.add(showPokemon);
JPanel line6 = new JPanel();
add("Center", line6);
line6.setLayout(new GridLayout());
line6.add(new Label("Raid Won:"));
line6.add(showRaid);
JPanel line7 = new JPanel();
add("Center", line7);
line7.setLayout(new GridLayout());
line7.add(new Label("Pokestop visited:"));
line7.add(showPokestop);
}
Am i using the wrong layout or my coding are having problems?
Well, yes, a little, but it has more to do with the size of your JFrame, never call setSize() on them, instead call pack(). However if you change it for pack(), the default orientation of the FlowLayout is FlowLayout.HORIZONTAL and thus all your components will go to the right of each other.
Then, you have 2 options:
Keep the JFrame's layout as FlowLayout but make two JPanels, one for the image and one for the data, the image might have the default FlowLayout as well but the other one might have GridLayout.
Use GridBagLayout for all your components, letting the image JLabel to have a height of 7 cells and all the others a height of 1.
For the following example I will be using the GridBagLayout option, and I recommend you to try to make the multipanel option (option 1).
However, before starting I must mention your other problems in your code:
You're not following the Java naming conventions: firstWordLowerCaseVariable, firstWordLowerCaseMethods(), FirstWordUpperCaseClasses, ALL_WORDS_UPPER_CASE_CONSTANTS, this will make your code easier to read and understand for you and for us.
You're not changing the behavior of the JFrame so, there's no need to inherit from it: See Extends JFrame vs. creating it inside the program for more information.
Related to the above point, it's wise to build your GUI towards JPanels instead of JFrames, see: The Use of Multiple JFrames: Good or Bad Practice? as well, as I think you might end up in similar problems in the future.
You're not placing your program on the Event Dispatch Thread (EDT), see this related answer to see how to solve this problem.
You're calling setSize(...) method, and as I said before, it's always better to call pack() method instead, leaving the calculations for the GUI size to the layout manager.
You're calling setVisible before adding all your components to the GUI, this could lead you to blank or black screens, it should be the last line in your program.
Related to the above point, I always like to start doing the GUI from inside out and adding the items that way, instead of outside in.
Why are you using JTextAreas instead of JTextFields for the user information?
Now, the code that follows the above recommendations using the 2nd option I gave you is this:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class PokemonJournal {
private JFrame frame;
private JPanel pane;
private GridBagConstraints gbc;
private JLabel imageLabel;
private JLabel firstName;
private JLabel lastName;
private JLabel level;
private JLabel gender;
private JLabel pokemonCaught;
private JLabel raidWon;
private JLabel pokestopVisited;
private JTextField nameField;
private JTextField lastNameField;
private JTextField levelField;
private JTextField genderField;
private JButton pokemonCaughtButton;
private JButton raidWonButton;
private JButton pokestopVisitedButton;
public static void main(String[] args) {
SwingUtilities.invokeLater(new PokemonJournal()::createAndShowGui);
}
private void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
pane = new JPanel();
pane.setLayout(new GridBagLayout());
gbc = new GridBagConstraints();
imageLabel = new JLabel();
try {
imageLabel.setIcon(new ImageIcon(
new URL("http://pm1.narvii.com/6535/1b362404d09091a335ce53fa68506827418890a3_128.jpg")));
} catch (MalformedURLException e) {
e.printStackTrace();
}
firstName = new JLabel("First Name: ");
lastName = new JLabel("Last Name: ");
level = new JLabel("Level: ");
gender = new JLabel("Gender: ");
pokemonCaught = new JLabel("Pokemon Caught: ");
raidWon = new JLabel("Raid Won: ");
pokestopVisited = new JLabel("Pokestop Visited: ");
nameField = new JTextField(10);
lastNameField = new JTextField(10);
levelField = new JTextField(10);
genderField = new JTextField(10);
pokemonCaughtButton = new JButton("Show");
raidWonButton = new JButton("Show");
pokestopVisitedButton = new JButton("Show");
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridheight = 7;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(5, 5, 5, 5);
pane.add(imageLabel, gbc);
gbc.gridx = 1;
gbc.gridheight = 1;
pane.add(firstName, gbc);
gbc.gridx = 2;
pane.add(nameField, gbc);
gbc.gridx = 1;
gbc.gridheight = 1;
gbc.gridy++;
pane.add(lastName, gbc);
gbc.gridx = 2;
pane.add(lastNameField, gbc);
gbc.gridx = 1;
gbc.gridheight = 1;
gbc.gridy++;
pane.add(level, gbc);
gbc.gridx = 2;
pane.add(levelField, gbc);
gbc.gridx = 1;
gbc.gridheight = 1;
gbc.gridy++;
pane.add(gender, gbc);
gbc.gridx = 2;
pane.add(genderField, gbc);
gbc.gridx = 1;
gbc.gridheight = 1;
gbc.gridy++;
pane.add(pokemonCaught, gbc);
gbc.gridx = 2;
pane.add(pokemonCaughtButton, gbc);
gbc.gridx = 1;
gbc.gridheight = 1;
gbc.gridy++;
pane.add(raidWon, gbc);
gbc.gridx = 2;
pane.add(raidWonButton, gbc);
gbc.gridx = 1;
gbc.gridheight = 1;
gbc.gridy++;
pane.add(pokestopVisited, gbc);
gbc.gridx = 2;
pane.add(pokestopVisitedButton, gbc);
frame.add(pane);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
And it produces a GUI similar to this one:
I want to creat a palet with many JComboBox. like that :
for(int x=0; x<MAX; x++){
box[x] = new JComboBox(new String[]{"op1", "op2", "op3");
}
at the right of each JComboBox i want to create many JTextField. So, in my palet i will have some think like that:
myJComboBox1 myJTextField
anotherJTextField
anotherJTextField
myJComboBox2 myJTextField
anotherJTextField
anotherJTextField
...
How can i do that please ? I tried by setBounds and other layout like FlowLayout and GridLayout but without success.
GridBagLayout is the best solution. However, if you are new to Swing, it might be a bit over complicated. In that case:
Use GridLayout(0, 2) for the main panel.
Wrap the combobox in a Panel with a border layout and add it to north. Add it to the main panel.
Use another panel with GridLayout(0,1) add your text fields to it and add it to the main panel.
and loop...
Adding sample code:
package snippet;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridLayout;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class BorderLayoutTest extends JFrame {
static private int MAX = 10 ;
public BorderLayoutTest() {
super(BorderLayoutTest.class.getName());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents();
}
private void initComponents() {
setLayout(new GridLayout(0, 2));
for(int i = 0; i < MAX; i++) {
add(createComboPanel());
add(createPanelWithTextFields());
}
pack();
}
public Component createComboPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.add(new JComboBox<>(new String[] { "First Option", "Second Option", "Third Option" }), BorderLayout.NORTH);
return panel;
}
private Component createPanelWithTextFields() {
JPanel panel = new JPanel(new GridLayout(0, 1));
panel.add(new JTextField(30));
panel.add(new JTextField(30));
panel.add(new JTextField(30));
return panel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() {
new BorderLayoutTest().setVisible(true);
}
});
}
}
Take a look at GridBagLayout. You can use your window like a table.
myPanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
JLabel lbl = new JLabel("bla");
myPanel.add(lbl, gbc);
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 0;
gbc.weightx = 3;
JTextField tf = new JTextField();
myPanel.add(tf, gbc);
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
gbc.weightx = 3;
JTextField othertf = new JTextField();
myPanel.add(othertf, gbc);
You can even set weights and so on for the GridBagConstraints. It is completly adjusted as table. That will result in something like that:
label textfield
textfield
Just re-read the question. Just replace the JLabels with JComboBoxes and it answers your question a little bit better ;)
This is my first question inhere, so please bear with me :)
Im working on a dynamic part of a GUI, and for some reason its teasing me.
The class is opened in a new window after login.
What I want, is for a new JPanel to be built and added to 'container' every time the "add player" button is clicked. It is supposed to put them below eachother, yet all it does is to add one button on the first click, and then the rest of the clicks afterwards does nothing.
Any help is appreciated :)
package Gui;
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 javax.swing.JButton;
import javax.swing.JFrame;
//import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
#SuppressWarnings("serial")
public class TeamManagerGUI extends JFrame implements ActionListener
{
// private JLabel pNameLabel = new JLabel("Player Name: "),
// pSchoolLabel = new JLabel("School: ");
// private JTextField pNameField = new JTextField(),
// pSchoolField = new JTextField();
private JButton addButton = new JButton("Add Player"),
removeButton = new JButton("Remove player");
private JPanel container = new JPanel(),
playerContainer = new JPanel();
int frameCounter = 1;
public TeamManagerGUI()
{
super("Team Manager User Interface");
setSize(1200,800);
setDefaultCloseOperation(EXIT_ON_CLOSE);
container.setLayout(new GridBagLayout());
playerContainer.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(3,3,3,3);
addButton.addActionListener(this);
container.add(addButton,gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.insets = new Insets(3,3,3,3);
container.add(removeButton,gbc);
this.add(container);
}
public void playerFrame()
{
GridBagConstraints gbc = new GridBagConstraints();
playerFrameArr.add(new JPanel());
gbc.gridx = 0;
gbc.gridy = 0;
playerContainer.add(new JButton("LABEL"),gbc);
gbc.gridx = 1;
gbc.gridy = 0;
playerContainer.add(new JButton("BUTTON"),gbc);
gbc.gridx = 0;
gbc.gridy = frameCounter+1;
container.add(playerContainer,gbc);
System.out.println(frameCounter);
frameCounter++;
}
public void addPlayerRow()
{
playerFrame();
container.revalidate();
container.repaint();
}
public void removePlayerRow()
{
//Not yet implemented
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource() == addButton)
{
addPlayerRow();
}
if(ae.getSource() == removeButton)
{
//Not yet implemented
}
}
}
You are adding the playerContainer again and again. I think you should actually use the newly created JPanel. This one should be populated and added to the main container.
Adding a single panel multiple times will not render properly as this screws up the layout. I think you need to keep a reference to the new JPanel and fill this one with your layout and the buttons.
I am thinking something like this:
public void playerFrame()
{
GridBagConstraints gbc = new GridBagConstraints();
JPanel newPanel = new JPanel(new GridBagLayout());
playerFrameArr.add(newPanel);
gbc.gridx = 0;
gbc.gridy = 0;
newPanel.add(new JButton("LABEL"), gbc);
gbc.gridx = 1;
gbc.gridy = 0;
newPanel.add(new JButton("BUTTON"), gbc);
gbc.gridx = 0;
gbc.gridy = frameCounter + 1;
container.add(newPanel, gbc);
System.out.println(frameCounter);
frameCounter++;
}
I added list items to JList
numbersList.add("first example");
numbersList.add("second example");
numbersList.add("third example");
and when I add new text or number to field it would would be added into list and showed at JList. Here my code, I just want to make that when I push button new element appear at JList fullList from list numberList which has been added from textfield numberTxtFld.
p.s i have removed some unnecessary code.
package average;
import java.awt.Color;
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.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
public class Surface extends JLabel{
private JTextField numberTxtFld;
private JLabel topLabel;
private JLabel sumLabel;
private JLabel avgLabel;
private JLabel maxLabel;
private JLabel minLabel;
private JLabel amountLabel;
private JLabel listLabel;
private JLabel resultLabel;
private JLabel sumAnswerFld;
private JLabel avgAnswerFld;
private JLabel maxAnswerFld;
private JLabel minAnswerFld;
private JLabel amountAnswerFld;
private JLabel fullListLabel;
private JList fullList;
final List<String> numbersList = new ArrayList<String>();
private JButton submitBtn;
private JButton closeBtn;
private JPanel panel;
private int arrayIndex = 0;// used for components adding into array
public Surface(){
panel = new JPanel();
panel.setBackground(Color.WHITE);
panel.setSize(300, 300);
panel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
topLabel = new JLabel("Enter your number and push submit");
gbc.gridwidth = 3;
gbc.gridx = 0; // column
gbc.gridy = 0; // row
panel.add(topLabel, gbc);
gbc.gridwidth = 1; // setting grid column with to default
fullListLabel = new JLabel("Full list");
gbc.gridx = 2;
gbc.gridy = 1;
panel.add(fullListLabel, gbc);
amountLabel = new JLabel("Amount");
gbc.gridx = 0;
gbc.gridy = 5;
panel.add(amountLabel, gbc);
amountAnswerFld = new JLabel("0");
gbc.gridx = 1;
gbc.gridy = 5;
panel.add(amountAnswerFld, gbc);
numberTxtFld = new JTextField();
numberTxtFld.setColumns(10);
gbc.gridx = 0;
gbc.gridy = 1;
panel.add(numberTxtFld, gbc);
submitBtn = new JButton("Submit");
gbc.gridx = 1;
gbc.gridy = 1;
submitBtn.addActionListener(
new ActionListener(){
#Override
public void actionPerformed(ActionEvent event) {
String text = numberTxtFld.getText();
numbersList.add(text);
}
}
);
panel.add(submitBtn, gbc);
numbersList.add("first example");
numbersList.add("second example");
numbersList.add("third example");
fullList = new JList(numbersList.toArray());
fullList.setVisibleRowCount(6);
fullList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
gbc.gridheight = 6;
gbc.gridx = 2;
gbc.gridy = 2;
panel.add(new JScrollPane(fullList), gbc);
gbc.gridheight = 1; // setting grid column with to default
add(panel);
}
}
You will need to create a ListModel. As what you are doing is very simple you can use the DefaultListModel.
you will need to declare
private DefaultListModel defaultListModel;
and instantiate it
defaultListModel = new DefaultListModel();
then attach it to your JList in the JLists constructor
fullList = new JList(defaultListModel);
you will then need to add your items to the defaultListModel, probably in a loop
for (Object o : numbersList) {
defaultListModel.addElement(o);
}
Finally in your action listener you now need to call the addElement method on the defaultListModel instead
String text = numberTxtFld.getText();
defaultListModel.add(text);
Then you should get everything to work as you desire plus all the update events are handled for you.
When you do this:
fullList = new JList(numbersList.toArray());
You are not magically attaching the JList to numbersList, you are simply populating the JList with the content of numbersList at that point, which, of course, does not include any items added later when your button is pressed.
You have at least three options:
The most basic solution is to explicitly add a new item to fullList in your submitBtn action listener. You have a number of options. You can just add the new item to fullList from submitBtn, which is simple and may be adequate from your application. To do this, make sure the list's model is a DefaultListModel, then you can use ((DefaultListModel)getModel()).addElement() to add an item.
DefaultListModel model = new DefaultListModel();
fullList.setModel(model);
// to add an element (during initial population, and action listener):
model.addElement("the element");
A more robust solution would be to completely repopulate fullList based on the current contents of numbersList, and do that from your action listener to resync the GUI to the data. This may not be desirable for other reasons, e.g. it may be unacceptable to clear the list first because of its effect on the current item selection, etc. Depends on your requirements. You could use JList's setListData() for this.
// any time you want to repopulate the list:
fullList.setListData(numbersList.toArray());
But bear in mind that this sets the list model to a read-only model, and you will not be able to use getModel().addElement() later.
An even more robust, and the generally preferred, solution is to implement a ListModel that reflects the contents of numbersList and assign that ListModel to your JList. This can lead to very clean code that lets you perform any operation you want on your list while keeping the GUI and data in sync. Rather than repost code here, you can find a simple implementation in the answer to this question.
Hope that helps.