The variable was made, the image is loaded into the variable and the paintComponent is asked to display the image in my JPanel. I can't see my mistake.
public class Main extends JFrame {
public static void main(String[] args) {
JFrame frame = new Main();
frame.setSize(1524, 715);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Animatieproject Stijn Mannaerts: Free Kick");
frame.setContentPane(new Voetbalveld());
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
}
class Voetbalveld extends JPanel {
private ImageIcon afbIntro;
public Voetbalveld() {
afbIntro = new ImageIcon("scr/afbeeldingen/Intro.jpg");
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
afbIntro.paintIcon(null, g, 0, 0);
}
}
That isn't how painting is done. Why not use Graphics.drawImage() instead? Check out this tutorial: http://docs.oracle.com/javase/tutorial/uiswing/painting/
Your code seems right to me. Make sure you don't want src instead of scr. Next, if your image folder is inside source folder of your project then you might want to try this:
afbIntro = new ImageIcon(Voetbalveld.class.getResourceAsStream("scr/afbeeldingen/Intro.jpg"));
or
afbIntro = new ImageIcon(Voetbalveld.class.getResourceAsStream("afbeeldingen/Intro.jpg"));
depending on your file structure. The path in the second example needs to be relative to the file Main.java.
The frame class
import javax.swing.JFrame;
public class Main
{
public static void main(String[] args)
{
Jframe frame = new JFrame("Animatieproject Stijn Mannaerts: Free Kick");
frame.setSize(1524, 715);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new Voetbalveld());
frame.setVisible(true);
}
}
The panel class
import javax.swing.*;
import java.awt.*;
public class Voetbalveld extends JPanel
{
public void paintComponent(Graphics g)
{
ImageIcon afbIntro = new ImageIcon("scr/afbeeldingen/Intro.jpg");
/*The following are two methods for image sizing,
*Use the one that best fits your code:
*
*g.drawImage(afbIntro.getImage(), x, y, null);
*Fill in the arguments for x and y to locate your upper left corner
*The image will be in it's original size with the designated upper left corner
*
*g.drawImage(afbIntro.getImage(), x, y, w, h, null);
*Fill in the arguments for w and h to set the width and height of your image
*The image will be in it's scaled size (w and h) and starting at the
*designated upper left corner (x and y)
*/
}
}
You spelled src wrong. You have scr.
"scr/afbeeldingen/Intro.jpg"
Fix that
Related
Disclaimer: I'm new to Java. I'm new to Swing. And I'm sure it shows.
I've viewed quite a number of examples/tutorials of how to draw on a jpanel "canvas". But they mostly have the same basic format and put all of their drawLine/drawRect/drawArc inside the paintComponent() method. It seems assumed that people want to draw static things to the jpanel one time. But what if I want to change the jpanel object over the course of the program's runtime, like a paint program, or a game?
I suppose I need to be able to access the jpanel object, and internal methods to paint. I'm betting what I'm doing isn't best practices, but here is what I have:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PaintPanel extends JPanel {
public static JFrame frame;
private Graphics g = getGraphics();
public static void main(String[] args) {
frame = new JFrame();
frame.getContentPane().setBackground(new Color(32, 32, 32));
frame.setResizable(false);
frame.setBounds(1, 1, 800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
frame.setVisible(true);
frame.setLocationRelativeTo(null); // center frame on screen
PaintPanel paintPanel = new PaintPanel();
paintPanel.setBounds(10, 10, 100, 100);
paintPanel.setBackground(Color.red);
frame.add(paintPanel);
}
// constructor
public PaintPanel() {
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
public void DrawRect(Integer x, Integer y, Integer w, Integer h, Color color) {
g.setColor(color);
g.fillRect(x, y, w, h);
this.repaint(); // doesn't seem to do anything
}
}
This code results in a red panel box, but my user method DrawRect() doesn't draw anything.
I've read in some places that it's necessary to override the paintComponent() method. If there's nothing in it, what's the purpose?
How can I get my DrawRect() method to work?
The piece of the puzzle you're missing is the model object. There should be an external object that describes what should be drawn. In a game for example, it would be something that describes the current state of the game.
Your custom component looks at this model and takes the necessary steps to paint it. This is implemented in paintComponent and in helper methods you see fit to add.
To make an animation, you make a loop that modifies the model over time, and asks the custom component to redraw itself with repaint().
I have added the image in the src and bin directories and cross-checked that the name of the image file is correct
Here is the main class
import javax.swing.*;
public class apples
{
public static void main(String args[])
{
JFrame frame = new JFrame();
MyDrawPanel wid = new MyDrawPanel();
frame.add(wid);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(300,300);
}
}
and here is the class that does the image adding part
import java.awt.*;
import javax.swing.*;
public class MyDrawPanel extends JPanel
{
public void paintComponent(Graphics g)
{
Image image = new ImageIcon("b.png").getImage();
g.drawImage(image,20, 20, this);
}
}
frame.setVisible(true); should be last code line inside public static void main(String args[]), because you setSize to already visible JFrame (just torso contains only Toolbar with three Buttons)
every Swing code lines in public static void main(String args[]) should be wrapped into invokeLater(), more info about in Oracle tutorial Initial Thread
public class MyDrawPanel extends JPanel returns zero Dimension (0, 0) you have to override getPreferredSize for (inside) MyDrawPanel extends JPanel, use there new Dimension (300, 300) from frame.setSize(300,300); and then replace this code line (frame.setSize(300,300);) with frame.pack()
Image image = new ImageIcon("b.png").getImage();
a) don't to load any FileIO inside paintComponent, create this Object as local variable
b) 1st code line inside paintComponent should be super.paintComponent() and without reason to be public, but protected (public void paintComponent(Graphics g))
c) Dimension set in g.drawImage(image,20, 20, this); doesn't corresponding with frame.setSize(300,300);, for why reason is there empty space
d) most important (as mentioned in comments) Image image = new ImageIcon("b.png").getImage(); isn't valid Java path
try to use getClass().getResource("b.png"); instead of simply giving the file name.
Because it sometimes doesn't receive the image, so extract the path and resource.
You have to add your image (or any file) in the main project file when you work with eclipse or other frameworks
and if you decides to specialize a specific folder in the project -to hold images for example- you can write Image image = new ImageIcon("src\\b.png").getImage();//replace the src with folder name
Or add the full (absolute)path
You're declaring a JFrame called frame and correctly declaring a class that inherits from Panel that can be drawn upon. The method paintComponent(Graphics G) in MyDrawPanel.Java is called upon every time the image needs to be rewritten.
I tested out your code in my own IDE and it works for me. I think that, as others also have suggested, that your picture needs to be dragged into your Eclipse IDE. Just drag-and-drop it into your Java-project.
So I have two classes, one is in charge of creating the JPanel and also overrides paint. The other contains the main and uses this other class. For the sake of ease, I've cut out what isn't involved in graphics. This first one does the JPanel and paint. The second is the main. I apologize for any poor structure or mess, I'm relatively new and I've just been throwing things in to see what works. The stuff in the paint is only a test, it isn't the primary goal.
public class PokerTable extends JPanel {
private static final int WIDTH = 800;
private static final int HEIGHT = WIDTH * 3 / 4;
private static final String NAME = "Test";
private JFrame frame = new JFrame(NAME);
public PokerTable() {
//frame.setMinimumSize(new Dimension(WIDTH,HEIGHT));
//frame.setMaximumSize(new Dimension(WIDTH,HEIGHT));
frame.setPreferredSize(new Dimension(WIDTH,HEIGHT));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setBackground(Color.GREEN);
g2d.setColor(Color.RED);
g2d.fillOval(0, 0, 30, 30);
}
}
This next one does more than call the PokerTable, but I've left the other parts out as they rely on other classes and just print to console.
public class Poker{
public static void main(String[]args) {
System.out.println("hello");
PokerTable pt = new PokerTable();
pt.repaint();
}
Not that I necessarily expected it to work, I've changed the extension on PokerTable to Canvas and JFrame without any luck.
You're not adding the panel to the frame, try with:
frame.add(this);
in PokerTable constructor
You need to add the panel to the frame, or the panel will never repaint.
frame.add(panel) or frame.add(this)
is what you need to call depending on where you do it.
Also, you should be overriding paintComponent, and never paint directly. that won't cause your code to fail, but it is bad practice.
I want go full screen and keep everything inside in order.
How should i put the JFrame into full screen AND rescale everything inside: images, generated drawings etc.(sth like zooming it up so the content will fit the screen).
The problem is I am making full screen app, but I don't know on what screen it will be displayed.
This will put the frame into fullscreen, but the content will not be rescaled
frame.dispose();
frame.setUndecorated(true);
frame.setLocation(0, 0);
frame.setSize(java.awt.Toolkit.getDefaultToolkit().getScreenSize());
frame.setVisible(true);
frame.repaint();
Depends on what it is that you want to scale.
If its graphics you draw using Java2D, just figure out how much the stuff needs to be scaled up and use Graphics2D.scale() to scale the gfx appropiately.
If its something with a Swing layout, use a Layout manager to make an adaptive layout.
If its something else, elaborate on your problem
If this really is what you want to do (see warnings from other answers), it's not too hard to do (but takes a little time to figure out). Basically, it involves extending JPanel, and then overwriting the paint method.
Here's a sample that I came up with:
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class CustomPanel extends JPanel{
Component myComponent;
public CustomPanel(){
super();
setLayout(null);
}
/**
* Only allows one component to be added
*/
#Override
public Component add(Component c){
super.add(c);
c.setLocation(0, 0);
c.setSize(c.getPreferredSize());
myComponent = c;
return c;
}
#Override
public void paint(final Graphics g){
Dimension d = this.getSize();
Dimension p = myComponent.getPreferredSize();
// Paints the child component to a image
BufferedImage newImg = new BufferedImage(p.width, p.height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = newImg.createGraphics();
super.paint(g2d);
// Resizes the image if necessary
Image img;
if(d.height > p.height && d.width > p.width){
System.out.println("Scaled");
float changePercentage = 0;
if(d.height/p.height > d.width/p.width){
changePercentage = (float)d.width/(float)p.width;
} else{
changePercentage = (float)d.height/(float)p.height;
}
System.out.println(changePercentage);
int newHeight = ((Float)(p.height * changePercentage)).intValue();
int newWidth = ((Float)(p.width * changePercentage)).intValue();
img = newImg.getScaledInstance(newWidth, newHeight, 0);
} else{
System.out.println("Not Scaled");
img = newImg;
}
// Paints the image of the child component to the screen.
g.drawImage(img, 0, 0, null);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
SwingUtilities.invokeLater(new Runnable(){public void run(){
JFrame frame = new JFrame("Zoom Panel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
CustomPanel buffer = new CustomPanel();
JPanel content = new JPanel();
content.add(new JLabel("Bogus"));
content.setBackground(Color.red);
buffer.add(content);
frame.setContentPane(buffer);
frame.setVisible(true);
new CustomPanel();
}});
}
}
few days back I just worked with an java full screen app. Have a look at the following link. if that was your requirement I can help you to some extent.
https://docs.google.com/open?id=0B9U-BwYu62ZaeDM3SWZhaTdSYzQ
I have the folowing custom JPanel and I have aded it to my frame using Netbeans GUI builder but the background won't change! I can see the circle, drawing with g.fillOval(). What's wrong?
public class Board extends JPanel{
private Player player;
public Board(){
setOpaque(false);
setBackground(Color.BLACK);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.red);
g.fillOval(player.getxCenter(), player.getyCenter(), player.getRadius(), player.getRadius());
}
public void updatePlayer(Player player){
this.player=player;
}
}
If your panel is 'not opaque' (transparent) you wont see your background color.
You have to call the super.paintComponent(); as well, to allow the Java API draw the original background. The super refers to the original JPanel code.
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.red);
g.fillOval(player.getxCenter(), player.getyCenter(), player.getRadius(), player.getRadius());
}
You need to create a new Jpanel object in the Board constructor.
for example
public Board(){
JPanel pane = new JPanel();
pane.setBackground(Color.ORANGE);// sets the background to orange
}
setOpaque(false);
CHANGED to
setOpaque(true);
I just tried a bare-bones implementation and it just works:
public class Test {
public static void main(String[] args) {
JFrame frame = new JFrame("Hello");
frame.setPreferredSize(new Dimension(200, 200));
frame.add(new Board());
frame.pack();
frame.setVisible(true);
}
}
public class Board extends JPanel {
private Player player = new Player();
public Board(){
setBackground(Color.BLACK);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.red);
g.fillOval(player.getCenter().x, player.getCenter().y,
player.getRadius(), player.getRadius());
}
}
public class Player {
private Point center = new Point(50, 50);
public Point getCenter() {
return center;
}
private int radius = 10;
public int getRadius() {
return radius;
}
}
In order to completely set the background to a given color :
1) set first the background color
2) call method "Clear(0,0,this.getWidth(),this.getHeight())" (width and height of the component paint area)
I think it is the basic procedure to set the background...
I've had the same problem.
Another usefull hint : if you want to draw BUT NOT in a specific zone (something like a mask or a "hole"), call the setClip() method of the graphics with the "hole" shape (any shape) and then call the Clear() method (background should previously be set to the "hole" color).
You can make more complicated clip zones by calling method clip() (any times you want) AFTER calling method setClip() to have intersections of clipping shapes.
I didn't find any method for unions or inversions of clip zones, only intersections, too bad...
Hope it helps