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

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.

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);
}
}

Java Multiple Checkboxes and Executing Multiple Statements

new to programming and Java is the first language I'm learning.
I'm having difficulty thinking through the logic on this application I'm building. The application is really simple: it has say five checkboxes and a sync button. You select a checkbox and click sync and it runs a cmd command associated with the specific checkbox.
However, I would like to be able to check multiple checkboxes and hit sync and have them all go instead of doing it one at a time. I currently have an if statement (if the checkbox is selected and sync button is pressed) run "xyz" command (that corresponds to that checkbox). But it only runs for the first checkbox (if) and then quits.
Thanks!
Edit. Code below:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.Scanner;
class RcSync extends JFrame implements ActionListener{
Container contentPane = getContentPane();
JPanel top = new JPanel();
JPanel center = new JPanel();
JPanel bottom = new JPanel();
JScrollPane mainScrollFrame = new JScrollPane(center);
JLabel displayMessage = new JLabel("Please select a item, and click sync:");
Font customFontHeader = new Font("", Font.BOLD,15);
JButton syncButton = new JButton("Sync");
JButton cancelButton = new JButton("Cancel");
String[] database = {"Apple","Pineapple","Orange","Pear","Fig"};
JCheckBox chk1 = new JCheckBox(database[0]);
JCheckBox chk2 = new JCheckBox(database[1]);
JCheckBox chk3 = new JCheckBox(database[2]);
JCheckBox chk4 = new JCheckBox(database[3]);
JCheckBox chk5 = new JCheckBox(database[4]);
JCheckBox chk6 = new JCheckBox(database[5]);
public RcSync() {
super ("Sync Application");
setSize (400,450);
setDefaultCloseOperation(EXIT_ON_CLOSE);
add(top);
setVisible(true);
top.add(displayMessage);
displayMessage.setFont(customFontHeader);
center.add(chk1);
center.add(chk2);
center.add(chk3);
center.add(chk4);
center.add(chk5);
bottom.add(syncButton);
syncButton.addActionListener(this);
cancelButton.addActionListener(new CloseListener());
bottom.add(cancelButton);
bottom.add(emailButton);
emailButton.addActionListener(this);
contentPane.add("North", top);
contentPane.add("South", bottom);
this.getContentPane().add(mainScrollFrame, BorderLayout.CENTER);
center.setLayout(new BoxLayout(center, BoxLayout.Y_AXIS));
}
public void actionPerformed(ActionEvent event){
if ((event.getSource() == syncButton) && (chk1.isSelected())) {
try {
Runtime.getRuntime().exec("cmd /c start \"\" C:\\File\\script.bat " + chk1.getText());
} catch (IOException e) {
e.printStackTrace();}
}
if ((event.getSource() == syncButton) && (chk2.isSelected())) {
try {
Runtime.getRuntime().exec("cmd /c start \"\" C:\\File\\script.bat " + chk2.getText());
} catch (IOException e) {
e.printStackTrace();}
}
if ((event.getSource() == syncButton) && (chk3.isSelected())) {
try {
Runtime.getRuntime().exec("cmd /c start \"\" C:\\File\\script.bat " + chk3.getText());
} catch (IOException e) {
e.printStackTrace();}
}
if ((event.getSource() == syncButton) && (chk4.isSelected())) {
try {
Runtime.getRuntime().exec("cmd /c start \"\" C:\\File\\script.bat " + chk4.getText());
} catch (IOException e) {
e.printStackTrace();}
}
if ((event.getSource() == syncButton) && (chk5.isSelected())) {
try {
Runtime.getRuntime().exec("cmd /c start \"\" C:\\File\\script.bat " + chk5.getText());
} catch (IOException e) {
e.printStackTrace();}
}
}
private class CloseListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
public static void main (String[]args){
RsSync gui = new RcSsync();
}
}
}
I have edited my response since you provided more context to your question. Pasted below: is my approach to solving your problem, working code with explanation, and errors I had to resolve with your associated code:
Approach: Associate a boolean value for each checkbox corresponding to whether or not that option has been 'selected by the end user'. When the sync button is clicked, find which checkboxes have been selected. These checkboxes will return a true value from their isSelected() method. For each checkbox selected add the associated command into a List containing all the commands to be ran on the end user's machine. Iterate through this list until there are no commands left to be ran.
Code:
import javax.swing.*;
import java.util.ArrayList;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
class RcSync extends JFrame implements ActionListener{
Container contentPane = getContentPane();
JPanel top = new JPanel();
JPanel center = new JPanel();
JPanel bottom = new JPanel();
JScrollPane mainScrollFrame = new JScrollPane(center);
JLabel displayMessage = new JLabel("Please select a item, and click sync:");
Font customFontHeader = new Font("", Font.BOLD,15);
JButton syncButton = new JButton("Sync");
JButton cancelButton = new JButton("Cancel");
// Encapsulate your checkboxes to commands, since there is one
// to one relationship and makes future changes easier since there is a single point of change
String[] database = {"Apple","Pineapple","Orange","Pear","Fig"};
CheckboxCommand chk1 = new CheckboxCommand("Checkbox 1 cmd", new JCheckBox(database[0]));
CheckboxCommand chk2 = new CheckboxCommand("Checkbox 2 cmd", new JCheckBox(database[1]));
CheckboxCommand chk3 = new CheckboxCommand("Checkbox 3 cmd", new JCheckBox(database[2]));
CheckboxCommand chk4 = new CheckboxCommand("Checkbox 4 cmd", new JCheckBox(database[3]));
CheckboxCommand chk5 = new CheckboxCommand("Checkbox 5 cmd", new JCheckBox(database[4]));
public RcSync() {
super ("Sync Application");
setSize (400,450);
setDefaultCloseOperation(EXIT_ON_CLOSE);
add(top);
setVisible(true);
top.add(displayMessage);
displayMessage.setFont(customFontHeader);
center.add(chk1.checkbox);
center.add(chk2.checkbox);
center.add(chk3.checkbox);
center.add(chk4.checkbox);
center.add(chk5.checkbox);
bottom.add(syncButton);
syncButton.addActionListener(this);
cancelButton.addActionListener(new CloseListener());
bottom.add(cancelButton);
// TODO email button doesn't exist, assuming copy/paste error?
// bottom.add(emailButton);
// emailButton.addActionListener(this);
contentPane.add("North", top);
contentPane.add("South", bottom);
this.getContentPane().add(mainScrollFrame, BorderLayout.CENTER);
center.setLayout(new BoxLayout(center, BoxLayout.Y_AXIS));
}
public void actionPerformed(ActionEvent event){
// Implements the approach I described initially
if (event.getSource() == syncButton){
List<String> cmdsToRun = new ArrayList<>();
if (chk1.isSelected()){
cmdsToRun.add(chk1.getCmdToRun());
}
if (chk2.isSelected()){
cmdsToRun.add(chk2.getCmdToRun());
}
if (chk3.isSelected()){
cmdsToRun.add(chk3.getCmdToRun());
}
if (chk4.isSelected()){
cmdsToRun.add(chk4.getCmdToRun());
}
if (chk5.isSelected()){
cmdsToRun.add(chk5.getCmdToRun());
}
// Note: for verification purposes I just print out your commands
// since they're hard coded to your particular environment
System.out.println(cmdsToRun);
// This is where you would loop through your command list i.e.
// for (int x=0; x<cmdsToRun; x++){ //run command at cmdToRun.get(x); }
}
}
private class CloseListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
// encapsulating your checkboxes to commands
private class CheckboxCommand {
private String cmdToRun;
private boolean isSelected;
private JCheckBox checkbox;
public CheckboxCommand(String cmdToRun, JCheckBox checkbox) {
this.cmdToRun = cmdToRun;
this.checkbox = checkbox;
}
public String getCmdToRun() {
return cmdToRun;
}
public void setCmdToRun(String cmdToRun) {
this.cmdToRun = cmdToRun;
}
public boolean isSelected() {
return this.checkbox.isSelected();
}
public void setSelected(boolean selected) {
isSelected = selected;
}
}
public static void main (String[]args){
// Fixed your typo error to run the swing interface
RcSync gui = new RcSync();
}
}
Verification of correct code:
Key Insight:
I encapsulated your commands to checkboxes into a private class since there is a one to one relationship and this will allow your code to have a single point of change, which in general is a best practice :)
Side Note:
I don't actually run your commands on my end since they're tied to your particular machine. I.e. associated to local scripts, so I printed out dummy commands to prove the code functions appropriately. I added a comment block in the code to show where you can add your environment specific code i.e. Runtime.getRuntime().exec("<CMD>");
Errors to be fixed:
I removed this line: JCheckBox chk6 = new JCheckBox(database[5]); since this will throw an indexOutOfBounds exception since there are only 5 elements in your in-memory database variable not 6.
emailButton doesn't exist so I commented it out:
// bottom.add(emailButton);
// emailButton.addActionListener(this);
This is a typo and won't run the gui: RsSync gui = new RcSsync(); so I changed it appropriately: RcSync gui = new RcSync();
Hopefully that helps! :)

