JLabel containing an ImageIcon won't repaint - java

I'm writing an application that creates a deck of cards in a random order and when a button is pressed moves the top card to the bottom and shows the new top card. (It's to simulate a Planechase deck to those familiar with Magic: the Gathering.) When the button is pressed it is properly cycling through the image files, but when I assign an image to a JLabel with an ImageIcon I can't get the JLabel to refresh with the new image. Here's the code I'm using to refresh
nextCardButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
planechase.topCardIncrement();
createCardToDisplay();
}
});
planechase is an instance of a class CardDeck which stores the randomized deck and has several methods to shuffle, change cards, etc. topCardIncrement() changes the top card to the next in the list.
private void createCardToDisplay()
{
cardToDisplay = new JLabel(new ImageIcon(planechase.getFolderName() + "\\" + planechase.displayTopCard()));
}
createCardToDisplay assigns cardToDisplay to an image derived from the folder name of the images and the current file. cardToDisplay is placed within JPanel contentPanel which is placed within JFrame frame. I can't figure out the proper way to repaint/revalidate (I'm not quite clear on what the difference is) my GUI to reflect the updated image. I've confirmed via System.out.println calls that
planechase.getFolderName() + "\\" + planechase.displayTopCard()
is updating as it should, so I assume that the JLabel is being reassigned properly. What is the proper way to redraw this so that it reflects the new ImageIcon?

The code is ambiguous...
The first thing that jumps out at me is...
private void createCardToDisplay()
{
cardToDisplay = new JLabel(new ImageIcon(planechase.getFolderName() + "\\" + planechase.displayTopCard()));
}
This is creating a new instance of cardToDisplay, but is it been added anywhere? Is the previous instance been removed? There's no context to be certain.
Normally, when you want to change the icon of a JLabel, you would simply call setIcon on the instance of the JLabel...
cardToDisplay.setIcon(new ImageIcon(planechase.getFolderName() + "\\" + planechase.displayTopCard()));
Because this is a bound field, it will trigger a repaint request automatically.

Related

How do I assign numbers a graphic to be shown in a JLabel

I am creating a higher or lower card game, and currently, it generates a random number from 1 to 13 as just a simple string label (1,2,3,4 etc), depending on what number gets pulled.
Instead of this, I would like to show a graphic of the card corresponding to the number.
public int getRandomNumber(){
Random r = new Random();
int nr = r.nextInt(13);
return nr;
}
...
JLabel label = new JLabel(getRandomNumber(), JLabel.CENTER);
To Update Label text you can use this method
public void updateLabel(int nr){
label.setText(nr+"");
//place this method inside your Jframe class extend from javax.swing.Jframe
}
If you want to put an image according to the number. Supose you have an array of 13 images(numbers)//Image images[13];
then you can use this
public void setIcon(int nr){
ImageIcon icon = new ImageIcon(images[nr]);
label.setIcon(icon);
}
I think that what you are looking for is adding an Icon to a JLabel.
You can do that using the setIcon method which accept any implementation of Icon, as for instance ImageIcon.
Something like the following should work:
ImageIcon imgIcon = new ImageIcon(URL_OF_THE_PIC));
jLabel.setIcon(imgIcon);
and whenever a new card gets picked you can change text and Icon accordingly.

Display a set of images inside Netbeans JFrame

I know how to display the images in separate JFrames.
public static void displayImage(BufferedImage img) {
JFrame f = new JFrame();
f.add(new JLabel(new ImageIcon(img)));
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
But I want a method to display all the images in a single JFrame(or in a suitable element), So I can shift between the images using two buttons("Next" and "Previous").
actually you don't need a multiple frame for this.you don't need even multiple jpanels .just a single jlable is sufficient .
all you need to do is change image of jlable when button press .
1) put your images in a directory and give a name .names should have pattern
example
C:\Users\Madhawa.se\Desktop\images\i1.jpg
C:\Users\Madhawa.se\Desktop\images\i2.jpg
C:\Users\Madhawa.se\Desktop\images\i3.jpg
C:\Users\Madhawa.se\Desktop\images\i4.jpg
C:\Users\Madhawa.se\Desktop\images\i5.jpg
2) declare a int variable as global
int i=0;
3) increase i by one when click next button and add appropriate image to label
i++;
ImageIcon imgThisImg = new ImageIcon("C:\\Users\\Madhawa.se\\Desktop\\images\\i"+i+".jpg");
jLabel1.setIcon(imgThisImg);
4) decrease i by one when click previous button and add appropriate image to label
i--;
ImageIcon imgThisImg = new ImageIcon("C:\\Users\\Madhawa.se\\Desktop\\images\\i"+i+".jpg");
jLabel1.setIcon(imgThisImg);
you can declare also String array which holds image paths .if your image names want to be arbitrary names .and then you can get image same way.
and also you should have a logic to correctly cycle images.you should restrict i to image quantity .otherwise image doesn't exist for i after i exceeded
output>>

How to add a JLabel to a JPanel in a different class and keep its set attributes.

