I already checked this duplicate question and other similar ones and it didn't help. I am trying to add an png to a button when it is clicked. The program is a variable sized tic-tac-toe game for school.
Right now I have:
private ImageIcon X_MARK = new ImageIcon("x.png");
private ImageIcon O_MARK = new ImageIcon("o.gif");
private JButton[][] cells;
...
cells = new JButton[size][size];
JPanel board = new JPanel(new GridLayout(size, size));
board.setBorder(new LineBorder(Color.BLACK, 1));
ButtonListener listener = new ButtonListener();
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++) {
cells[i][j] = new JButton();
cells[i][j].addActionListener(listener);
board.add(cells[i][j]);
}
JFrame ttt = new JFrame();
ttt.add(board);
ttt.setTitle("Show GUI Components");
ttt.setSize(60*size, 60*size);
ttt.setLocation(0, 0);
ttt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ttt.setVisible(true);
...
class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int i, j;
for (i = 0; i < size; i++)
for (j = 0; j < size; j++)
if (e.getSource() == cells[i][j]) {
if ((i + j) % 2 == 0) {
cells[i][j].setBackground(Color.GREEN);
cells[i][j].setIcon(X_MARK);
} else {
cells[i][j].setBackground(Color.CYAN);
cells[i][j].setIcon(O_MARK);
}
}
}
}
That is all the relevant code I think. I am using Eclipse and I have x.png and o.png in the src folder and the bin folder of the the project. I have also tried a couple of variants I have seen on SO and google searches like, new ImageIcon("C:/Users/BigBoy/workspace_1/EventDriven/src/x.png");, new ImageIcon("src/x.png");, and some other ones involving getClass().getResource among other things. I don't know what else to try. I know I've done this in the past and didn't have this much trouble.
I added .setBackground(Color.GREEN); just to make sure my clicks were registering properly and they are, the problem to me seems to be with the declaring/initializing of the ImageIcon.
NOTE: Right now my button listener just makes the checker board pattern, I will get to actually putting each player's mark after I figure out this icon problem.
You need to understand resources which is what you will want to use. They are located relative to the class files. If the images are with the class files, then
get your image as a resource
Create an ImageIcon from the Image.
i.e., something like:
package whateverpackeyouareusing;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
public class DefaultFoo {
public static void main(String[] args) throws IOException {
String resource = "x.png";
URL url = Class.class.getResource(resource);
BufferedImage img = ImageIO.read(url);
Icon icon = new ImageIcon(img);
JOptionPane.showMessageDialog(null, icon);
}
}
Edit: A better example per Andrew Thompson:
package some.package;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
public class PlayWithImages {
public static final String X_RESOURCE = "x.png";
private Icon xIcon;
public PlayWithImages() throws IOException {
URL xImgUrl = getClass().getResource(X_RESOURCE);
Image xImg = ImageIO.read(xImgUrl);
xIcon = new ImageIcon(xImg);
}
public Icon getXIcon() {
return xIcon;
}
public static void main(String[] args) {
try {
PlayWithImages playWithImages = new PlayWithImages();
Icon xIcon = playWithImages.getXIcon();
JOptionPane.showMessageDialog(null, xIcon);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Related
when I execute this segment of code it displays a grid of buttons out of which only the one at the bottom corner of the grid works while others do not. When you click on a button it will turn green meaning it's selected and if you click on it again it will become white meaning deselected. I want to make a cinema theater seat booking system in which the user will select their own seat. I cant figure out why the others aren't working.
Can anyone help me out?
import javax.swing.*;
import java.io.IOException;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;
import java.awt.Color;
import javax.swing.border.LineBorder;
import javax.swing.border.Border;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import java.io.File;
class cinemaSeats extends JFrame implements ActionListener {
private JButton[] bt = new JButton[1];
static int c=4;
static int k=5;
public cinemaSeats() throws IOException{
this.setSize(100, 100);
this.setLayout(null);
for(int s=0;s<=10;s++,k+=30)
{
c=4;
for(int j=1;j<=10;j++,c+=30)
{
for (int i = 0; i < bt.length; i++) {
bt[i] = new JButton("");
this.add(bt[i]);
bt[i].setBackground(Color.WHITE);
bt[i].addActionListener(this);
bt[i].setBounds(c,k,30,30);
}
}
}
this.setVisible(true);
this.pack();
this.setSize(new Dimension(3400,735));
}
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < bt.length; i++) {
if (e.getSource() == bt[i]) {
if(bt[i].getBackground() == Color.GREEN){
bt[i].setBackground(Color.WHITE);
}else if(bt[i].getBackground() == Color.WHITE){
bt[i].setBackground(Color.GREEN);
}else{
bt[i].setBackground(Color.WHITE);
}
}
}
}
}
public class cinemaSeat1 {
public static void main()throws IOException {
cinemaSeats bcts = new cinemaSeats();
}
}
Your bt array has length 1. Even though you're creating multiple JButton you keep a reference only to one of them (the last one created).
Because of that, when you get to actionPerformed the if (e.getSource() == bt[i]) condition will be true only when the last button created is pressed.
You will have to keep references to all the buttons or you could do something like this:
public void actionPerformed(ActionEvent e) {
JButton pressedButton = (JButton)e.getSource();
if(pressedButton.getBackground() == Color.GREEN){
pressedButton.setBackground(Color.WHITE);
}else if(pressedButton.getBackground() == Color.WHITE){
pressedButton.setBackground(Color.GREEN);
}else{
pressedButton.setBackground(Color.WHITE);
}
}
Hello I'm trying to do a ratsuk game that is chess but only with the knight.
import javax.swing.JButton;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.Icon;
import javax.swing.ImageIcon;
public class Knight {
private Icon image;
private int w;
private int k;
private Random rand;
public Knight() {
image = new ImageIcon(getClass().getResource("redKnight.gif"));
w = rand.nextInt(9);
k = rand.nextInt(9);
}
public void Caballo(JButton[][] matriz, int i, int j) {
matriz[i][j].setIcon(image);
matriz[i][j].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Execute when button is pressed
matriz[i][j].setBackground(Color.RED);
}
});
}
}
So I was trying to do a recursive method which I am not really sure will work.
But the problem is that inside the addActionListener, netbeans tells me that the variables have to be final which I don't really get why. Once I run it the image doesn't show at all
Here is the rest of the code
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.*;
import javax.swing.JPanel;
import java.util.Random;
public class Tablero {
private JButton[][] mesa;
private Random rad;
public Tablero() {
mesa = new JButton[8][8];
}
public void cuadriculado(JFrame ventana) {
JPanel panel = new JPanel(new GridLayout(8, 8, 0, 0));
for (int i = 0; i < mesa.length; i++) {
for (int j = 0; j < mesa[0].length; j++) {
mesa[i][j] = new JButton();
mesa[i][j].setPreferredSize(new Dimension(40, 40));
panel.add(mesa[i][j]);
}
}
for (int r = 0; r < mesa.length; r++) {
for (int t = 0; t < mesa[0].length; t++) {
if (r % 2 == 0 || r == 0) {
if (t % 2 == 0 || t == 0) {
mesa[r][t].setBackground(Color.BLACK);
} else {
mesa[r][t].setBackground(Color.WHITE);
}
} else {
if (t % 2 == 0 || t == 0) {
mesa[r][t].setBackground(Color.WHITE);
} else {
mesa[r][t].setBackground(Color.BLACK);
}
}
}
}
ventana.setContentPane(panel);
ventana.setSize(500, 500);
ventana.setVisible(true);
Knight kn =new Knight();
kn.Caballo(mesa, rad.nextInt(9), rad.nextInt(9));
}
}
Any help will greatly appreciated. I am really new to Java and none of this was explained to me, so I have been struggling a lot.
matriz[i][j].setBackground(Color.RED);
You are trying to access "matriz" from an annonymous inner class so the variable needs to either be a class variable or a final variable.
I would question why you made this method belong to the Knight class. This method should be part of the Tablero class since that is where you define the array as a class variable. Then you won't have the compiler problem.
But if you really want to keep the method in the Knight class then the code should be:
public void Caballo(**final** JButton[][] matriz, int i, int j) {
Once i run it the image doesnt show at all
image = new ImageIcon(getClass().getResource("redKnight.gif"));
You just create an Icon. You need to add it to a label and then add the label to the GUI.
i am really new to java and nothing of this was explained to me
Start by reading the Swing tutorial. Maybe the section on How to Use Icons would be a good place to start.
Try changing this
public void Caballo(JButton[][] matriz, int i, int j)
to this
public void Caballo(final JButton[][] matriz, final int i, final int j)
The reason the variables need to final is because they are accessed inside the ActionListener's actionPerformed. Java needs to know that these variables arent going to change before it gets to use them. It goes back to a Java Garbage collector thing that I would prefer not ramble on about, but that's the jest of it.
Okay I have tried different ways but I can not get the button to change into an image. I know the file source is right because when I upload it as just an image it works fine. Here's my code:
ImageIcon start = new ImageIcon("start.png");
button = new JButton (start);
add(button);
My whole code
import java.awt.AWTException;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.WritableRaster;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class UnfollowGUI extends JFrame{
private JLabel label;
private JButton button;
private ImageIcon bgi;
private JLabel bgl;
public static Rectangle gameSquare;
public static boolean rock = true;
public static boolean runningMine = true;
public static int stray = 0;
public static int strayCount = 0;
public static void main(String[] args) {
UnfollowGUI gui = new UnfollowGUI ();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // when click x close program
//gui.setSize(886, 266);
gui.pack();
gui.setVisible(true);
gui.setTitle("Solid Cloud Inc - Twitter Unfolower");
}
public UnfollowGUI(){
setLayout(new FlowLayout());
bgi = new ImageIcon(getClass().getResource("tu.png"));
bgl = new JLabel (bgi);
add(bgl);
ImageIcon start = new ImageIcon("start.png");
button = new JButton (start);
add(button);
label = new JLabel ("");
add(label);
Events e = new Events();
button.addActionListener(e);
}
public class Events implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button) {
label.setText("Searching");
try {
Unfollow();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
public static void Unfollow() throws InterruptedException{
if (rock==true){
runningMine = true;
}
if (strayCount >=2){
runningMine = false;
stray = 90000000;
JOptionPane.showMessageDialog(null, "Program Ended");
System.out.println("Program ended");
}
//System.out.println("look iron start");
try {
Robot robot = new Robot();
while(runningMine == true){
//while (rock == true)
//System.out.println("searching");
gameSquare = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); //== game square
BufferedImage img = robot.createScreenCapture(gameSquare);
WritableRaster r = img.getRaster();
DataBuffer db = r.getDataBuffer();
DataBufferInt dbi = (DataBufferInt)db;
int[] data = dbi.getData();
for (int x_scale = 0; x_scale < gameSquare.width; x_scale += 1) {
for(int y_scale = 0; y_scale < gameSquare.height; y_scale += 1) {
int rgb = data[x_scale + gameSquare.width * y_scale];
if (stray < 10000000){ // 2 sec
if ( rgb == -15817767){ //finds unfollow
if (runningMine == true){
runningMine = false;
stray = 0;
int xRock = gameSquare.x + x_scale; // sets the x and y of the point
int yRock = gameSquare.y + y_scale;
robot.mouseMove(xRock, yRock);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
Thread.sleep(800);
strayCount = 0;
Unfollow();
//System.out.println("clicked on Rock");
}
}
else{
stray ++;
//lookIron();
}
}
else if ((stray>=10000000)&&(stray <20000000)){
//skillScreen();
//System.out.println("no unfollow buttons");
robot.mouseMove(1359, 704);
Thread.sleep(500);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
Thread.sleep(1000);
stray = 0;
strayCount ++;
Unfollow();
}
}
}
}
}
catch(AWTException e) {
e.printStackTrace();
}
}
}
I would get the button's ImageIcon the same way that you get the Icon for the JLabel. So rather than
ImageIcon start = new ImageIcon("start.png");
You'd do:
ImageIcon start = new ImageIcon(getClass().getResource("start.png"));
button = new JButton (start);
Assuming that the start.png image is located with the class files, same as the tu.png image.
This bit of code worries me:
try {
Robot robot = new Robot();
while(runningMine == true){
//....
}
As it looks like it will tie up the Swing Event Dispatch Thread (or EDT), freezing your application. Should that code be run in a background thread such as with a SwingWorker?
Make the picture size smaller i.e equal to the size of your button and you'll get the image on your button.
Hope that It will helps.
I am having a bit of problem with changing and Icon in a JLabel dynamically. First of all, what i am trying to do is basically simulating a screen sharing operation. On the client side, I am taking screenshots every second, sending them to the server. On the server side, I am trying to open these pictures in a simple GUI.
I am able to send the pictures without problem and I am also able to get them without problem as well. However, the GUI code I have written cannot open the pictures. More specifically, If there is a picture, it is able to open it, but it does not open another picture that has come.
What I am doing in the server side is, as soon as a picture gets to the server, I am saving it with a predetermined name. And then I am able to open the picture with Windows' own picture photo viewer. In fact, as soon as a new picture comes, photo viewer updates itself and shows the new screenshot.
However, I am having trouble opening the screenshots in a JFrame. I have written a program to take the screenshots in jpg format, send them to the server and then open them in a GUI. however i am having problems with the opening in the GUI part. From what I have understood, it does not open the files that are coming by from the client.
Below are my codes, any help will be much appreciated.
Server side,
package ScreenCap;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import FileServer.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import test.TsgIcons;
/**
*
* #author busra
*/
public class ScreenCapServer extends Thread{
String filePath;
int portNumber;
FileServer screenCapServer;
ServerSocket getFileServer;
Socket getFile;
InputStream in;
FileOutputStream fileOutputStream;
TsgIcons screenShotIcons;
public ScreenCapServer(String path, int port) {
this.filePath = path;
this.portNumber = port;
this.screenShotIcons = new TsgIcons();
}
public static void waitTime(long millisecond){
long max = millisecond;
for(long i = 0; i < max; i++){
for(long j = 0; j < max; j++){
}
}
}
public void run() {
while(true) {
try {
for(int i = 0; i < 10; i++) {
getFileServer = new ServerSocket(portNumber);
getFile = getFileServer.accept();
in = getFile.getInputStream();
fileOutputStream = new FileOutputStream(filePath + "\\" + i + ".jpg");
byte [] buffer = new byte[64*1024];
int bytesRead = 0;
while ( (bytesRead = in.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, bytesRead);
}
in.close();
fileOutputStream.close();
getFileServer.close();
screenShotIcons.update();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
GUI,
package test;
import java.awt.BorderLayout;
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.Timer;
public class TsgIcons extends JFrame implements ActionListener {
protected Timer timer;
protected JLabel viewIcon;
private String[] SMILEY = {"orig_screen"};
private String BUTTON = "Button";
private int timeCount;
private int iconNumber;
private String image;
public TsgIcons() {
this(1, 100);
}
public TsgIcons(int initialTime, int delay) {
super("TSG Smileys");
this.timeCount = initialTime;
this.iconNumber = this.timeCount % this.SMILEY.length;
this.image = "TransferredScreenShots\\" + this.SMILEY[this.iconNumber] + ".jpg";
this.viewIcon = new JLabel();
this.viewIcon.setIcon(new javax.swing.ImageIcon(this.image));
this.timer = new Timer(delay, this);
this.init();
}
protected void init() {
JButton button = new JButton("Start / Stop");
button.setActionCommand(BUTTON);
button.addActionListener(this);
this.viewIcon.setHorizontalAlignment(JLabel.CENTER);
this.getContentPane().add(button, BorderLayout.SOUTH);
this.getContentPane().add(this.viewIcon, BorderLayout.CENTER);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocation(250, 250);
this.pack();
this.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if ( BUTTON.equals(e.getActionCommand()) ) { // test if the button clicked
if ( this.timer.isRunning() ) {
this.timer.stop();
} else {
this.timer.start();
}
} else
{ this.timeCount++;
this.iconNumber = this.timeCount % this.SMILEY.length;
this.image = "TransferredScreenShots\\" + this.SMILEY[this.iconNumber] + ".jpg";
this.viewIcon.setIcon(new javax.swing.ImageIcon(this.image));
}
}
public void update() {
this.timeCount++;
this.iconNumber = this.timeCount % this.SMILEY.length;
this.image = "TransferredScreenShots\\" + this.SMILEY[this.iconNumber] + ".jpg";
this.viewIcon.setIcon(new javax.swing.ImageIcon(this.image));
}
public static void main(String argv []) {
new TsgIcons();
}
}
I have a simple puzzle game. There is an image consisting of 16 tiles (randomly placed). Images are stored in an array and when game is launched they're added to main JPanel.
Game works in this way : Each image has atributes 'place' and 'number'. 'Place' is the current place on grid (either correct or not) and 'number' is the desired place for the image. When a user clicks image their 'place' and 'number' attributes are checked. If they match nothing happens. If not game checks if any image is currently in memory. If there is none, then this image's 'place' and 'number' are stored. If there is some image in memory, then the currently clicked image's 'plac'e is checked with stored image's 'number'. When they match - their places are exchanged. This part works properly. But now, I'm calling addComponent method on my JPanel with updated images and simply nothing happens. Shouldn't the new images be added to JPanel replacing the old ones ?
package Bonus;
import javax.swing.*;
import java.util.Random;
import java.awt.event.*;
import java.awt.*;
class Puzzle extends JPanel implements ActionListener {
private int selected_nr=-1;
private int selected_pl=-1;
private boolean memory=false;
private static Img[] images;
public Puzzle(){
JFrame f = new JFrame("Smile");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.setSize(252,252);
f.setVisible(true);
setLayout(new GridLayout(4, 4));
images = new Img[16];
int[] buttons = new int[16];
for(int i=0; i<16; i++){
buttons[i] = i;
}
int rand;
int temp;
Random random;
random = new Random(System.currentTimeMillis());
for (int i = 0; i < buttons.length; i++) {
rand = (random.nextInt() & 0x7FFFFFFF) % buttons.length;
temp = buttons[i];
buttons[i] = buttons[rand];
buttons[rand] = temp;
}
for (int i = 0; i < 16; i++) {
images[i] = new Img(i, buttons[i]);
}
addComponents(images);
}
public void addComponents(Img[] im){
this.removeAll();
for(int i=0; i<16; i++){
im[i].addActionListener(this);
im[i].setPreferredSize(new Dimension(53,53));
add(im[i]);
}
this.validate();
}
public void actionPerformed(ActionEvent e) {
Img b = (Img)(e.getSource());
int num = b.getNumber();
int pl = b.getPlace();
if(!(b.rightPlace())){
if(memory){
if(pl == selected_nr){
images[pl].setPlace(selected_pl);
images[selected_pl].setPlace(selected_nr);
selected_nr = -1;
selected_pl = -1;
memory = false;
addComponents(images);
}
else{
System.out.println("Try other image");
}
}
else{
memory = true;
selected_nr = num;
selected_pl = pl;
}
}
else{
System.out.println("OK !");
}
}
public static void main(String args[]) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Puzzle();
}
});
}
}
class Img extends JButton {
int number;
int place;
ImageIcon img;
public Img(int p, int n){
number = n;
place = p;
img = new ImageIcon("u"+number+".jpg", BorderLayout.CENTER);
setIcon(img);
}
public boolean rightPlace(){
boolean correct=false;
if(number == place){
correct = true;
}
return correct;
}
public void setPlace(int i){
place = i;
}
public int getNumber(){
return number;
}
public int getPlace(){
return place;
}
}
EDIT: Changed the code to use the answers, but still no luck. addComponents() gets updated images[] but doesn't revalidate them.
Rather than relying on precut image files, here's an example of slicing an existing image and shuffling the resulting pieces. It combines the helpful (+1) suggestions of both #Frederick and #akf.
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ImageLabelPanel extends JPanel implements ActionListener {
private static final int N = 4;
private final List<JLabel> list = new ArrayList<JLabel>();
private final Timer timer = new Timer(1000, this);
ImageLabelPanel() {
this.setLayout(new GridLayout(N, N));
BufferedImage bi = null;
try {
bi = ImageIO.read(new File("image.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
int w = bi.getWidth() / N;
int h = bi.getHeight() / N;
BufferedImage b = bi.getSubimage(c * w, r * h, w, h);
list.add(new JLabel(new ImageIcon(b)));
}
}
createPane();
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setVisible(true);
timer.start();
}
private void createPane() {
this.removeAll();
for (JLabel label : list) add(label);
this.validate();
}
#Override
public void actionPerformed(ActionEvent e) {
Collections.shuffle(list);
createPane();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ImageLabelPanel();
}
});
}
}
You are adding all of your components again to your JPanel without actually removing any of them. In your addComponents() method, I would first call removeAll(). You might want to rename that method to highlight the side-effects, as it no longer would only be adding components. Perhaps, resetComponents() would be better.
After changing the components, you need to 'refresh' the Swing component by calling invalidate() or revalidate().