if statements,lables and combo boxes

Ok my code has to pick route combo box (check) display in label(check) have a return and single ticket combobox(check) need it to display text(check) my problem is it only prints text related to one of my statments hope someone can tell me how to fix my if statments. The lable changes on a button .It reads code by lable.So far it only prints 15 and wont print 20 unless i had another label but this wouldnt make sense for the program
package learning;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList.*;
import java.util.Arrays.*;
import java.util.List.*;
#SuppressWarnings("unused")
public class test {
String[] items = {"Tipperary_to_cork","Cork_to_Dublin","Limerick_to_Tipperary","Dublin_to_Cork"};
JComboBox c = new JComboBox(items);
JButton b = new JButton("From");
JLabel l = new JLabel();
String[] items2 = {"window","aisle"};
JComboBox m = new JComboBox(items2);
JButton n = new JButton("Seat");
JLabel o = new JLabel();
String[] items3 = {"Single","return"};
JComboBox x = new JComboBox(items3);
JButton y= new JButton("Ticket");
JLabel z = new JLabel("choose Ticket");
String[] items4 = {"1","2","3","4","5","6","7","8","9","10"};
JComboBox<?> xx = new JComboBox(items4);
JButton yy = new JButton("seat");
JLabel zz = new JLabel("Choose a seat");
JLabel hh = new JLabel("cost");
JButton ccc = new JButton("comfirm");
JLabel hhh = new JLabel("");{
}
public test(){
frame();
}
public void frame(){
JFrame wolf = new JFrame();//frame
wolf.setVisible(true);
wolf.setSize(350,350);
wolf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
JPanel p = new JPanel();
p.add(hh);
p.add(c);//
p.add(b);//
p.add(l);//lable1
p.add(m);//
p.add(n);//
p.add(o);//lable 2
p.add(x);//
p.add(y);//
p.add(z);//lable 2
p.add(xx);//
p.add(yy);//
p.add(zz);//lable 2
p.add(ccc);
p.add(hhh);
wolf.add(p);
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
String s = c.getSelectedItem().toString();
l.setText(s);
}
});
n.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
String s = m.getSelectedItem().toString();
o.setText(s);
}
});
y.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
String s = x.getSelectedItem().toString();
z.setText(s);
}
});
yy.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
String s = xx.getSelectedItem().toString();
zz.setText(s);
}
});
}
{
if(l.getText().equals("Tipperary_to_cork")&&(z.getText().equals("single"))){
ccc.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
hh.setText("15"); //***
}});
if(l.getText().equals("Tipperary_to_cork")&&(z.getText().equals("return"))){
ccc.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
hh.setText("20"); //****
}
});
}}}
public static void main(String[]args){
new test();
}
}
You want to check "if some condition" when you click the button. So, start with one simple if statement inside one of the actionPerformed methods. You shouldn't add an action listener inside an if statement, you should always perform an action, and determine the event inside that action.
For example
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
String s = c.getSelectedItem().toString();
if (s.equals("Tipperary to cork")) {
// TODO: do something
}
}
});
Original answer
These line just happen to work because you have if(false==false)
if(l.equals("Tipperary to cork")==(z.equals("single"))) { ... }
if(l.equals("Tipperary to cork")==(z.equals("return"))) { ... }
The reason they evaluate to false is because you are comparing a JLabel.equals(String). You should use l.getText().equals("text here"), but...
The problem is that you have those if statements inside the constructor for your class, meaning that they are the first thing that is evaluated in your code. You should move the corrected if statements into the ActionListeners for the respective buttons.
Additional note: You seem to want "Tipperary to cork" AND "single". In that case, use && in place of ==. Alternatively, you could do this (psuedocode intentional)
if "Tipperary to cork" {
if "single" { ... }
else if "return" { ... }
}
In reality, though, you should compare c.getSelectedItem().toString() instead of the text of the label, but that's your decision.

How do I update a JLabel in a JPanel?

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]);
}

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(...);
}
}
}
}

Categories