How do I update a JLabel in a JPanel? - java

I am having trouble getting the image on my JLabel to update in the JPanel. I do not see what the problem is. I have tried removing the existing JLabel and adding a new one to the JPanel but that doesn't work. Here is the code I am trying to get the animaiton to work on. My key listener works fine so I am sure there is some problem in this class:
import javax.swing.*;
import java.awt.event.*;
public class Character extends JPanel{
//Constructs array that holds running frames
static ImageIcon running[] = new ImageIcon[19];
static int i = 0;
//Contstructs label that holds the current image frame
static JLabel characterLabel = new JLabel();
//Creates imageicon to be returned to the character and stored in characterLabel
static ImageIcon character = new ImageIcon();
Timer runningTimer = new Timer(300, new RunningListener());
public Character() {
running[0] = new ImageIcon("running 1.png");
running[1] = new ImageIcon("running 2.png");
running[2] = new ImageIcon("running 3.png");
running[3] = new ImageIcon("running 4.png");
running[4] = new ImageIcon("running 5.png");
running[5] = new ImageIcon("running 6.png");
running[6] = new ImageIcon("running 7.png");
running[7] = new ImageIcon("running 8.png");
running[8] = new ImageIcon("running 9.png");
running[9] = new ImageIcon("running 10.png");
running[10] = new ImageIcon("running 11.png");
running[11] = new ImageIcon("running 12.png");
running[12] = new ImageIcon("running 13.png");
running[13] = new ImageIcon("running 14.png");
running[14] = new ImageIcon("running 15.png");
running[15] = new ImageIcon("running 16.png");
running[16] = new ImageIcon("running 17.png");
running[17] = new ImageIcon("running 18.png");
running[18] = new ImageIcon("running 19.png");
characterLabel.setIcon(running[0]);
this.add(characterLabel);
}
private void refreshCharacter(){
this.remove(characterLabel);
characterLabel.setIcon(running[i]);
this.add(characterLabel);
i++;
if (i > 18){
i = 0;
}
}
private class RunningListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
refreshCharacter();
}
}
}
I suppose that this JPanel may be the problem aswell but I doubt it:
import javax.swing.*;
//Panel that manages the game
public class GamePanel extends JPanel{
//Adds stuff to GamePanel to send to Frame
public GamePanel(){
this.addKeyListener(new KeyInput());
this.add(new Character());
}
}
Here is the key listener:
import java.awt.event.*;
//Listens for key actions
public class KeyInput implements KeyListener{
//Constructs character
Character c = new Character();
public void keyPressed(KeyEvent evt) {
int key = evt.getKeyCode();
//When the right key is pressed, start the timer that starts the running animation
if(key == KeyEvent.VK_RIGHT){
c.runningTimer.start();
}
}
public void keyReleased(KeyEvent evt){
int key = evt.getKeyCode();
//When the right key is released, the timer that starts the running animation is stopped
if(key == KeyEvent.VK_RIGHT){
c.runningTimer.stop();
}
}
//There is no use for this... it just has to be there
public void keyTyped(KeyEvent evt){
}
}
and here is the frame:
import javax.swing.*;
public class Frame{
//Creates window and calls to GamePanel
public static void main (String[]args){
GamePanel gamePanel = new GamePanel();
JFrame window = new JFrame("Game");
window.add(gamePanel);
window.setLocation(50,50);
window.setSize(1000,650);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
gamePanel.requestFocus();
}
}

If you're trying to change a displayed image, if you can avoid it, don't remove JLabels or components, but rather swap a JLabel's Icon. If you're not trying to change an image, but do something different, then please give us more detail on your desired behavior, since all you tell us is that you're trying "animation", and that's somewhat broad.
e.g.,
private void refreshCharacter() {
i++;
i %= running.length;
characterLabel.setIcon(running[i]);
}

Related

How to move and change the size of a Jpanel rectangle?