I'm creating a card game in Java. I have a JPanel (actually a JLayeredPane) in my GUI class and JLabels containing the card images are added to it as they are dealt. These JLabels are generated in my Card class and called using a getImage() method. This method returns a JLabel like so:
public JLabel getImage(){
String theCardName = getName()+getSuit();
theCardName = theCardName.replaceAll("\\s+","");
image = new ImageIcon(getClass().getResource("Images\\"+theCardName+".png"));
cardImage = new JLabel(image,JLabel.CENTER);
return cardImage;
}
In my Gui class, I add the card to a JlayeredPane like this:
Card card = new Card();
jLayeredPane1.add(card.getImage(),new Integer(i));
i++ //this is just so each card is layered on top of the proceeding card.
Except I need to set the bounds for the label and would like to do that in the getImage() method. So I add this line to the getImage() method:
cardImage.setBounds(5, 5, 60, 100); //(The first parameter in that method actually gets incremented every time the methods is called so the cards get spread out, but that's irrelevant)
This does not work. These bound parameters do not seem to come with the label when it is returned to my Gui class.
What I had to do was this in the Gui class instead:
Card card = new Card();
JLabel label = card.getImage();
label.setBounds(5, 5, 60, 100);
jLayeredPane1.add(label,new Integer(i));
i++;
But I would prefer to set the bounds in the getImage() method for a number of reasons I won't go into. Why am I not able to or is there a way?

displaying images from an array in a gui window using swing in java

I am developing a program that will populate an array with 52 images of cards from a file. I would like to display these images in a gui window. This is for a program that will select five random card images and display them in a gui window. So, right now, i am trying to develop the part of the code which will display images from an array in a window and i am at a loss as to how to display png images in a jframe. This is the code i have so far. I used a system.out.println statement so i know that the array of 52 card images is populating correctly, however, i do not know how to display them properly in a window.
String[] cardsArray = new String[52];
for (int i = 0; i < 52; i++)
{
cardsArray[i] = "C:\\Users\\mike\\Documents\\NetBeansProjects\\card shuffler\\cards\\\"+String.valueOf(i+1)+".png";
}
System.out.println(Arrays.toString(cardsArray));
additional note. I have to use a jframe to display the results in a side by side layout. I thought to use flowLayout to accomplish this, but, i a not sure how to pass in an array of images. I have no problem doing it with a single image from a file. I am using the code below as a guide.
JFrame myJFrame = new JFrame();
// create and assign a FlowLayout for myFrame
myJFrame.setLayout(new FlowLayout());
// Create a label with an image icon
JLabel jlCSCI = new JLabel(new ImageIcon("CSCI.jpg"));
// add the Label to the frame
myJFrame.add(jlCSCI); // Add thelabel to MyGridLayout
// set the title, size, location and exit behavior for the frame
myJFrame.setTitle("ImageIcon Demo");
myJFrame.setSize(240, 200);
myJFrame.setLocation(200, 100);
myJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// make the frame visible (activate the GUI frame)
myJFrame.setVisible(true);
I am not sure how to develop the statement that would utilize an array that i created within the program.
Maybe like this?
for (String imgName : cardsArray)
{
myJFrame.add(new JLabel(new ImageIcon(imgName)));
}
Hope this helps.
EDIT:
I simply added a JLabel with an Icon to the frame. The ImageIcon class is just an implementation of the Icon interface and it creates an icon by reading an image from file. Creating a JLabel with an Icon will display the icon instead of the text. You can also combine the text and the icon. For more info, check the documentation.

Refreshing display of a text panel in a GUI

I'm having more "I'm hopeless at programming" problems.
I have a piece of code which uses StringBuilder to display elements of an array in a text panel of a GUI when the program starts. Here's the StringBuilder code:
// memory tab
StringBuilder mList = new StringBuilder();
memLocList = new Memory[MEM_LOCATIONS];
mem = new Memory();
for (int i = 0; i < memLocList.length; i++) {
memLocList[i] = mem;
memLocList[i].setOpCode(00);
mList.append(String.format("%10s %04x %10s %6s", "Address: ", i,
"Value: ", memLocList[i].getOpCode()));
mList.append("\n");
}
JComponent memTab = makeTextPanel(mList.toString());
tabs.addTab("Memory", new JScrollPane(memTab));
}
protected JComponent makeTextPanel(String t) {
text = t;
JPanel panel = new JPanel(false);
JTextPane filler = new JTextPane();
filler.setFont(new Font("Courier", Font.PLAIN, 14));
filler.setText(text);
filler.setAlignmentX(LEFT_ALIGNMENT);
panel.setLayout(new GridLayout(1, 1));
panel.add(filler);
return panel;
}
The GUI also has a text entry panel where a String of hex values can be entered.
On clicking a button, the user is prompted for another value, which corresponds to the position in the array where the first hex value should be inserted.
Once these values have been entered, I'd like the display to be updated / refreshed to reflect this but am unsure of how to go about it.
I found this question here, which is similar but I'm not sure if implementing Observer/Observable pattern is the right way to proceed, and even if it is, how I'd go about it:
Best Way to Constantly Update GUI Elements
My initial approach was to add an "updateDisplay()" method, which I could call after processing the button click and re-call the makeTextPanel method:
public void updateDisplay() {
makeTextPanel(text);
}
I thought this might refresh it but it has no effect of the display.
Any help appreciated.
You hold your array in a model class, and you allow other classes to "listen" to this by giving this class a SwingPropertyChangeSupport object as well as an addPropertyChangeListener(...) method. Then give the array a setXXX(...) method, and in that method fire the SwingPropertyChangeSupport object after updating the array. There are examples of just this sort of thing on this site, some written by me.
For example: here, here, here, ...
By the way, I'm not surprised that your call to makeTextPanel(text) doesn't work. It creates a JPanel, but you don't appear to do anything with the JPanel that is returned from the method. But nor should you. I don't think that creating new JPanels is the solution you want, but rather updating the Strings displayed by a component of some sort such as a JList or JTextArea using the listener framework that I've described above.
If any of this is confusing, please ask for clarification.

Categories