I have googled this and searched through this site to try and get an Image to show up using Swing, but every time i implement the code i find online it doesn't work. I have no idea what i am doing wrong, can anyone help me?
package Game;
import java.awt.Dimension;
import java.awt.Graphics;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Amazing {
private int width = 300;
private int height = width / 16 * 9;
private int scale = 3;
private static Graphics g;
private static JFrame frame = new JFrame();
private static JPanel panel = new JPanel();
public Amazing(){
Dimension size = new Dimension(width*scale, height*scale);
frame.setPreferredSize(size);
frame.setResizable(false);
frame.setTitle("Amazing!");
frame.add(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args){
Amazing amazing = new Amazing();
Character character = new Character();
character.paintComponent(g);
}
}
package Game;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class Character extends JPanel{
private BufferedImage image;
public Character(){
try {
image = ImageIO.read(new File("E:\\Libraries\\Documents\\Java Stuff\\workspace\\Java_Final\\narwhal.png"));
} catch (IOException ex) {
// handle exception...
}
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 50, 50, null); // see javadoc for more info on the parameters
}
}
Amazing amazing = new Amazing();
All that line of code does is create a frame and then add an empty panel to it. Since the panel is empty there is nothing to paint.
Character character = new Character();
character.paintComponent(g);
You should never invoke the paintComponent() method directly. Swing will invoke that method when a component needs to be repainted. Anyway, creating a Character object does nothing. That object is just sitting in memory. It is not added to a GUI so it can never be painted.
I suggest you forget about custom painting and just use a JLabel to display an image. Read the section from the Swing tutorial on How to Use Labels for a working example. Not only that, the tutorial will show you how to better structure your code. You should not be using static variables. Start with the working example and then customize it to use your image.
Related
I have been wanting to program a 2D game from scratch in Java for a while. The pixel aesthetic is one of my favorites, so I am aiming for a pixel 2D game. However, whenever I try to use BufferedImage to draw my tiles, the tiles become extremely distorted.
The tile drawn is actually bigger than the real tile and it seems like it has been stretched. Basically, say I have a 16x16 tile and I draw it. I can visually tell it is distorted when I run the program, and when I take a screenshot, I can measure the pixels and it has somehow become a 20x20.
I have also noticed that when I set a JFrame or a JPanel in the JFrame to a certain size, it is not the actual size that is produced. In my program I create a 320x320 JPanel and put it in a JFrame, but when I take a screenshot and measure the window, it comes up to about 399x399.
Can someone please tell me how to fix this. I stop every game project because the graphics keep looking like rubbish.
This is the Main class:
package main;
import javax.swing.SwingUtilities;
public class Main {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Engine e = new Engine();
e.start();
}
});
}
}
This is the Engine class:
package main;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class Engine {
public JFrame f;
public void initFrame() {
f = new JFrame();
f.setTitle("Something");
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
}
public void start() {
initFrame();
BufferedImage tree;
try {
tree = ImageIO.read(new File("res/boy_down_1.png"));
Panel p = new Panel(tree);
f.add(p);
f.pack();
} catch (IOException e) {
e.printStackTrace();
}
f.setVisible(true);
}
}
This is the Panel class:
package main;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
public class Panel extends JPanel {
BufferedImage i;
public Panel(BufferedImage image) {
i = image;
this.setDoubleBuffered(true);
this.setPreferredSize(new Dimension(320, 320));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(i, 20, 20, null);
g2d.dispose();
}
}
This is the 16x16 I am trying to draw
This is what my computer shows me
I have tried multiple ways to specify the size of the image, but Java seems to distort my image no matter what I do. Thank you in advance.
First off, I am new to JFrame and all the associated classes so I am still learning how to do this.
My current goal is to draw multiple images on a single JFrame. So far, I can get test2.png to draw, but not test1.png. Any suggestions or help understanding JFrame is appreciated. This is my main class:
package com.osj.oneshotjava;
import java.awt.Dimension;
import javax.swing.JFrame;
/**
*
* #author BCG04
*/
public class actorTest {
public static void main(String []args){
JFrame jFrame = new JFrame("OSJ actor test");
jFrame.setPreferredSize(new Dimension(640, 480)); // sets window size
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Actor2 Background = new Actor2(jFrame, "test1.png");
Actor2 testActor = new Actor2(jFrame, "test2.png");
jFrame.pack(); // automatically adjusts window size (also sets window size based on the maximum and minimum sizes)
jFrame.setVisible(true);
}
}
And this is Actor2:
package com.osj.oneshotjava;
import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
*
* #author BCG04
*/
public class Actor2 { //Purpose: make it easer to add multiple images to a single JFrame using only a single call to Actor2's constuctor rather than repeating the same section of code for each image.
private BufferedImage image = null;
private JLabel jLabel = null;
public Actor2(JFrame jFrame, String filename){
try
{ // try to load a image 'filename' into 'image'
image = ImageIO.read(new File(filename));
}
catch (Exception e)
{
e.printStackTrace(); // if loading fails, print the error
System.exit(1); // then exit with an error code 1 'unsuccessful exit'
}
ImageIcon imageIcon = new ImageIcon(image); // create a new ImageIcon that contains 'image'
JPanel jPanel = new JPanel();
jLabel = new JLabel();
jLabel.setIcon(imageIcon); // set JLabel 'jLabel' to contain 'imageIcon'
jPanel.add(jLabel);
jFrame.getContentPane().add(jPanel, BorderLayout.CENTER); // makes window visible?
}
public JLabel getJLabel(){
return jLabel;
}
}
Edit:
-removed Thread.sleep(1000); and setLocation(90, 90); since they were not relevant to the question or the problem and I originally had them in to test whether I could move images.
-removed jLabel.setBounds as it did not seem to do anything.
+added a comment clarifying Actor2's goal.
I'd like to clarify my end goal, I would like to create a simple 2d game that uses Java.
Here is a complete, self contained example that is close to what you're after. It is to demonstrate the use of a layout manager.
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
public class DuelingJLabels{
public static void startGui(){
JFrame frame = new JFrame();
JPanel scene = new JPanel();
Actor red = new Actor(Color.RED);
Actor blue = new Actor(Color.BLUE);
//scene.setLayout( null );
scene.add(red.image);
scene.add(blue.image);
//scene.setPreferredSize( new Dimension(512, 512) );
frame.add(scene, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
static class Actor{
int x, y;
JLabel image;
public Actor(Color c){
BufferedImage a = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics g = a.getGraphics();
g.setColor(c);
g.fillOval(0, 0, 64, 64);
image = new JLabel();
image.setIcon(new ImageIcon(a));
image.setLocation( x, y );
image.setSize( 64, 64);
image.addMouseListener( new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent evt){
x = x+64;
if(x>=448){
x = 0;
y += 64;
}
image.setLocation(x, y);
}
});
}
}
public static void main(String[] args){
EventQueue.invokeLater( DuelingJLabels::startGui );
}
}
Take note of the line scene.setLayout(null); if you run the example with that line commented out, then you will see two circles side by side. That is because we are letting swing handle the layout. scene is a JPanel with a FlowLayout by default.
Now when you click the circles, nothing happens* because we tell the new position but the layout manager resets the position.
*Actually they move sometimes, but if you trigger a re-validation then they get moved by the layout manager.
So now remove the comment on scene.setLayout(null); and notice the difference.
The frame is tiny, and we have to manually resize it to see our scene.
There is only one circle.
If you click on the circle, it moves.
That's because we have told swing to not use a layout manager for the JPanel scene. That means it will not reposition the components in the scene for us, and it will not adjust the sizes for us either.
The other line that is commented setPreferredSize makes scene tell the parent component a size it would like to be at. If you uncomment that line then the JFrame will not start out incredibly small. You should only use that with custom components, otherwise you can end up conflicting with the layout manager.
Another tool, which I have found usefull is the JLayeredPane because it gives you some depth. I also think the example is good.
Finally, another technique for putting custom graphics arbitrarily is to #Override paintComponent. That way you can draw whatever, where-ever on your component.
I would like to display an image in an area in my Jframe but the image takes up much space.
I would like to take it fair precise dimensions.
How can I do this in Java
This is my simple code :
I am open to any proposal if I did not use the right method or the right class to instantiate the image.
import java.awt.*;
import javax.swing.*;
public class ExempleDeplace extends JFrame{
private JLabel myLabel;
public ExempleDeplace(){
setLayout(new FlowLayout());
setTitle("Fenetre, modele Duchi");
setSize(500,700);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel j = new JLabel(new ImageIcon("src/images/bateau.png"));
add(j);
setVisible(true);
}
public static void main (String[] args) {
ExempleDeplace c = new ExempleDeplace();
}
}
You can paint the image in a JPanel as the whole panel. Then whenever the panel is resized, the image will be resized along with it. Here's a quick-n-dirty runnable demo:
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ImgFrame extends JFrame {
private static BufferedImage IMG;
static{
try {
IMG = ImageIO.read(new File("img/Original_Doge_meme.jpg")); //Replace with your image path
} catch (IOException e) {
e.printStackTrace();
}
}
public ImgFrame(){
add(new ImgPanel(), BorderLayout.CENTER);
setSize(500,700);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
class ImgPanel extends JPanel{
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(IMG, 0, 0, getWidth(), getHeight(), this);
}
}
public static void main(String[] args){
new ImgFrame();
}
}
It's probably cleaner to just resize the image. I highly recommend the image resizing utility methods provided by filthyrichclients.
I actually highly recommend the book as well, as it was one of the few books that actually demonstrated the power of Swing...
Once you have the code, you will want to call
createCompatibleImage(myImage, myWidth,myHeight);
first I want to apologize for any mistakes, I'm not speaking english well, I'm new to Java and I'm new to Stackoverflow. Please be kind!
I keep failing to draw a simple image to screen. I tried everything, but I keep failing and I'm getting more and more confused. Here's my Sourcecode:
package com.Animation;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.awt.Graphics2D;
import java.awt.Point;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class Class1 extends JFrame{
private BufferedImage backgroundImg;
public Class1(){
this.setTitle("Animation");
this.setSize(1080, 720);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
LoadContent();
}
public static void main(String[] args){
new Class1();
}
private void LoadContent()
{
try
{
URL backgroundImgUrl = this.getClass().getResource("Back.jpg");
backgroundImg = ImageIO.read(backgroundImgUrl);
}
catch (IOException ex) {
System.err.println("Fehler!");
}
}
public void Draw(Graphics2D g2d)
{
g2d.drawImage(backgroundImg, 0, 0, null);
}
}
So what happens is, that a JFrame window opens with nothing to see on it. I think that's beacuse the Draw() method doesn't get called. But when I add like "Draw(g2d);" somewhere, I keep getting a NullPointerException. The picture "Back.jpg" is located in the same package as the class. I'm using eClipse and the JRE JavaSE 1.7.
I really hope you can help me, im totally exhausted by all my tries to figure out what's the problem. It would be cool if you could write the correct code into the answers and explain what I've done wrong. Remember, I'm new to all this.
Thanks a lot!
There are a lot of ways to do that. Examples
1) JLabel. //Not recommended
Add the JLabel in your JFrame, then do label.setIcon(backgroundImg);
2) JPanel
Override the paint() method in JPanel(make sure you've added it to your JFrame).
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(backgroundImg, 0, 0, this);
}
Try this. Here I have set the image to a JPanel instead of directly setting it to JFrame.
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
/**
*
* #author Rumesh
*/
public class Test extends JFrame{
public static void main(String[] args) throws IOException {
JFrame frame = buildFrame();
final BufferedImage image = ImageIO.read(new File("1.jpg"));
JPanel pane = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
};
frame.add(pane);
}
private static JFrame buildFrame() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
return frame;
}
}
I don't know if this is what you're searching for:
ImageIcon image = new ImageIcon("src/media/Image.jpg");
JLabel lblImg = new JLabel("", image, JLabel.CENTER);
lblImg.setBounds(..., ..., ..., ...);
add(lblImg);
This way you'll add an image to a JLabel and than place it on the screen. I hope it helps in some way.
This question already has answers here:
Java: JPanel background not scaling
(2 answers)
Closed 8 years ago.
Im trying to add an image to a JLabel and i have encountered a problem where the image is to big for the JLabel so I'm looking for a way to make the image automatically scale to the size of the JLabel.
Here is my main body of code where i call up my GUImain class:
public class Main
{
public static void main(String[] args)
{
int i = 0;
int t = 0;
int st = 0;
int h = 0;
Texts textObject = new Texts();
textObject.TextList();
Commands commandObject = new Commands();
commandObject.commands();
GUImain guiObject = new GUImain();
guiObject.displayGUI();
}
}
And here is the code for my GUImain class, i will only include one image button because there are allot of objects in my code.
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JTextPane;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JScrollBar;
import javax.swing.JTextField;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
public class GUImain
{
private JFrame frame;
private JTextField textField;
private ImageIcon image1;
public void displayGUI()
{
this.frame.setVisible(true);
}
//Launch the application.
public static void main(String[] args)
{
GUImain window = new GUImain();
}
//Create the application.
public GUImain()
{
frame = new JFrame();
frame.setBounds(100, 100, 611, 471);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
...
JLabel lblHunger = new JLabel();
Image img2 = new ImageIcon(this.getClass().getResource("/Food.png")).getImage();
lblHunger.setIcon(new ImageIcon(img2));
lblHunger.setBounds(211, 58, 50, 50);
panel.add(lblHunger);
}
}
}
Don't use a null layout!!!
Swing was designed to be used with layout managers. Let each component determine its preferred size and then let the layout manager size and position the component based on the rules of the layout manager.
Instead of doing custom painting you can use Darry'ls Stretch Icon. The Icon will be painted based on the space available to the icon.
i have encountered a problem where the image is to big for the JLabel
Just reread that part of the question. In that case you may want to use the Image.getScaledInstance(...) method to scale the image to an appropriate size. The you can use a regular Icon and the appropriate layout manager.
what layout would i be able to use to easily choose the dimensions and where the objects are positioned
You are not supposed to choose the size/location of a component. That is the job of the layout manager. Read the tutorial on Layout Managers and choose the one (or combination of layout managers) that is appropriate for your requirements.