I have a rectangle, and I am trying to grow it like a graph of some sorts, but it does not show it growing in real time, it just has a white screen then I see a rectangle. Any help would be appreciated, thanks. The code I am having a problem with is under the ¨Animates the bar¨ comment.
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Main extends JPanel {
static String[] mainArr;
static int start;
static boolean done = false;
static double datapoint1;
static double datapoint2;
static int jPlaceholder;
public static void main(String[] args) throws Exception {
// Creating the window
JFrame panel = new JFrame();
panel.setSize(450,250);
// Creating the window that shows the animation
JFrame drawingFrame = new JFrame();
drawingFrame.setSize(450,250);
JPanel jp = new JPanel();
jp.setLayout(null);
jp.setBackground(Color.red);
drawingFrame.add(jp);
// Creating all the text fields
JTextField dataTypesTextField = new JTextField("This box is currently not in use. Please do not type anything into this box");
dataTypesTextField.setBounds(50,50, 400,30);
panel.add(dataTypesTextField);
JTextField yearStartTextField = new JTextField("Type in this box what year your data starts in:");
yearStartTextField.setBounds(50,100, 400,30);
panel.add(yearStartTextField);
JTextField yearEndTextField = new JTextField("Type in this box what year your data ends in:");
yearEndTextField.setBounds(50,150, 400,30);
panel.add(yearEndTextField);
// Creating the button to submit the data
JButton enterButton = new JButton("Enter");
enterButton.setBounds(50,200, 100, 30);
panel.add(enterButton);
// =================================== ActionListener for enter button ========================================
enterButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (done==false) {
// Creating the variables to store the data the user just inputted
start = Integer.parseInt(yearStartTextField.getText());
int end = Integer.parseInt(yearEndTextField.getText());
mainArr = new String[end-start+1];
// Gets the data points
dataTypesTextField.setText("Datapoints you will use in order, space between each: ");
done = true;
} else {
// Getting all the data needed
mainArr = dataTypesTextField.getText().split(" ");
double[] datapoints = new double[mainArr.length];
for (int i=0; i<datapoints.length; i++) {
datapoints[i] = Double.parseDouble(mainArr[i]);
}
under here is where I had my problems I am pretty sure, but I could have screwed up somewhere else.
// Animates the bar
for (int i=0; i<datapoints.length-1; i++) {
// Getting all the datapoints
datapoint1 = datapoints[i];
datapoint2 = datapoints[i+1];
int j = 0;
while(j<50) {
j++;
int width = (int) (datapoint1+((datapoint2-datapoint1)/50)*j);
JPanel rectangle = new JPanel();
rectangle.setBackground(Color.black);
rectangle.setBounds(50, 50, width, 30);
jp.add(rectangle);
drawingFrame.setVisible(true);
rectangle.repaint();
System.out.println("The width is: "+width);
at first I thought it was because there was no pause between each ¨frame¨ but it still just shows a white screen, then it shows the rectangle.
try {
Thread.sleep(20);
} catch (Exception exp) {
}
}
}
}
}
});
// =====================================================================================================
// Finishes up both the windows
panel.setLayout(null);
panel.setVisible(true);
}
}

Implementing freehand draw in a MVC Java Swing project

I'm currently working on a project that involves using the Model-View-Controller architecture, in the project I have to implement freehand drawing inside of a JPanel, however the panel.paintComponent(g) method doesn't seem to work.
In my view package I create the GUI and give each object a getter, my controller class creates a GUI and uses these getters to instantiate the JPanels, JButtons etc. The Drawing model is passed the JPanel I want to draw on, as seen below.
public class Editor extends JPanel implements MouseListener, MouseMotionListener {
private int index = 0;
private Point[] arr = new Point[100000];
private JPanel xPanel = new JPanel();
Updater upDate = new Updater();
public void getPanel(JPanel dPanel)
{
xPanel = dPanel;
xPanel.addMouseListener(this);
xPanel.addMouseMotionListener(this);
xPanel.setBackground(Color.white);
}
public void paintComponent(Graphics g)
{
System.out.println("Got to this point");
xPanel.paintComponents(g);
for(int i = 0; i < index - 1; i++)
{
System.out.println("And here 2");
g.drawLine(arr[i].x, arr[i].y, arr[i+1].x, arr[i+1].y);
System.out.println("And here 3");
}
}
#Override
public void mousePressed(java.awt.event.MouseEvent e) {
arr[index] = new Point(e.getX(), e.getY());
index++;
System.out.println(index);
upDate.update(xPanel);
}
#Override
public void mouseDragged(java.awt.event.MouseEvent e) {
arr[index] = new Point(e.getX(), e.getY());
index++;
System.out.println(index);
upDate.update(xPanel);
}
My Controller class looks like this.
private GUI view;
private JButton buttonLoad;
private JButton buttonZoom;
private JButton buttonDrag;
private JButton buttonSave;
private JButton buttonRotate;
private JButton buttonDraw;
private JMenuBar menuB;
private JPanel dPanel;
private MouseListener e;
Graphics g;
public Controller(GUI gui){
this.view = gui;
menuB = view.getMenu();
buttonLoad = view.getLoad();
buttonZoom = view.getZoom();
buttonRotate = view.getRotate();
buttonSave = view.getSave();
buttonDrag = view.getDrag();
buttonDraw = view.getDraw();
dPanel = view.getModel();
g = dPanel.getGraphics();
FunctionListener x = new FunctionListener();
MenuBarListener y = new MenuBarListener();
buttonLoad.addActionListener(x);
buttonZoom.addActionListener(x);
buttonRotate.addActionListener(x);
buttonSave.addActionListener(x);
buttonDrag.addActionListener(x);
buttonDraw.addActionListener(x);
//menuB.addMenuListener(y);
}
class FunctionListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource().equals(buttonZoom)){
Editor editor = new Editor();
editor.getPanel(dPanel);
editor.paintComponent(g);
}
It's worth noting that dPanel = view.getModel(); is a getter for a JPanel called Model in my GUI class. Everything seems to be working, the index of points is being returned properly yet there is no drawing, after running some simple System.out.println tests, I know that the code isn't entering the for loop in the Editor class.
Thanks for any help!

