I am trying to add the buttons to the centerPanel that I created, then add that panel to the main center borderlayout. for some reason though my tab will not repaint anymore. It worked fine a while ago when I had the DrawFieldsListener class in the same class file as the MagicSquare, but nothing in the code has changed from my splitting them into two class files. So i really don't know what is going on. When it did repaint before, it would also take a long time. Any help? thanks!
All source for the project is on GitHub if it is easier to read and understand there: https://github.com/andrefecto/Academic-Convivium-Project
MagicSquare Class:
package magicSquare;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class MagicSquare extends JPanel {
JLabel sizeLabel = new JLabel("Enter A Square Size: ");
JButton setSize;
static JButton calculate;
static JButton reset;
static JTextField squareSize;
static JTextField field;
public static ArrayList<JTextField> inputFields = new ArrayList<JTextField>();
public static ArrayList<Integer> inputs = new ArrayList<Integer>();
public static ArrayList<Integer> totals = new ArrayList<Integer>();
public static int squared = 0;
public static int square = 0;
public static JPanel centerPanel = new JPanel();
public static JPanel bottomPanel = new JPanel();
public MagicSquare (){
setLayout(new BorderLayout());
JPanel subPanel = new JPanel();
subPanel.add(sizeLabel);
squareSize = new JTextField();
squareSize.setColumns(6);
subPanel.add(squareSize);
setSize = new JButton("Enter");
subPanel.add(setSize);
setSize.addActionListener(new DrawFieldsListener());
add(subPanel, BorderLayout.NORTH);
add(new DrawFieldsListener(), BorderLayout.CENTER);
}
}
my DrawFieldsListener class:
package magicSquare;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;
class DrawFieldsListener extends JPanel implements ActionListener {
int square = MagicSquare.square;
int squared = MagicSquare.squared;
JPanel centerPanel = MagicSquare.centerPanel;
JTextField squareSize = MagicSquare.squareSize;
JTextField field = MagicSquare.field;
ArrayList<JTextField> inputFields = MagicSquare.inputFields;
JButton calculate = MagicSquare.calculate;
JButton reset = MagicSquare.reset;
JPanel bottomPanel = MagicSquare.bottomPanel;
public void actionPerformed(ActionEvent e){
square = Integer.parseInt(squareSize.getText());
squared = square*square;
centerPanel.setLayout(new GridLayout(square, square));
for(int i = 0; i < squared; i++){
field = new JTextField();
field.setColumns(3);
inputFields.add(field);
centerPanel.add(inputFields.get(i));
System.out.println("DRAWING");
}
add(centerPanel, BorderLayout.CENTER);
System.out.println("ADDING ADDITINOAL BUTTONS");
additionalButtons();
System.out.println("ADDED ADDITINOAL BUTTONS");
System.out.println("REPAINTING");
repaint();
System.out.println("REPAINTED");
}
public void additionalButtons(){
calculate = new JButton("Calculate");
reset = new JButton("Reset");
bottomPanel.setLayout(new GridLayout(2, 2));
bottomPanel.add(reset);
bottomPanel.add(calculate);
add(bottomPanel, BorderLayout.SOUTH);
calculate.addActionListener(new CalculateListener());
reset.addActionListener(new ResetListener());
}
}
Mistake #1
public static JPanel centerPanel = new JPanel();
Followed by...
class DrawFieldsListener extends JPanel implements ActionListener {
//...
JPanel centerPanel = MagicSquare.centerPanel;
static is not a cross object communication mechanism...and now I have no idea who is suppose to be responsible for managing the centerPanel...
Remember, static is not your friend, beware of how it is used
Mistake #2
setSize.addActionListener(new DrawFieldsListener());
add(subPanel, BorderLayout.NORTH);
add(new DrawFieldsListener(), BorderLayout.CENTER);
You are creating two instances of DrawFieldsListener (which is a panel), one is acting as the ActionListener and one is acting as the view, but which one is actually housing MagicSquare.centerPanel as a component can only have one parent...
Mistake #3
Not revalidating the container after you have changed it...
public void actionPerformed(ActionEvent e) {
square = Integer.parseInt(squareSize.getText());
squared = square * square;
centerPanel.setLayout(new GridLayout(square, square));
for (int i = 0; i < squared; i++) {
field = new JTextField();
field.setColumns(3);
inputFields.add(field);
centerPanel.add(inputFields.get(i));
System.out.println("DRAWING");
}
add(centerPanel, BorderLayout.CENTER);
System.out.println("ADDING ADDITINOAL BUTTONS");
additionalButtons();
System.out.println("ADDED ADDITINOAL BUTTONS");
System.out.println("REPAINTING");
revalidate();
repaint();
System.out.println("REPAINTED");
}
Swing is lazy when it comes to container management, it assumes that you will want to do a number of adds or removes, so it won't update the container hierarchy layout until you ask it to, as the operation can be expensive
A better solution...
Isolate responsibility and provide information to your objects in a de-coupled manner.
For example, the DrawFieldsListener shouldn't care about MagicSquare, but should provide a means by which "some body" can tell it how many squares it should create.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
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.JSpinner;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MagicSquare extends JPanel {
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) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MagicSquare());
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
JLabel sizeLabel = new JLabel("Enter A Square Size: ");
JButton setSize;
private JSpinner squareSize;
JTextField field;
public MagicSquare() {
setLayout(new BorderLayout());
JPanel subPanel = new JPanel();
subPanel.add(sizeLabel);
squareSize = new JSpinner();
subPanel.add(squareSize);
setSize = new JButton("Enter");
subPanel.add(setSize);
DrawFieldsListener dfl = new DrawFieldsListener();
setSize.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int gridSize = (int) squareSize.getValue();
dfl.makeGrid(gridSize);
}
});
add(subPanel, BorderLayout.NORTH);
add(dfl, BorderLayout.CENTER);
}
class DrawFieldsListener extends JPanel {
private JButton calculate;
private JButton reset;
private ArrayList<JTextField> inputFields = new ArrayList<JTextField>();
private ArrayList<Integer> inputs = new ArrayList<Integer>();
private ArrayList<Integer> totals = new ArrayList<Integer>();
private int squared = 0;
private int square = 0;
private JPanel centerPanel = new JPanel();
private JPanel bottomPanel = new JPanel();
public void makeGrid(int gridSize) {
square = gridSize;
squared = square * square;
centerPanel.setLayout(new GridLayout(square, square));
for (int i = 0; i < squared; i++) {
field = new JTextField();
field.setColumns(3);
inputFields.add(field);
centerPanel.add(inputFields.get(i));
System.out.println("DRAWING");
}
add(centerPanel, BorderLayout.CENTER);
System.out.println("ADDING ADDITINOAL BUTTONS");
additionalButtons();
System.out.println("ADDED ADDITINOAL BUTTONS");
System.out.println("REPAINTING");
revalidate();
repaint();
System.out.println("REPAINTED");
}
public void additionalButtons() {
calculate = new JButton("Calculate");
reset = new JButton("Reset");
bottomPanel.setLayout(new GridLayout(2, 2));
bottomPanel.add(reset);
bottomPanel.add(calculate);
add(bottomPanel, BorderLayout.SOUTH);
// calculate.addActionListener(new CalculateListener());
// reset.addActionListener(new ResetListener());
}
}
}
Related
package SOS;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
public class BoardPanel {
private JFrame frame;
private void createAndDisplayGui() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTopPanel(), BorderLayout.PAGE_START);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private void createBoard(ActionEvent event) {
Object source = event.getSource();
if (source instanceof JTextField) {
JTextField textField = (JTextField) source;
String text = textField.getText();
int dimension = Integer.parseInt(text);
JPanel board = new JPanel(new GridLayout(dimension, dimension));
for (int row = 0; row < dimension; row++) {
for (int col = 0; col < dimension; col++) {
JLabel square = new JLabel(" ");
square.setBackground(Color.white);
square.setOpaque(true);
square.setBorder(BorderFactory.createLineBorder(Color.black));
board.add(square);
}
}
frame.add(board, BorderLayout.CENTER);
frame.pack();
}
}
private JPanel createTopPanel() {
JRadioButton optionS = new JRadioButton("S");
JRadioButton optionO = new JRadioButton("O");
ButtonGroup group = new ButtonGroup();
group.add(optionS);
group.add(optionO);
JPanel topPanel = new JPanel();
JLabel label = new JLabel("Board size:");
topPanel.add(label);
JTextField boardSize = new JTextField(6);
boardSize.addActionListener(this::createBoard);
topPanel.add(boardSize);
topPanel.add(optionS, BorderLayout.NORTH);
topPanel.add(optionO, BorderLayout.CENTER);
return topPanel;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new BoardPanel().createAndDisplayGui());
}
}
I know I am supposed to make an action listener for each radio button and that seems pretty straightforward, but I am confused on how I would do that and then translate that to placing an S or O on the game boards given cell depending on what is selected. I think the more confusing part is being able to draw in the given cell either the S or the O depending on what is selected. This is for an SOS game, sort of like tic tac toe. I tried following a simple tic tac toe example but got lost as there is no radio buttons like this and I am using a different createboard method.
You can declare your radioButton globally so you can check the selected status. Then in a listener in your cells check that and place the appropriate letter:
package SOS;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
public class BoardPanel {
private JFrame frame;
private JRadioButton optionS;
private JRadioButton optionO;
private void createAndDisplayGui() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(createTopPanel(), BorderLayout.PAGE_START);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private void createBoard(ActionEvent event) {
Object source = event.getSource();
if (source instanceof JTextField) {
JTextField textField = (JTextField) source;
String text = textField.getText();
int dimension = Integer.parseInt(text);
JPanel board = new JPanel(new GridLayout(dimension, dimension));
for (int row = 0; row < dimension; row++) {
for (int col = 0; col < dimension; col++) {
JLabel square = new JLabel(" ");
square.setBackground(Color.white);
square.setOpaque(true);
square.setBorder(BorderFactory.createLineBorder(Color.black));
board.add(square);
square.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
square.setText(optionS.isSelected() ? " S " : " O ");
}
});
}
}
frame.getContentPane().add(board, BorderLayout.CENTER);
frame.pack();
}
}
private JPanel createTopPanel() {
optionS = new JRadioButton("S");
optionO = new JRadioButton("O");
ButtonGroup group = new ButtonGroup();
group.add(optionS);
group.add(optionO);
JPanel topPanel = new JPanel();
JLabel label = new JLabel("Board size:");
topPanel.add(label);
JTextField boardSize = new JTextField(6);
boardSize.addActionListener(this::createBoard);
topPanel.add(boardSize);
topPanel.add(optionS, BorderLayout.NORTH);
topPanel.add(optionO, BorderLayout.CENTER);
return topPanel;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new BoardPanel().createAndDisplayGui());
}
}
There are few ways you might be able to do this, personally, I like to decouple the workflows and remove dependencies where I can.
For example, your createBoard method is making an assumption about how the dimension value is captured by the user. What happens if you want to change that workflow to use a JSpinner or JCombobox? You'd then have to modify this method as well.
Better to pass the method the information it needs to do its job. In fact, I'd make it return an instance of JPanel, so as to remove all the dependencies, after all createBoard should do just that, nothing else.
I've changed the workflow so there is now a dedicated "create" button, this will collect the information it needs in order to be able to create the board itself. Not as dynamic as the other approach, but it gives the user time to consider their inputs
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
public class BoardPanel {
private JFrame frame;
enum State {
S, O;
}
private JPanel board;
private void createAndDisplayGui() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTopPanel(), BorderLayout.PAGE_START);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createBoard(int dimension, State state) {
JPanel board = new JPanel(new GridLayout(dimension, dimension));
for (int row = 0; row < dimension; row++) {
for (int col = 0; col < dimension; col++) {
JLabel square = new JLabel(" " + state.name() + " ");
square.setBackground(Color.white);
square.setOpaque(true);
square.setBorder(BorderFactory.createLineBorder(Color.black));
board.add(square);
}
}
return board;
}
private JPanel createTopPanel() {
JRadioButton optionS = new JRadioButton("S");
JRadioButton optionO = new JRadioButton("O");
JTextField boardSize = new JTextField(6);
JPanel topPanel = new JPanel();
ButtonGroup group = new ButtonGroup();
group.add(optionS);
group.add(optionO);
// Default state
optionS.setSelected(true);
JButton createButton = new JButton("Make it so");
createButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
State state = State.O;
if (optionS.isSelected()) {
state = State.S;
}
try {
int dimension = Integer.parseInt(boardSize.getText());
if (board != null) {
frame.remove(board);
}
board = createBoard(dimension, state);
frame.add(board, BorderLayout.CENTER);
frame.pack();
} catch (NumberFormatException exp) {
JOptionPane.showMessageDialog(topPanel, "Invalid board size", "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
JLabel label = new JLabel("Board size:");
topPanel.add(label);
topPanel.add(boardSize);
topPanel.add(optionS);
topPanel.add(optionO);
topPanel.add(createButton);
return topPanel;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new BoardPanel().createAndDisplayGui());
}
}
If you'd prefer something a little more dynamic, then you could add shared ActionListener to the buttons and text field, for example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
public class BoardPanel {
private JFrame frame;
enum State {
S, O;
}
private JPanel board;
private void createAndDisplayGui() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTopPanel(), BorderLayout.PAGE_START);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createBoard(int dimension, State state) {
JPanel board = new JPanel(new GridLayout(dimension, dimension));
for (int row = 0; row < dimension; row++) {
for (int col = 0; col < dimension; col++) {
JLabel square = new JLabel(" " + state.name() + " ");
square.setBackground(Color.white);
square.setOpaque(true);
square.setBorder(BorderFactory.createLineBorder(Color.black));
board.add(square);
}
}
return board;
}
private JPanel createTopPanel() {
JRadioButton optionS = new JRadioButton("S");
JRadioButton optionO = new JRadioButton("O");
JTextField boardSize = new JTextField(6);
JPanel topPanel = new JPanel();
ButtonGroup group = new ButtonGroup();
group.add(optionS);
group.add(optionO);
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
State state = State.O;
if (optionS.isSelected()) {
state = State.S;
}
try {
int dimension = Integer.parseInt(boardSize.getText());
if (board != null) {
frame.remove(board);
}
board = createBoard(dimension, state);
frame.add(board, BorderLayout.CENTER);
frame.pack();
} catch (NumberFormatException exp) {
// Not yet ready
}
}
};
optionS.addActionListener(actionListener);
optionO.addActionListener(actionListener);
boardSize.addActionListener(actionListener);
// Default state
optionS.setSelected(true);
JLabel label = new JLabel("Board size:");
topPanel.add(label);
topPanel.add(boardSize);
topPanel.add(optionS);
topPanel.add(optionO);
return topPanel;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new BoardPanel().createAndDisplayGui());
}
}
I feel as beginner I may have bitten off too much in regards to application building. That said, I am working on developing an application for a friend that will have prompts where each JPanel will provide fields to create an object to be used later. What I would like to have happen is that when the panel loads, it displays one object creation panel and a button to dynamically add a new panel if the user wants to make multiples (the plus button would add the new panel).
I have drawn up something in paint to illustrate this:
By my very limited understanding, I can create a panel to hold these sub-panels, and then add a action listener to the '+' button to create new panels. The only way I could think to implement this is to create a constructor for the panel I want to add. Is this possible? Let me show you what I have:
package com.company;
import java.awt.*;
import javax.swing.*;
/**
* Created by Travis on 3/1/2015.
*/
public class MainSnakeGui extends JFrame{
protected int panelCount;
//row 1
JPanel row1 = new JPanel();
JLabel splitSnakeLabel = new JLabel("Create a Split Snake", JLabel.CENTER);
//row 2
JPanel row2 = new JPanel();
JButton addButton = new JButton("+");
public MainSnakeGui() {
super("Snake Channels");
setSize(550, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridLayout layout = new GridLayout(5, 1, 10, 10);
setLayout(layout);
FlowLayout layout1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
row1.setLayout(layout1);
row1.add(splitSnakeLabel);
add(row1);
GridLayout layout2 = new GridLayout(1, 2, 10, 10);
row2.setLayout(layout2);
row2.add(addButton);
MainSnakeConstructor snakePanel = new MainSnakeConstructor();
row2.add(snakePanel);
add(row2);
setVisible(true);
}
public static void setLookAndFeel () {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception e) {
}
}
public static void main(String[] arg) {
MainSnakeGui.setLookAndFeel();
MainSnakeGui frame = new MainSnakeGui();
}
}
Here is the constructor:
package com.company;
import javax.swing.*;
import java.awt.*;
/**
* Created by Travis on 3/1/2015.
*/
public class MainSnakeConstructor extends JFrame {
public MainSnakeConstructor () {
JPanel splitSnakeRow = new JPanel();
JLabel snakeNameLabel = new JLabel("Snake Name");
JLabel channelCountLabel = new JLabel("Channel Count");
JCheckBox artistSuppliedCheckBox = new JCheckBox("Artist Supplied?");
JTextField snakeNameTextField = new JTextField(30);
JTextField channelCountTextField = new JTextField(3);
GridLayout layout = new GridLayout(3,2,10,10);
splitSnakeRow.setLayout(layout);
splitSnakeRow.add(snakeNameLabel);
splitSnakeRow.add(channelCountLabel);
splitSnakeRow.add(artistSuppliedCheckBox);
splitSnakeRow.add(snakeNameTextField);
splitSnakeRow.add(channelCountTextField);
add(splitSnakeRow);
}
}
Think about it differently. You want a button that allows you to add new panels, so you really only need a single button.
From there, you need some kind common panel which provides the functionality you want to the user (the creation panel). Then, when the user clicks the add button, you create a new creation panel and add it to the container been used to display them, for example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
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.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
JButton btnAdd = new JButton("+");
setLayout(new BorderLayout());
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.LEFT));
buttons.add(btnAdd);
add(buttons, BorderLayout.NORTH);
JPanel content = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weighty = 1;
content.add(new JPanel(), gbc);
add(new JScrollPane(content));
btnAdd.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CreationPane pane = new CreationPane();
int insertAt = Math.max(0, content.getComponentCount() - 1);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
content.add(pane, gbc, insertAt);
content.revalidate();
content.repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public static class CreationPane extends JPanel {
private static int count;
public CreationPane() {
setLayout(new GridBagLayout());
add(new JLabel("Make it so " + (count++)));
setBorder(new CompoundBorder(new LineBorder(Color.BLACK), new EmptyBorder(10, 10, 10, 10)));
}
}
}
Now having done all that, I prefer the VerticalLayout manager from SwingLabs, SwingX library, which basically does the same thing...
I'm having trouble with this JApplet. At the moment I have a CardLayout JPanel which contains two BorderLayout JPanels. Whenever I run it, the components added to each 'card' (a JButton to go back to the other JPanel) don't display unless I use setVisible(true) for each LayoutManager. Furthermore, none of my ActionListeners work. I'm assuming because they only use show() and there's something else I have to do that's alluding me.
Must I use setVisible(true)? It seems from other questions that there's a way of doing this without that. Here's the code I'm having trouble with:
/*
*Java Version: 1.8.0_25
*Author: Peadar Ó Duinnín
*Student Number: R00095488
*/
package As1;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class AUIJApplet extends JApplet implements ActionListener {
private final int WIDTH = 600;
private final int HEIGHT = 400;
private int highScore;
private int currentScore;
JPanel panelCont = new JPanel();
JPanel startPanel = new JPanel();
JPanel gamePanel = new JPanel();
JButton newGameButton = new JButton("New Game");
JButton endGameButton = new JButton("End Game");
JLabel highScoreLabel;
JLabel currentScoreLabel;
CardLayout cl = new CardLayout();
BorderLayout bl = new BorderLayout();
public AUIJApplet() {
highScore = 0;
}
#Override
public void init() {
setSize(WIDTH, HEIGHT);
panelCont.setLayout(cl);
startPanel.setLayout(bl);
gamePanel.setLayout(bl);
startPanel.add(newGameButton, BorderLayout.SOUTH);
gamePanel.add(endGameButton, BorderLayout.SOUTH);
startPanel.setBackground(Color.BLUE);
gamePanel.setBackground(Color.GREEN);
panelCont.add(startPanel, "Start Applet Screen");
panelCont.add(gamePanel, "New Game Screen");
newGameButton.addActionListener((e) -> {
newGame();
});
endGameButton.addActionListener((e) -> {
quitGame();
});
cl.show(panelCont, "Start Applet Screen");
this.add(panelCont);
}
public void newGame() {
cl.show(panelCont, "New Game Screen");
showScores(gamePanel);
}
public void quitGame() {
cl.show(panelCont, "Start Applet Screen");
if (currentScore > highScore) {
highScore = currentScore;
}
currentScore = 0;
}
public void showScores(JPanel currentPanel) {
currentPanel.add(new JLabel("High Score:") , BorderLayout.EAST);
currentPanel.add(highScoreLabel, BorderLayout.EAST);
currentPanel.add(new JLabel("Current Score:"), BorderLayout.EAST);
currentPanel.add(currentScoreLabel, BorderLayout.EAST);
}
#Override
public void actionPerformed(ActionEvent ae) {
}
}
I have made the a little similar code to perform same operation it works for me try to write the code from scratch. Here is my code.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import javax.swing.JApplet;
import javax.swing.*;
public class Example extends JApplet {
JPanel panel1,panel2,mainPanel;
JButton start,stop;
CardLayout cl = new CardLayout();
#Override
public void init() {
panel1 = new JPanel();
panel1.setBackground(Color.red);
panel1.setLayout(new BorderLayout());
panel2 = new JPanel();
panel2.setBackground(Color.blue);
panel2.setLayout(new BorderLayout());
start = new JButton("Start");
stop = new JButton("stop");
panel1.add(start,BorderLayout.SOUTH);
panel2.add(stop,BorderLayout.SOUTH);
mainPanel = new JPanel();
mainPanel.setLayout(cl);
mainPanel.add(panel1,"First Panel");
mainPanel.add(panel2, "Second Panel");
start.addActionListener((ActionEvent e) -> {
newGame();
});
stop.addActionListener((ActionEvent e) ->{
endGame();
});
this.add(mainPanel);
}
public void newGame()
{
cl.show(mainPanel, "Second Panel");
}
public void endGame()
{
cl.show(mainPanel,"First Panel");
}
}
I have a GUI with a scroll pane in it. The Scroll Pane is scrolling though a JPanel of JPanels. I would like the ability to add one more to the list of subJPanels and have the JFrame update to do it.
Right now I have the array updating, but not the JFrame.
package SSCCE;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class Add extends JFrame{
private JPanel[] branches;
private JPanel pane; //Pane that stores accounts
private JScrollPane scroller;
private JButton newBranch;
public static void main(String[] args) {
JFrame frame = new Add();
}
public Add(){
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(500, 500);
this.setTitle("How Do I add?");
this.setLayout(new BorderLayout());
this.add(statusBar(), BorderLayout.NORTH);
populateBranches();
pane = new JPanel();
pane.setLayout(new GridLayout(branches.length,1));
for (int i = 0; i < branches.length; i++){
pane.add(branches[i]);
}
scroller = new JScrollPane(pane);
scroller.createVerticalScrollBar();
this.add(scroller,BorderLayout.CENTER);
this.setVisible(true);
}
private JPanel statusBar(){
JPanel statusBar = new JPanel();
statusBar.setLayout(new FlowLayout());
newBranch = new JButton("New Branch");
newBranch.addActionListener(new ButtonEventHandler());
statusBar.add(newBranch);
return statusBar;
}
private void populateBranches(){
branches = new JPanel[2];
for (int i = 0; i < branches.length; i++){
branches[i] = new JPanel();
branches[i].setLayout(new FlowLayout());
branches[i].add(new JTextField(20));
}
}
private void newBranch(){
JPanel[] tempBranches = new JPanel[branches.length + 1];
System.out.println(tempBranches.length);
for (int i = 0; i < branches.length; i++){
tempBranches[i] = branches[i];
}
tempBranches[branches.length] = new JPanel();
tempBranches[branches.length].setLayout(new FlowLayout());
tempBranches[branches.length].add(new JTextField(20));
branches = tempBranches;
pane = new JPanel();
pane.setLayout(new GridLayout(branches.length, 1));
for (int i = 0; i < branches.length; i++){
pane.add(branches[i]);
}
pane.repaint();
pane.validate();
scroller = new JScrollPane(pane);
this.add(scroller, BorderLayout.CENTER);
this.repaint();
this.validate();
}
private class ButtonEventHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
String btnClkd = event.getActionCommand();
if (btnClkd.equals("New Branch")){
newBranch();
}
}
}
}
If you allow the GridLayout to grow, You can simply add more components to it:
// 0 means new rows are added as needed
pane.setLayout(new GridLayout(0, 1));
// ...
private void newBranch(){
// Create the component
JPanel branch = new JPanel();
branch.add(new JTextField(20));
// + any additional subcomponents
// and just add it where the others already are
pane.add(branch);
pane.revalidate();
}
I want to add textfields dynamically on the click of a button but the value to be fetched and the button are in one class and the panel where i want to add the textboxes and sliders adjacent to the are in a different class. Code is -
public class TipSplitting extends JPanel
JLabel lblNoOfGuests = new JLabel("No. Of guests");
lblNoOfGuests.setBounds(10, 26, 95, 14);
add(lblNoOfGuests);
private JTextField noofguests = new JTextField();
noofguests.setBounds(179, 23, 86, 20);
add(noofguests);
noofguests.setColumns(10);
JButton btnTiptailoring = new JButton("TipTailoring");
btnTiptailoring.setBounds(117, 286, 89, 23);
add(btnTiptailoring);
public class TipTailoring extends JPanel {}
In this class I need to create the text fields dynamically according to the no. entered. In the variable noofguests and the click of the button in the previous class.
I can't really see what the problem, but here some simple demo code of what you describe.
import java.awt.BorderLayout;
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.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class TestDynamicallyAddedTextFields {
private void initUI() {
JFrame frame = new JFrame(TestDynamicallyAddedTextFields.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel textfieldContainerPanel = new JPanel();
textfieldContainerPanel.setLayout(new GridBagLayout());
JLabel nrOfGuests = new JLabel("Nr. of guests");
final JFormattedTextField textfield = new JFormattedTextField();
textfield.setValue(Integer.valueOf(1));
textfield.setColumns(10);
JButton add = new JButton("Add");
add.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (textfield.getValue() != null) {
addTextFieldsToPanel((Integer) textfield.getValue(), textfieldContainerPanel);
}
}
});
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEADING));
panel.add(nrOfGuests);
panel.add(textfield);
panel.add(add);
frame.add(panel, BorderLayout.NORTH);
frame.add(new JScrollPane(textfieldContainerPanel));
frame.setSize(300, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
protected void addTextFieldsToPanel(Integer value, JPanel textfieldContainerPanel) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridheight = 1;
for (int i = 0; i < value; i++) {
textfieldContainerPanel.add(new JTextField(20), gbc);
}
textfieldContainerPanel.revalidate();
textfieldContainerPanel.repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestDynamicallyAddedTextFields().initUI();
}
});
}
}
And the result: