I am beginner to Swing and I am writing some codes. I have added images on JLabel and JLabel on JFrame. I want to move that Image. Is it possible to move that image(fish). If yes, How can I do it?
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Aquarium extends JFrame{
private ImageIcon fish2image;
private ImageIcon fish1image;
private ImageIcon image;
private JLabel imglabel;
private JLabel fish1label;
private JLabel fish2label;
int numberFish = 12;
public Aquarium(){
initComponents();
setTitle("The Aquarium");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setResizable(false);
setBounds(500,200,500,300); //left,top,width,height
add(fish1label);
add(fish2label);
add(imglabel);
}
private void initComponents(){
image = new ImageIcon(getClass().getResource("../res/aquarium.gif"));
fish1image = new ImageIcon(getClass().getResource("../res/smallFish.gif"));
fish2image = new ImageIcon(getClass().getResource("../res/smallFish2.gif"));
imglabel = new JLabel(image);
fish1label = new JLabel(fish1image);
fish2label = new JLabel(fish2image);
fish1label.setBounds(100,100,250,200);
fish2label.setBounds(50,25,200,200);
}
public static void main(String[] args) {
new Aquarium();
}
}
Repeat question. But you would shift the x, and y values (Based on keyBindings or KeyListener added on frame) and it will automatically repaint.
But since you want the fist to move automatically. You are going to need either a loop based on a swing timer, Thread.sleep(1000); <= Highly not recommended, or a Thread.
Then you would shift the x and y values as described above as a certain amount of seconds pass within the method that you choose
Related
I am working on this reaction time game that tells you to click an arrow key once the ball has turned into a different colored ball. However, I can't seem to get the image of the ball to be replaced by the other ball.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.Timer;
public class Game extends JPanel
{
private JLabel watch, main;
private ImageIcon constant, react;
final int width = 600;
final int height = 600;
private Timer replace;
private ActionListener timerListener;
public Game()
{
setPreferredSize(new Dimension(width, height));
setBackground(Color.black);
watch = new JLabel("Click Up Arrow when you see a blue ball");
watch.setForeground(Color.white);
add(watch);
constant = new ImageIcon("constantCircle.png");
main = new JLabel(constant);
replace = new Timer(3000, timerListener);
replace.setRepeats(false);
replace.start();
add(main);
}
public void actionPerformed (ActionEvent e)
{
react = new ImageIcon("reactCircle.png");
main.setIcon(react);
}
}
This is the code for my display and I wanted to use a swing timer to replace the image after 3 seconds
This is what I want it to look like before
and this is what I want it to look like after 3 seconds
You're never initializing timerListener
private ActionListener timerListener;
Inside your constructor you have to call (With Java 8 lambdas):
timerListener = e -> {
react = new ImageIcon("reactCircle.png");
main.setIcon(react);
}
Or (Java 7 and lower):
timerListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
react = new ImageIcon("reactCircle.png");
main.setIcon(react);
}
}
And don't forget to call timerListener.stop() once the timer has fired, so that you don't keep computing more times
From Andrew Thompson's comment below:
As you only want to replace the image once, call timerListener.setRepeats(false) on your constructor. Check the docs for more information about it.
I have a card project that I am doing and it uses GUI's. I have a JFrame
JFrame frame = new JFrame("Card Game");
//Splits the Jframe into two sections where the cards will be placed
//according to what user draws them
frame.setLayout(new GridLayout(1,2));
//The users, with different hands of cards
JPanel user1 = new JPanel();
JPanel user2 = new JPanel();
frame.add(user1);
frame.add(user2);
I want to be able to efficiently add/remove cards for each users hand. The maximum amount of cards that a user could draw is 9. Initially the user will start of with two cards and I want to make it so that I can add another card neatly. If the space in the panel runs out the cards should go start forming a row beneath.
How do I achieve this? I was thinking of somehow using JLabels, but don't know if this is a correct way. Also I don't know what layout I should use, so any help/tips would be appreciated. Thank you.
EDIT
Thank you for the help, but I still have a problem. I use the code that 'Lourenco' posted to use as my panel where I add cards. I didn't change it.
In my GUI class I added
MyPanel myPanel = new MyPanel();
public void addPlayerCard(Card c){
myPanel.addCard(c.getImageIcon());//should draw the card into the panel
}
This is how I add my imageicon to the card
java.net.URL imgURL = Card.class.getResource(imgFileName);
if (imgURL != null) {
image = new ImageIcon(imgFileName, "");
} else {
System.err.println("Couldn't find file: " + imgFileName);
image = new ImageIcon();
}
What am I doing wrong?
Try to use this class. Its a JPanel, so you can create an instance of MyPanel and add to your JFrame.
To add a card you must create an ImageIcon object [ex: ImageIcon card = new ImageIcon("c:\users\desktop\aceOfSpades.png")].
After creating the ImageIcon object you must call the addCard function and pass the card as argument. The card will be added to the ArrayList of cards and the painel will be repainted. You can manipulate the 2 constants CARD_WIDTH and CARD_HEIGHT and the variables x, y and widthToNextCard in the rapaintComponent method.
This way will give you a lot more freedom to paint the cards the way you want, instead of using a layout with different JLabels.
Good luck ;)
import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class MyPanel extends JPanel {
private static final long serialVersionUID = 1L;
public final static int CARD_WIDTH = 50;
public final static int CARD_HEIGHT = 100;
private ArrayList<ImageIcon> cardsList;
public MyPanel() {
cardsList = new ArrayList<ImageIcon>();
}
public void addCard(ImageIcon newCard) {
cardsList.add(newCard);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int widthToDrawNextCard = 75;
int x = 50;
int y = 100;
for (int i = 0; i < cardsList.size(); i++) {
ImageIcon card = cardsList.get(i);
Image image = card.getImage();
g.drawImage(image, x, y, CARD_WIDTH, CARD_HEIGHT, null);
x = x + widthToDrawNextCard;
}
}
}
Current code
ThreeColorButton class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ThreeColorButton {
private static CompositeIcon icons = new CompositeIcon();
private static JPanel panel = new JPanel();
private static JFrame frame = new JFrame();
private static JLabel label = new JLabel();
public static void main(String[] args) {
//create rgb buttons
JButton redButton = new JButton("Red");
JButton greenButton = new JButton("Green");
JButton blueButton = new JButton("Blue");
//add rgb buttons to panel
panel.add(redButton);
panel.add(greenButton);
panel.add(blueButton);
//add action listeners to buttons
redButton.addActionListener(buttonListener(40, Color.red));
greenButton.addActionListener(buttonListener(40, Color.green));
blueButton.addActionListener(buttonListener(40, Color.blue));
frame.setLayout(new BorderLayout());
frame.add(panel, BorderLayout.NORTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private static ActionListener buttonListener(final int size,final Color color) {
return new ActionListener() {
public void actionPerformed(ActionEvent event) {
SquareIcon icon = new SquareIcon(size, color);
icons.addIcon(icon);
label.setIcon(icons);
frame.add(label, BorderLayout.SOUTH);
frame.repaint();
frame.pack();
}
};
}
}
CompositeIcon code
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class CompositeIcon implements Icon{
private ArrayList<Icon> icons;
private int size;
public CompositeIcon() {
icons = new ArrayList<Icon>();
}
public void paintIcon(Component c, Graphics g, int x, int y) {
int position = x;
for(Icon z : icons) {
z.paintIcon(c,g,position,y);
position = position + z.getIconWidth();
}
}
public int getIconHeight() {
return size;
}
public int getIconWidth() {
int total = 0;
for(Icon z : icons) {
total = total + z.getIconWidth();
}
return total;
}
public void addIcon(Icon z) {
icons.add(z);
}
}
SquareIcon class is only a simple little class that creates a square of a single color with a given size.
My question is, in my ThreeColorButton class, when I run it, it doesn't show any icons when I press either of the RGB buttons. However, in the buttonListener method, if I set label.setIcons(icons) to label.setIcons(icon), it shows a single square and it doesnt place it side by side.
I can't seem to figure out whats causing this behavior. Is there a problem with displaying an array of icons using JLabel?
There is nothing to paint in the label since the height of your Icon is 0, since you never set the size.
I would suggest code something like:
#Override
public int getIconHeight()
{
int size = 0;
for(Icon z : icons)
{
size = Math.max(size, z.getIconHeight());
}
return size;
}
You may want to check out Compound Icon. Similar to your class but it has more features. It supports horizontal/vertical/stacked icon and icon alignment options.
It doesn't support dynamically adding Icons so you would need to change that. I might looking adding that feature myself (when I get time) :)
I can't seem to figure out whats causing this behavior. Is there a problem with displaying an array of icons using JLabel?
Yes, as #mKorbel mentioned, there is a problem. A JLabel can only display a single icon. If you want to display n icons, you will need n JLabel instances.
I am trying to build a simple basic to a game for my class in Game Engine Architecture. But my JFrame just wont show anything.
My code is currently structured like this:
Implementation.java (This is some arbitrary implementation of the Engine-package I'm creating)
public class Implementation {
public static void main(String[] args){
World w = new World("Hej", "M:\\workspace\\SP6\\pics\\tulips.jpg",1024,768);
}
}
World.java
public class World extends JFrame{
private static final long serialVersionUID = 1L;
private SpritePanel spritePanel;
private JPanel bottom;
private int width;
private int height;
public World(String windowCaption, String bgPath, int width, int height){
super(windowCaption);
spritePanel = new SpritePanel(bgPath);
add(spritePanel, BorderLayout.CENTER);
System.out.println(spritePanel);
bottom = new JPanel();
bottom.add(new JLabel("Hej"));
add(bottom, BorderLayout.SOUTH);
Dimension size = new Dimension(width,height);
setSize(size);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
validate();
repaint();
}
SpritePanel.java
public class SpritePanel extends JPanel {
private static final long serialVersionUID = 1L;
private ImageIcon background;
private ArrayList<Sprite> sprites = new ArrayList<Sprite>();
public SpritePanel(String bgPath){
background = new ImageIcon(bgPath);
setLayout(null);
Dimension size = new Dimension(background.getIconWidth(), background.getIconHeight());
setPreferredSize(size);
setMaximumSize(size);
setMinimumSize(size);
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(background.getImage(), 0, 0, this);
System.out.println("painted panel");
}
}
So the basic action flow at the moment (from what I can see):
I create a new World object in the Implementation
The World-constructor is called with the given parameters
The window caption is set (this works)
I create a new SpritePanel object with the given bgPath
The SpritePanel-constructor is called and sets the ImageIcon to the image that exists in the given path
The SpritePanel is added to the frame in BorderLayout.CENTER
I add a new JPanel to the frame in BorderLayout.CENTER
I set size and stuff
I pack and set the frame to visible
I validate and repaint
The thing is the paintComponent methods in the JPanel and SpritePanel doesn't seem to get called. As you can see I added a System.out.println in the paintComponent for SpritePanel and that line is never executed.
Another thing I noticed is that the pack seems to know that the components are there. Because if I comment the three lines
spritePanel = new SpritePanel(bgPath);
add(spritePanel, BorderLayout.CENTER);
System.out.println(spritePanel);
The windows size when I run the program is reduced to the size of the "bottom"-JPanel. I can't see the JLabel that I added to the panel but the window size is the size of it. So the pack() method seems to be finding the dimensions of my components.
If I comment the three lines that adds the bottom panel as well the window size is reduced to no height and the width it gets from the standard icons.
I've been trying different things to get it to work but to no avail. I have programmed with Swing before and made working programs but I just can't seem to find the problem here.
Help very much appreciated.
Something may be wrong with your with your String path. What you should do though, instead o reading a file, you should be reading a URL, loading from the class path. At time of deployment, you'll find out that the file path won't work, so it's better to package your image as an embedded resource, putting the image in the class path. I had no problems when doing this. Here's what I did.
Change the path to a path relative to my class path
World w = new World("Hej", "/resources/stackoverflow5.png", 1024, 768);
Changed loading from a file to loading from a URL from my class path
background = new ImageIcon(SpritePanel.class.getResource(bgPath));
Put the image in resources package in my class path
Everything works fine
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Implementation {
public static void main(String[] args) {
World w = new World("Hej", "/resources/stackoverflow5.png", 1024, 768);
}
}
class World extends JFrame {
private static final long serialVersionUID = 1L;
private SpritePanel spritePanel;
private JPanel bottom;
private int width;
private int height;
public World(String windowCaption, String bgPath, int width, int height) {
super(windowCaption);
spritePanel = new SpritePanel(bgPath);
add(spritePanel, BorderLayout.CENTER);
System.out.println(spritePanel);
bottom = new JPanel();
bottom.add(new JLabel("Hej"));
add(bottom, BorderLayout.SOUTH);
Dimension size = new Dimension(width, height);
setSize(size);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
validate();
repaint();
}
class SpritePanel extends JPanel {
private static final long serialVersionUID = 1L;
private ImageIcon background;
//private ArrayList<Sprite> sprites = new ArrayList<Sprite>();
public SpritePanel(String bgPath) {
background = new ImageIcon(SpritePanel.class.getResource(bgPath));
setLayout(null);
Dimension size = new Dimension(background.getIconWidth(), background.getIconHeight());
setPreferredSize(size);
setMaximumSize(size);
setMinimumSize(size);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background.getImage(), 0, 0, this);
System.out.println("painted panel");
}
}
}
Side Notes
No need to setSize(). You already pack(). It better to just pack anyway.
Put the pack() before the setLocationRelativeTo(). If you pack() after, you'll notice your frame won't be in the desired location.
Run your Swing apps from the Event Dispatch Thread (EDT) like this
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
new World("Hej", "/resources/stackoverflow5.png", 1024, 768);
}
});
}
If you want to make the frame fill the screen, don't set the size. Different machines have different screen sizes. Instead use setExtendedState(JFrame.MAXIMIZED_BOTH);
Also, your setSize() won't work anyway because you're calling pack() after.
My problem was that I hade overridden the getWidth() and getHeight() methods in my World-class.
But look to peeskillets response for how to make things better!
In the last secong and third line if I say
label.setText("x = ");
The label is moving perfectly but when I change it to
label.setText("x = "+ x);
it does not move. To be specific I want to see the width location of JLabel when it's moving by variable x!
Beside this I said label.setBounds(x,(getHeight()/2),300,300); which set the Y bound of the label to half of the frame size but it's not at the middle of frame? Any Idea?
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JLabel;
import javax.swing.Timer;
import javax.swing.JFrame;
public class myTiemr {
public static void main(String args[])
{
TimeFrame frame = new TimeFrame();
}
}
class TimeFrame extends JFrame
{
private static final long serialVersionUID = 1L;
private int x = 0;
JLabel label = new JLabel("Here is my label");
public TimeFrame()
{
int d = 10;
setTitle("My Frame");
setSize(500,500);
this.setLocationRelativeTo(null);
add(label);
Timer time = new Timer(d,new TimerListener());
time.start();
setVisible(true);
}
class TimerListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(x>getWidth()){
x=-100;
}
x+=1;
label.setText("x = "+ x);
//label.setText("x = ");
label.setBounds(x,(getHeight()/2),300,300);
}
}
}
The reason that label.setText("x = "+ x) causes the text to remain still but yet the line label.setText("x = ") causes the label to move across the frame is that revalidate() is called on the JLabel. This will cause the correct behavior applying the current layout manager's rules (namely BorderLayout in this case).
When the text does not change, revalidate() is never called.
As #Sébastien Le Callonnec suggested setting no layout on the frame will cause
label.setText("x = "+ x)
to move as desired.
In the TimeFrame constructor, add:
this.setLayout(null);
after this.setLocationRelativeTo(null);.