ListSelectionListener and CardLayout

I'm creating a program that reads data from a file, displays it on a GUI that has a JList and JButtons. I am trying to write it with CardLayout so the appropriate JPanel can be displayed when an item is selected from the JList or a JButton is clicked (i.e. next, previous, first and last). I am able to successfully read from the file and display data to the GUI. I've run into 2 problems and I've tried searching online for answers but cant seem to figure it out:
1) How do I get the JPanels to switch using CardLayout?
2) How do I get the data to be displayed in the GUI in text fields when a user clicks an item from the JList? The JList does appear and my ListSelectionListener is working because when I click on a particular item, it will print to the console (as a test).
If I comment out all of the JPanels except for 1, then it is correctly displayed but when I place all of them, then it does not switch.
So far, I have this for my ListSelectionListener (as an inner class):
public class CancerSelectionListener implements ListSelectionListener {
#Override
public void valueChanged(ListSelectionEvent e) {
Integer selection = (Integer)(((JList) e.getSource()).getSelectedIndex());
if(selection == 0) {
System.out.println("blah"); // works
// switch to the corresponding JPanel in CardLayout
}
}
}
String[] tester;
String teste;
listModel = new DefaultListModel();
for(int i = 0; i < 36; i++) {
tester = _controller.readCancer(i); // reads from the file, this part works!
teste = tester[0];
listModel.addElement(teste);
}
cancerList = new JList(listModel);
cancerList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
cancerList.setSelectedIndex(-1);
cancerList.setVisibleRowCount(5);
cancerListScroller = new JScrollPane(cancerList);
CardLayout myCardLayout;
myCardLayout = new CardLayout();
mainPanel2.setLayout(myCardLayout);
myCardLayout.show(mainPanel2, "test");
CancerPanels.aplPanel apl = new CancerPanels.aplPanel();
CancerPanels.fcPanels fc = new CancerPanels.fcPanels();
CancerPanels.vhlsPanels vhls = new CancerPanels.vhlsPanels();
CancerPanels.pdgPanels pdg = new CancerPanels.pdgPanels();
CancerPanels.cebpaPanels cebpa = new CancerPanels.cebpaPanels();
mainPanel2.add(apl.aplReturn(), "test");
mainPanel2.add(fc.fcReturn());
mainPanel2.add(vhls.vhlsReturn());
mainPanel2.add(pdg.pdgReturn());
mainPanel2.add(cebpa.cebpaReturn());
// I have 37 JPanels that are placed in the JPanel that uses CardLayout but I didn't post all of them as it would take up lots of space
The data for each JPanel is populated from static inner classes in the CancerPanels class (only showing 1 as each is very long!)
public class CancerPanels extends CancerGUI {
static JPanel cards;
static CancerController _cons = new CancerController();
static String[] cancerData;
static JScrollPane treatmentsScroller = new JScrollPane(txtTreatments, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
static JScrollPane causesScroller = new JScrollPane(txtCauses, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
static JScrollPane symptomsScroller = new JScrollPane(txtSymptoms, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
public static class aplPanel extends JPanel {
public JPanel aplReturn() {
treatmentsScroller.setViewportView(txtTreatments);
txtTreatments.setEditable(false);
causesScroller.setViewportView(txtCauses);
txtCauses.setEditable(false);
symptomsScroller.setViewportView(txtSymptoms);
txtSymptoms.setEditable(false);
cards = new JPanel(new GridLayout(6,1));
cancerData = _cons.readCancer(0);
resultName.setText(cancerData[0]);
txtSymptoms.setText(cancerData[1]);
txtCauses.setText(cancerData[2]);
txtTreatments.setText(cancerData[3]);
resultRate.setText(cancerData[4]);
resultPrognosis.setText(cancerData[5]);
cards.add(resultName);
cards.add(symptomsScroller);
cards.add(causesScroller);
cards.add(treatmentsScroller);
cards.add(resultRate);
cards.add(resultPrognosis);
return cards;
}
}
Edit:
Here is my most recent attempt. I can scroll through the JList but it doesn't properly display the correct corresponding JPanel (in fact it doesn't display anything, except whenever I click the last button, I don't know why that button works). I successfully managed to place an ItemListener on a JComboBox but ultimately, I want the CardLayout to work. Our instructor provided us with sample code to use but when I try it, the JPanels do not switch (or if they do they're hidden, not sure why).
Each of my listeners are public inner classes in the overall CancerGUI class.
public CancerGUI() {
CancerPanels.aplPanel apl = new CancerPanels.aplPanel();
CancerPanels.fcPanels fc = new CancerPanels.fcPanels();
CancerPanels.vhlsPanels vhls = new CancerPanels.vhlsPanels();
// more than 30 JPanels that I add to the JPanel that uses CardLayout, so I only posted 3
// each of them uses the GridLayout
mainPanel2 = new JPanel(new CardLayout());
mainPanel2.add(apl.aplReturn(), "1");
mainPanel2.add(fc.fcReturn(), "2");
mainPanel2.add(vhls.vhlsReturn(), "3");
CancerActionButtons _cab = new CancerActionButtons();
btnNext = new JButton("Next");
btnPrevious = new JButton("Previous");
btnFirst = new JButton("First");
btnLast = new JButton("Last");
btnClear = new JButton("Clear");
btnNext.addActionListener(_cab);
btnPrevious.addActionListener(_cab);
btnFirst.addActionListener(_cab);
btnLast.addActionListener(_cab);
CancerItemListener _item = new CancerItemListener(); // this listener works!
renalC.addItemListener(_item);
skinC.addItemListener(_item);
brainC.addItemListener(_item);
bladderC.addItemListener(_item);
ovarianC.addItemListener(_item);
pancC.addItemListener(_item);
breastC.addItemListener(_item);
String[] tester;
String teste;
listModel = new DefaultListModel();
for(int i = 0; i < 36; i++) {
tester = _controller.readCancer(i);
teste = tester[0];
listModel.addElement(teste);
}
cancerList = new JList(listModel);
cancerList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
cancerList.setSelectedIndex(-1);
cancerList.setVisibleRowCount(5);
cancerListScroller = new JScrollPane(cancerList);
ListSelection _list = new ListSelection();
cancerList.addListSelectionListener(_list);
JScrollPane treatmentsScroller = new JScrollPane(txtTreatments, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
treatmentsScroller.setViewportView(txtTreatments);
JScrollPane causesScroller = new JScrollPane(txtCauses, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
causesScroller.setViewportView(txtCauses);
JScrollPane symptomsScroller = new JScrollPane(txtSymptoms, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
symptomsScroller.setViewportView(txtSymptoms);
public class ListSelection implements ListSelectionListener {
#Override
public void valueChanged(ListSelectionEvent e) {
String selection = (String)(((JList)e.getSource()).getSelectedValue());
((CardLayout) mainPanel2.getLayout()).show(mainPanel2, selection);
((CardLayout) mainPanel2.getLayout()).show(mainPanel2, selection);
}
}
public class CancerActionButtons implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
switch(e.getActionCommand()) {
case "First":
((CardLayout) mainPanel2.getLayout()).first(mainPanel2);
cancerCount = 1;
break;
case "Last":
((CardLayout) mainPanel2.getLayout()).last(mainPanel2);
cancerCount = 11;
break;
case "Previous":
((CardLayout) mainPanel2.getLayout()).previous(mainPanel2);
cancerCount--;
cancerCount = cancerCount < 1 ? 11 : cancerCount;
break;
case "Next":
((CardLayout) mainPanel2.getLayout()).next(mainPanel2);
cancerCount++;
cancerCount = cancerCount > 11 ? 1 : cancerCount; //
break;
}
cancerList.setSelectedIndex(cancerCount-1);
}
}
/**
* Inner class that responds to any user interaction with a JComboBox for
* general types of cancers.
*/
public class CancerItemListener implements ItemListener {
#Override
public void itemStateChanged(ItemEvent e) {
JPanel showPanel = new JPanel();
if(e.getStateChange() == ItemEvent.SELECTED) {
String selection = (String) e.getItem();
if(selection.equalsIgnoreCase("skin cancer")) {
CancerPanels.skin skin = new CancerPanels.skin();
showPanel = skin.skinReturn();
} else if (selection.equalsIgnoreCase("bladder cancer")) {
CancerPanels.bladder bladder = new CancerPanels.bladder();
showPanel = bladder.bladderReturn();
} else if (selection.equalsIgnoreCase("pancreatic cancer")) {
CancerPanels.pancreatic pancreatic = new CancerPanels.pancreatic();
showPanel = pancreatic.returnPancreatic();
} else if (selection.equalsIgnoreCase("renal cancer")) {
CancerPanels.renal renal = new CancerPanels.renal();
showPanel = renal.returnRenal();
} else if (selection.equalsIgnoreCase("ovarian cancer")) {
CancerPanels.ovarian ovarian = new CancerPanels.ovarian();
showPanel = ovarian.ovarianReturn();
} else if (selection.equalsIgnoreCase("breast cancer")) {
CancerPanels.breast breast = new CancerPanels.breast();
showPanel = breast.returnBreast();
} else if (selection.equalsIgnoreCase("brain cancer")) {
CancerPanels.brain brain = new CancerPanels.brain();
showPanel = brain.returnBrain();
} else if (selection.equalsIgnoreCase("von hippel-lindau syndrome")) {
CancerPanels.vhlsPanels vhls = new CancerPanels.vhlsPanels();
showPanel = vhls.vhlsReturn();
}
JOptionPane.showMessageDialog(null, showPanel);
}
}
}
Seperate class where the JPanels are made before being added to CardLayout:
public class CancerPanels extends CancerGUI {
static String name;
static JPanel cards;
static CancerController _cons = new CancerController();
static String[] cancerData;
static JScrollPane treatmentsScroller = new JScrollPane(txtTreatments, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
static JScrollPane causesScroller = new JScrollPane(txtCauses, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
static JScrollPane symptomsScroller = new JScrollPane(txtSymptoms, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
public static class aplPanel extends JPanel {
public JPanel aplReturn() {
treatmentsScroller.setViewportView(txtTreatments);
txtTreatments.setEditable(false);
causesScroller.setViewportView(txtCauses);
txtCauses.setEditable(false);
symptomsScroller.setViewportView(txtSymptoms);
txtSymptoms.setEditable(false);
cards = new JPanel(new GridLayout(6,1));
cancerData = _cons.readCancer(0);
resultName.setText(cancerData[0]);
txtSymptoms.setText(cancerData[1]);
txtCauses.setText(cancerData[2]);
txtTreatments.setText(cancerData[3]);
resultRate.setText(cancerData[4]);
resultPrognosis.setText(cancerData[5]);
cards.add(resultName);
cards.add(symptomsScroller);
cards.add(causesScroller);
cards.add(treatmentsScroller);
cards.add(resultRate);
cards.add(resultPrognosis);
return cards;
}
In essence what you are trying to do is to change the state of one class from another.
How this is done with Swing GUI's is no different for how it is done for non-GUI programs: one class calls the public methods of another class.
One key is to have wiring to allow this to occur which means references for one class needs to be available to the other class so that appropriate methods can be called on appropriate references. The devil as they say is in the details.
"1) How do I get the JPanels to switch using CardLayout?" -- So the class that holds the CardLayout could for instance have the public methods, next(), previous(), and perhaps show(SOME_STRING_CONSTANT) or some other swapView(...) method.
"2) How do I get the data to be displayed in the GUI in text fields when a user clicks an item from the JList?" -- This will involve the use of listeners -- the class holding the JTextFields will listen for notification from the class that holds the JList, and when notified gets the necessary information from the list-displaying class. A PropertyChangeListener could work well here.
e.g.,
public class CancerSelectionListener implements ListSelectionListener {
private CardDisplayingView cardDisplayingView = null;
public CancerSelectionListener(CardDisplayingView cardDisplayingView) {
this.cardDisplayingView = cardDisplayingView;
}
#Override
public void valueChanged(ListSelectionEvent e) {
int selection = ((JList) e.getSource()).getSelectedIndex();
if(selection == 0) {
if (cardDisplayingView != null) {
cardDisplayingView.swapView(...);
}
}
}
}

Updating an image contained in a JLabel - problems

The part of the application that I am currently having trouble getting to work is being able to scroll through and display a list of images, one at a time. I'm getting a directory from the user, spooling through all of the files in that directory, and then loading an array of just the jpegs and pngs. Next, I want to update a JLabel with the first image, and provide previous and next buttons to scroll through and display each image in turn. When I try to display the second image, it doesn't get updated... Here's what I've got so far:
public class CreateGallery
{
private JLabel swingImage;
The method that I'm using to update the image:
protected void updateImage(String name)
{
BufferedImage image = null;
Image scaledImage = null;
JLabel tempImage;
try
{
image = ImageIO.read(new File(name));
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
// getScaledImage returns an Image that's been resized proportionally to my thumbnail constraints
scaledImage = getScaledImage(image, THUMB_SIZE_X, THUMB_SIZE_Y);
tempImage = new JLabel(new ImageIcon(scaledImage));
swingImage = tempImage;
}
Then in my createAndShowGUI method that puts the swingImage on...
private void createAndShowGUI()
{
//Create and set up the window.
final JFrame frame = new JFrame();
// Miscellaneous code in here - removed for brevity
// Create the Image Thumbnail swingImage and start up with a default image
swingImage = new JLabel();
String rootPath = new java.io.File("").getAbsolutePath();
updateImage(rootPath + "/images/default.jpg");
// Miscellaneous code in here - removed for brevity
rightPane.add(swingImage, BorderLayout.PAGE_START);
frame.add(rightPane, BorderLayout.LINE_END);
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
UIManager.put("swing.boldMetal", Boolean.FALSE);
new CreateGalleryXML().createAndShowGUI();
}
});
}
If you've gotten this far, the first image is my default.jpg, and once I get the directory and identify the first image in that directory, that's where it fails when I try to update the swingImage. Now, I've tried to swingImage.setVisible() and swingImage.revalidate() to try to force it to reload. I'm guessing it's my tempImage = new JLabel that's the root cause. But I'm not sure how to convert my BufferedImage or Image to a JLabel in order to just update swingImage.
Instead of creating a New Instance of the JLabel for each Image, simply use JLabel#setIcon(...) method of the JLabel to change the image.
A small sample program :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SlideShow extends JPanel
{
private int i = 0;
private Timer timer;
private JLabel images = new JLabel();
private Icon[] icons = {UIManager.getIcon("OptionPane.informationIcon"),
UIManager.getIcon("OptionPane.errorIcon"),
UIManager.getIcon("OptionPane.warningIcon")};
private ImageIcon pictures1, pictures2, pictures3, pictures4;
private ActionListener action = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
i++;
System.out.println(i);
if(i == 1)
{
pictures1 = new ImageIcon("image/caIcon.png");
images.setIcon(icons[i - 1]);
System.out.println("picture 1 should be displayed here");
}
if(i == 2)
{
pictures2 = new ImageIcon("image/Keyboard.png");
images.setIcon(icons[i - 1]);
System.out.println("picture 2 should be displayed here");
}
if(i == 3)
{
pictures3 = new ImageIcon("image/ukIcon.png");
images.setIcon(icons[i - 1]);
System.out.println("picture 3 should be displayed here");
}
if(i == 4)
{
pictures4 = new ImageIcon("image/Mouse.png");
images.setIcon(icons[0]);
System.out.println("picture 4 should be displayed here");
}
if(i == 5)
{
timer.stop();
System.exit(0);
}
revalidate();
repaint();
}
};
public SlideShow()
{
JFrame frame = new JFrame("SLIDE SHOW");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.getContentPane().add(this);
add(images);
frame.setSize(300, 300);
frame.setVisible(true);
timer = new Timer(2000, action);
timer.start();
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new SlideShow();
}
});
}
}
Since you doing it with ImageIO, here is a good example related to that JLabel using ImageIO
Information relating to your case, as to what is happening :
Inside your createAndShowGUI() method you initializing your JLabel (swingImage), and you added that to your JPanel by virtue of which indirectly to the JFrame.
But now inside your updateImage() method, you are initializing a new JLabel, now it resides in some another memory location, by writing tempImage = new JLabel(new ImageIcon(scaledImage)); and after this you pointing your swingImage(JLabel) to point to this newly created JLabel, but this newly created JLabel was never added to the JPanel, at any point. Hence it will not be visible, even if you try revalidate()/repaint()/setVisible(...). Hence either you change the code for your updateImage(...) method to this :
protected void updateImage(String name)
{
BufferedImage image = null;
Image scaledImage = null;
JLabel tempImage;
try
{
image = ImageIO.read(new File(name));
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
// getScaledImage returns an Image that's been resized
// proportionally to my thumbnail constraints
scaledImage = getScaledImage(image, THUMB_SIZE_X, THUMB_SIZE_Y);
tempImage = new JLabel(new ImageIcon(scaledImage));
rightPane.remove(swingImage);
swingImage = tempImage;
rightPane.add(swingImage, BorderLayout.PAGE_START);
rightPane.revalidate();
rightPane.repaint(); // required sometimes
}
Or else use JLabel.setIcon(...) as mentioned earlier :-)
UPDATED THE ANSWER
Here see how a New JLabel is placed at the position of the old one,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SlideShow extends JPanel
{
private int i = 0;
private Timer timer;
private JLabel images = new JLabel();
private Icon[] icons = {UIManager.getIcon("OptionPane.informationIcon"),
UIManager.getIcon("OptionPane.errorIcon"),
UIManager.getIcon("OptionPane.warningIcon")};
private ActionListener action = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
i++;
System.out.println(i);
if(i == 4)
{
timer.stop();
System.exit(0);
}
remove(images);
JLabel temp = new JLabel(icons[i - 1]);
images = temp;
add(images);
revalidate();
repaint();
}
};
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("SLIDE SHOW");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
this.setLayout(new FlowLayout(FlowLayout.LEFT));
add(images);
frame.getContentPane().add(this, BorderLayout.CENTER);
frame.setSize(300, 300);
frame.setVisible(true);
timer = new Timer(2000, action);
timer.start();
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new SlideShow().createAndDisplayGUI();
}
});
}
}
And for your Question : Of the two options that I have tried, is one better than the other?
setIcon(...) has an edge over the other way, in the sense, you doesn't have to bother about revalidate()/repaint() thingy after adding/remove JLabel. Moreover, you don't need to remember the placement of your JLabel everytime, you add it. It remains at it's position, and you simply call the one method to change the image, with no strings attached and the work is done, without any headaches.
And for Question 2 : I had a bit of doubt, as to what is Array of Records ?

Array of ImageIcons, change contents of array on drag and drop

I have an array of ImageIcons, and I can drag and drop other Icons onto them to replace them. When I hit a button a new JFrame is created from the array of ImageIcons.
If I do this without dragging any other Icons on to the original array, it works. However once I drop a different imageicon into the array, I get an error when I hit the button.
I'm just wondering if this is even possible at all?
I've considered other approaches of using a JTable for the top panel, or trying to use an ArrayList, but I'm not too comfortable using them. If anyone has any opinion on how this should be done, please let me know!
I shortened this example as much as possible(at 200 lines it's not exactly short). But this is exactly what my problem is...
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Properties;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.*;
import java.lang.String.*;
public class test extends JFrame {
JPanel storyPanel, rightStoryPanel, leftStoryPanel,centerStoryPanel, imageSelectPanel, CreatePanel, storyFramePanel, storycard;
TransferHandler handler;
MouseListener listener;
CardLayout cl3;
JLabel[] storyLabel = new JLabel[20];
JButton playStory, nextStory,addtargetbutton;
int count, start, i, j,stop, start1;
public test(){
CreatePanel = new JPanel(new BorderLayout());
storyPanel = new JPanel(new BorderLayout());
rightStoryPanel = new JPanel(new GridLayout(6,1));
leftStoryPanel = new JPanel(new GridLayout(6,1));
centerStoryPanel = new JPanel();
JScrollPane centerscroll = new JScrollPane(centerStoryPanel);
addtargetbutton = new JButton("Add Another Image Slot");
addtargetbutton.addActionListener(new createbuttons());
playStory = new JButton("Play your story!");
leftStoryPanel.add(playStory);
playStory.addActionListener(new createbuttons());
leftStoryPanel.add(addtargetbutton);
imageSelectPanel = new JPanel(new FlowLayout());
storyPanel.add(rightStoryPanel,BorderLayout.EAST);
storyPanel.add(leftStoryPanel, BorderLayout.WEST);
storyPanel.add(centerscroll, BorderLayout.CENTER);
CreatePanel.add(storyPanel, BorderLayout.NORTH);
CreatePanel.add(imageSelectPanel, BorderLayout.CENTER);
count= 3;
start= 0;
stop = 0;
start1= 0;
ImageSelection();
targetpanel();
getContentPane().add(CreatePanel);
}//End Create}
public void ImageSelection(){
int i = 0;
int j = 0;
TransferHandler handler = new TransferHandler("icon") {
#Override
public boolean canImport(TransferSupport support) {
return super.canImport(support)
&& support.getComponent().getParent() != imageSelectPanel;}
};
MouseListener listener = new MouseAdapter(){
public void mousePressed(MouseEvent e){
JComponent c = (JComponent) e.getSource();
TransferHandler handler = c.getTransferHandler();
handler.exportAsDrag(c, e, TransferHandler.COPY);
System.out.println(e);}
}; // Drag & Drop mouse
try{
String imagePath = "";
BufferedImage[] CreateImagesFromDB = new BufferedImage[40];
JLabel[] ImageLabel = new JLabel[40];
while (count > start1) {
i = 1;
CreateImagesFromDB[i] = ImageIO.read(new File("one.jpg"));
ImageLabel[i] = new JLabel(new ImageIcon(CreateImagesFromDB[i]));
imageSelectPanel.add(ImageLabel[i]);
ImageLabel[i].addMouseListener(listener);
ImageLabel[i].setTransferHandler(handler);
i++;
start1++;
}
}//EndTRY
catch(Exception e){
System.out.println("CATCH"+ e);
}//end catch
}
public void targetpanel(){
TransferHandler handler = new TransferHandler("icon") {
#Override
public boolean canImport(TransferSupport support) {
return super.canImport(support)
&& support.getComponent().getParent() != imageSelectPanel;
}
};
MouseListener listener = new MouseAdapter(){
public void mousePressed(MouseEvent e){
JComponent c = (JComponent) e.getSource();
TransferHandler handler = c.getTransferHandler();
handler.exportAsDrag(c, e, TransferHandler.COPY);
}
};
BufferedImage[] storyImages = new BufferedImage[20];
try{
while(count > start){
storyImages[j] = ImageIO.read(new File("TargetImg.jpg"));
storyLabel[j] = new JLabel(new ImageIcon(storyImages[j]));
centerStoryPanel.add(storyLabel[j]);
storyLabel[j].addMouseListener(listener);
storyLabel[j].setTransferHandler(handler);
j++;
start++;
centerStoryPanel.revalidate();
//validate();
System.out.println("J in Loop is: "+j );
}//end while Loop
//System.out.println("J is equalto: "+j);
} catch(Exception e) {};
}// End TargetPanel
public void storyFrame (JLabel[] storyArray){
int i = 0;
storyFramePanel = new JPanel(new BorderLayout());
nextStory = new JButton("Next Image");
nextStory.addActionListener(new createbuttons());
storycard = new JPanel();
cl3 = new CardLayout();
storycard.setLayout(cl3);
JPanel[] storyImgPanel = new JPanel[20];
JLabel[] imglab = new JLabel[20];
storyImgPanel[i]= new JPanel();
while( i < j){
storyImgPanel[i].add(new JLabel(storyArray[i].getIcon()));
storycard.add(storyImgPanel[i], ""+i);
i++;
}
JFrame story = new JFrame("Story");
story.setSize(500,500);
storyFramePanel.add(storycard, BorderLayout.CENTER);
storyFramePanel.add(nextStory, BorderLayout.EAST);
story.add(storyFramePanel);
cl3.show(storycard, "1");
story.setVisible(true);
}
public static void main(String[] args){
System.out.println("Application Running");
JFrame mainframe = new test();
mainframe.setTitle("Let Me Know!");
mainframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainframe.setSize(1000,1000);
mainframe.setVisible(true);
}
class createbuttons implements ActionListener{
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == addtargetbutton){
count++;
targetpanel();
System.out.println("Trying to add another TargetImg, count = "+count);
}
if(e.getSource() == playStory){
storyFrame(storyLabel);
}
if(e.getSource() == nextStory){
cl3.next(storycard);
System.out.println("button pressed");
}
}
}
}
I figured it out:
Firstly, each time you call targetpanel(), you create a new instance of storyLabel, but then you are behaving like you have it already populated from the previous calls. So the result is:
first call:
storyLabel[0] = something;
storyLabel[1] = something;
storyLabel[2] = something;
storyLabel[3] = null;
storyLabel[4] = null.... etc
second call (you added another image slot):
storyLabel[0] = null;
storyLabel[1] = null;
storyLabel[2] = null;
storyLabel[3] = something;
storyLabel[4] = null.... etc
So when you use this array in the storyboard, you get NullPointerException.
You need to create the array only once. So remove storyLabel = new JLabel[20] from targetpanel() and initialize the array in the constructor, or even better in the declaration:
...
CardLayout cl3;
JLabel[] storyLabel = new JLabel[20];
JButton playStory, nextStory, addtargetbutton;
...
Secondly, when displaying the images using the storyFrame(), you change the parent of the supplied JLabels and they subsequently disappear from the storyPanel. You must create new instances of JLabel for the storyboard.
In storyFrame(), instead of
storyImgPanel[i].add(storyArray[i]);
write
storyImgPanel[i].add(new JLabel(storyArray[i].getIcon()));
If I do all this the program is working.
There's not enough in your code to really give you a good answer. One of these two lines:
storyImgPanel[i].add(storyArray[i]);
storycard.add(storyImgPanel[i], ""+i);
would be my guess. The component you're adding in is null (either storyArray[i] or storyImgPanel[i]. Probably the first, since you're creating the second in the loop.
If you could post all your code, it would be easier. Or, (preferably) post a self-contained small example.

Categories