I've made some code for my tile, where I draw 2 objects, but I can't load a background in the tile as it extends JFrame.
What am I doing wrong?
I used buffered image to read the picture, made it suitable for any screen size, set it as a JLabel, but still isn't working.
Square1 and obstacle are graphics of rectangles imported, one acting as the player moving and the other as an obstacle respectively.
public class BasicTwoPlayer extends JFrame implements Runnable {
static Square1 p1 = new Square1();
static Square2 p2 = new Square2();
static obstacle o1 = new obstacle();
static Thread p1t;
static Thread p2t;
static Thread o1t;
KeyADAPT a = new KeyADAPT();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
final int widthScreen = screenSize.width;
final int heightScreen = screenSize.height;
public BasicTwoPlayer() {
try {
BufferedImage backgroundImage = ImageIO.read(new File("P://My Pictures//background1.jpg"));
JLabel background = new JLabel(new ImageIcon(backgroundImage));
Image scaleBackground = backgroundImage.getScaledInstance(widthScreen, heightScreen, Image.SCALE_SMOOTH);
ImageIcon imageIcon = new ImageIcon(scaleBackground);
setContentPane(new JLabel(imageIcon));
addKeyListener(a);
setSize(new Dimension(widthScreen, heightScreen));
setUndecorated(true);
setBackground(Color.WHITE);
setLayout(null);
setLocationRelativeTo(null);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
p1t = new Thread(p1);
p2t = new Thread(p2);
o1t = new Thread(o1);
p1t.start();
p2t.start();
} catch (IOException ex) {
Logger.getLogger(BasicTwoPlayer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void paint(Graphics g) {
background.paint(g);
}
public void draw(Graphics g) {
p1.draw(g);
o1.draw(g);
repaint();
}
public static void main(String[] args) {
BasicTwoPlayer sf = new BasicTwoPlayer();
Thread mt = new Thread(sf);
mt.start();
t1.start();
}
I just want an answer like everyone else :/
You'd be surprised how much I'd prefer to learn how to answer my own questions ;)
You will need to understand:
Performing Custom Painting
Painting in AWT and Swing
It wouldn't hurt to understand:
Reading/Loading an Image
Laying Out Components Within a Container
"How to add a background image" ...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setContentPane(new BackgroundPane());
frame.add(new OverlayPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class OverlayPane extends JPanel {
public OverlayPane() {
setOpaque(false);
setLayout(new GridBagLayout());
JLabel label = new JLabel("You'd be suprised who far a little knowledge will take you");
label.setForeground(Color.WHITE);
add(label);
}
}
public class BackgroundPane extends JPanel {
private BufferedImage backgroundImage;
public BackgroundPane() {
setLayout(new BorderLayout());
try {
backgroundImage = ImageIO.read(BackgroundPane.class.getResource("background.jpg"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return backgroundImage == null ? new Dimension(200, 200) : new Dimension(backgroundImage.getWidth(), backgroundImage.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgroundImage == null) { return; }
int x = (getWidth() - backgroundImage.getWidth()) / 2;
int y = (getHeight() - backgroundImage.getHeight()) / 2;
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(backgroundImage, x, y, this);
g2d.dispose();
}
}
}
You are going to want to learn about:
Concurrency in Swing
How to Use Swing Timers
How to Use Key Bindings
based on you the direction of this and all your other questions to date. They will help you avoid common pitfalls.
I don't doubt you'll have issues coming to grips with these concepts and I encourage you to have a play and if and when, post a question out them, specifically.
Related
I started programming in SWING class recently and I try to set Image (like Space) and on it image(like spaceShip) like background. I
would love for you to help me,
Here is my code
public class SpaceWar {
static JFrame frame = new JFrame("Space War");
static JPanel panel = new JPanel();
public static void main(String[] args) {
new SpaceWar();
//frame.setResizable(false);
frame.setVisible(true);
}
public SpaceWar() {
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
Dimension size
= Toolkit.getDefaultToolkit().getScreenSize();
frame.setPreferredSize(size);
frame.setLayout(null);
panel.setLayout(null);
panel.setBounds(frame.getPreferredSize().width/4,0,
frame.getPreferredSize().width/2,frame.getPreferredSize().height);
frame.add(panel);
frame.add(new Background());
spaceShip sp1 = new spaceShip();
panel.setBackground(Color.black);
panel.add(sp1);
System.out.println(panel.getPreferredSize().width);
}
}
class spaceShip extends JLabel{
static ImageIcon img = new ImageIcon("spaceShip.png");
public spaceShip(){
sizeIcon(100,100,img);
setIcon(img);
}
public static ImageIcon sizeIcon(int w,int h,ImageIcon image1){
Image image = image1.getImage(); // transform it
Image newimg = image.getScaledInstance(w,h, java.awt.Image.SCALE_SMOOTH); // scale it the smooth way
ImageIcon img1 = new ImageIcon(newimg); // transform it back
return img1;
}
}
class Background extends JPanel{
public void paint(Graphics g) { // paint() method
super.paint(g);
ImageIcon image = new ImageIcon("space.jpg");
Image bg = image.getImage();
g.drawImage(bg,0,0,null);
}
}
So, your "core" problem is the use of null layouts and a lack of understand of how components are sized and positioned. Having said that, if your aim is to make a game, this probably isn't the best approach anyway.
Instead, I'd focus on creating a "surface", onto which you can paint all your assets directly, this will give you much greater control.
Start by taking a look at Painting in AWT and Swing and Performing Custom Painting to get a better understanding how the paint system works and how you can work with it to perform custom painting.
I'd also avoid ImageIcon, it's not the best way to handle images, instead, take a look at ImageIO (Reading/Loading an Image), it will generate an IOException if the image can't be loaded and will return a fully realised image (unlike ImageIcon which off loads the image loading to a background thread).
For example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class MainPane extends JPanel {
private BufferedImage ufo;
private BufferedImage background;
private int horizontalPosition = 106;
public MainPane() throws IOException {
ufo = ImageIO.read(getClass().getResource("/images/ufo.png"));
background = ImageIO.read(getClass().getResource("/images/starfield.png"));
System.out.println("background = " + background);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
paintBackground(g2d);
paintUFO(g2d);
g2d.dispose();
}
protected void paintBackground(Graphics2D g2d) {
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
}
protected void paintUFO(Graphics2D g2d) {
int x = (getWidth() - ufo.getWidth()) / 2;
int y = (getHeight() - ufo.getHeight()) / 2;
g2d.drawImage(ufo, x, y, this);
}
}
}
The example makes use of embedded resources (something to read up on). Managing your assets this way will save you countless hours of wondering why they aren't loading/working. How you achieve this will come down to your IDE and build system, for example, Netbeans and Eclipse will allow you to add resources directly to the src directory, when you're not using maven.
At some point, you're going to want to learn about How to Use Swing Timers and How to Use Key Bindings
I draw an image which is my background image, everything is fine but when I'm trying to add some JButtons to the frame the whole business goes wrong the picture that I drew disappear and I see the original background.
The picture drawing looks like that:
public void paint(Graphics g){
g.drawImage(bg, 0, 0, null);
}
I guess my problem is something with the paint method, need to be mentioned that I'm extending the JFrame class.
edit:
Here are some pictures to demonstrate what I mean.
It first draw my image:
And when I move my mouse to the place that my buttons should have been drew, that's what I get:
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.URL;
import javax.imageio.ImageIO;
public class FrameWithBG {
public static void main(String[] args) throws Exception {
URL url = new URL("http://i.stack.imgur.com/OVOg3.jpg");
final BufferedImage bg = ImageIO.read(url);
Runnable r = new Runnable() {
#Override
public void run() {
JPanel c = new PanelWithBackgroundImage(bg);
c.setLayout(new GridLayout(0,5,16,16));
c.setBorder(new EmptyBorder(10, 10, 10, 10));
for (int ii = 1; ii < 26; ii++) {
c.add(new JButton("Button " + ii));
}
JFrame f = new JFrame(c.getClass().getSimpleName());
f.add(c);
f.pack();
f.setVisible(true);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}
class PanelWithBackgroundImage extends JPanel {
Image bg;
PanelWithBackgroundImage(Image bg) {
this.bg = bg;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bg, 0, 0, getWidth(), getHeight(), this);
}
}
I'd like to make a Java panel that creates objects where the user clicks. Since my actual application uses a MVC approach I'd like also for these objects to be able to repaint themselves when a model is changed, and provide menus to change their properties.
I think that the best way to control their x and y locations would be to take a canvas based approach whereby the JPanel calls a draw method on these objects from the paintComponent method. This however will only draw the shape on the canvas and does not add the object itself loosing all abilities to control object properties. I'd be very grateful if someone could tell me the best approach for what I want to do.
I've created some sample code which can be seen below. When clicked I'd like the circle to change colour, which is implemented using a MouseListener (it basically represents changing the models properties in this small example). Also I'd just like to make sure that zooming in/out still works with any sample code/advice can provide so I've added buttons to zoom the objects in and out as a quick test.
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.geom.Ellipse2D;
public class Main {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ExamplePanel panel = new ExamplePanel();
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
});
}
//I could not get this to with when it extended JLayeredPane
private static class ExamplePanel extends JPanel {
private static final int maxX = 500;
private static final int maxY = 500;
private static double zoom = 1;
private static final Circle circle = new Circle(100, 100);
public ExamplePanel() {
this.setPreferredSize(new Dimension(maxX, maxY));
this.setFocusable(true);
Button zoomIn = new Button("Zoom In");
zoomIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
zoom += 0.1;
repaint();
}
});
add(zoomIn);
Button zoomOut = new Button("Zoom Out");
zoomOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
zoom -= 0.1;
repaint();
}
});
add(zoomOut);
// add(circle); // Comment back in if using JLayeredPane
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.scale(zoom, zoom);
super.paintComponent(g);
circle.paint(g); // Comment out if using JLayeredPane
}
}
static class Circle extends JPanel {
private Color color = Color.RED;
private final int x;
private final int y;
private static final int DIMENSION = 100;
public Circle(int x, int y) {
// setBounds(x, y, DIMENSION, DIMENSION);
this.x = x;
this.y = y;
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
color = Color.BLUE;
}
#Override
public void mouseReleased(MouseEvent e) {
}
});
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(color);
g2.fillOval(x, y, DIMENSION, DIMENSION);
}
// I had some trouble getting this to work with JLayeredPane even when setting the bounds
// In the constructor
// #Override
// public void paintComponent(Graphics g) {
// Graphics2D g2 = (Graphics2D) g;
// g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// g2.setPaint(color);
// g2.fillOval(x, y, DIMENSION, DIMENSION);
// }
#Override
public Dimension getPreferredSize(){
return new Dimension(DIMENSION, DIMENSION);
}
}
}
As an aside I did try using a JLayeredPane(useful because I'd also like to layer my objects) but could not get my objects to even render. I know it has no default layout manager so tried calling setBounds in the circle in the constructor, but sadly it did not work. I know it's better to use a layout manager but can't seem to find one suitable for my needs!
Thanks in advance.
Don't override paint components, use paintComponent and don't forget to call super.paintComponent
A component already has a concept of "location", so when painting, the top left position of your component is actually 0x0
What you are doing is actually painting beyond the boundaries of you component
For example, if you place your Circle at 100x100 and then did...
g2.fillOval(x, y, DIMENSION, DIMENSION);
You would actually start painting at 200x200 (100 for the actual location of the component and 100 for you additional positioning).
Instead use
g2.fillOval(x, y, DIMENSION, DIMENSION);
And go back and try using JLayeredPane.
You could actually write your own layout manager that takes the location of the component and it's preferred size and updates the components bounds and then apply this to a JLayeredPane. This gives you the "benefits" of an absolute layout, but keeps you within how Swing works to update its components when things change.
You should also be careful with doing anything like...
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
The Graphics context is a shared resource. That means, anything you apply to, will still be in effect when the next component is painted. This may produce some strange results.
Instead try using...
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//...
g2.dispose();
Updated
For zooming I would take a closer look at JXLayer (or JLayer in Java 7)
The JXLayer (and excellent PBar extensions) have gone quite on the net, so you can grab a copy from here
(I tried finding a better example, but this is the best I could do with the limited time I have available)
Updated with working zooming example
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jdesktop.jxlayer.JXLayer;
import org.pbjar.jxlayer.demo.TransformUtils;
import org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel;
public class TestJLayerZoom {
public static void main(String[] args) {
new TestJLayerZoom();
}
public TestJLayerZoom() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JXLayer<JComponent> layer;
private DefaultTransformModel transformModel;
private JPanel content;
public TestPane() {
content = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridy = 0;
JLabel label = new JLabel("Hello");
JTextField field = new JTextField("World", 20);
content.add(label, gbc);
content.add(field, gbc);
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.REMAINDER;
final JSlider slider = new JSlider(50, 200);
slider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
int value = slider.getValue();
double scale = value / 100d;
transformModel.setScale(scale);
}
});
content.add(slider, gbc);
transformModel = new DefaultTransformModel();
transformModel.setScaleToPreferredSize(true);
Map<RenderingHints.Key, Object> hints = new HashMap<>();
//hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//hints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
//hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
layer = TransformUtils.createTransformJXLayer(content, transformModel, hints);
setLayout(new BorderLayout());
add(layer);
}
}
}
I've left the rendering hints in to demonstrate their use, but I found that they screwed with the positing of the cursor within the text field, but you might like to have a play
I'd just like to add that I fixed the zooming issue not in the way suggested by the answer, but just by keeping the line that applied a scaled transform call in the ExamplePanel paintComponent method:
g2.scale(zoom, zoom);
I thought that this was the nicest implementation since none of the components require any knowledge about zooming and it seemed far simpler than JLayer since I only required basic zooming functionalities.
I am trying to learn how to make a graphics program, but some of the methods in java AWT are giving me unexpected results.
I have made a window, and I place a rectangle and that works. I want another figure, a circle, to appear after 1 second. I have tried the wait(x) method, which just places the circle immediately, and now I have tried the Thread.sleep(x) method, which does work, however I get the following behaviour:
After one second, the circle is displayed on the screen, but after a split second it disappears again, and another split second later it reappears and stays on the screen. I don't want it to temporarily disappear. What am I doing wrong?
import java.awt.*;
class Example extends Canvas{
public static void main(String[] args){
Example graphicProgram = new Example();
Frame graphics = new Frame();
graphics.setSize(300, 300);
graphics.add(graphicProgram);
graphics.setVisible(true);
}
public Example(){
setSize(200, 200);
setBackground(Color.white);
}
public void paint(Graphics g){
g.fillRect(20, 150, 100, 100);
try{
Thread.sleep(1000);
} catch (Exception ex){
}
g.fillOval(150, 20, 100, 100);
}
}
Never call Thread.sleep from within a paint type of method. Doing this will make your GUI completely unresponsive.
Yes, do call the super painting method from within your painting method (as per muhammad's answer).
You should not call Thread.sleep(...) from the event thread either as this too will freeze your application.
You should skip doing AWT and move to Swing.
When you do so, do your drawing in the paintComponent(Graphics g) method of a JComponent or JPanel object.
Call the super's paintComponent(g) within your paintComponent method override.
Use a Swing Timer to do any delay or animation.
e.g.,
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class DrawFoo extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private static final Stroke BASIC_STROKE = new BasicStroke(3f);
private static final Color RECT_COLOR = Color.blue;
private static final Color OVAL_COLOR = Color.red;
private boolean drawCircle = false;
private int rectX = 20;
private int rectY = 150;
private int rectWidth = 100;
public DrawFoo() {
int delay = 1000;
Timer timer = new Timer(delay, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
drawCircle = true;
repaint();
}
});
timer.setRepeats(false);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(BASIC_STROKE);
g2.setColor(RECT_COLOR);
g.fillRect(rectX, rectY, rectWidth, rectWidth);
if (drawCircle) {
g2.setColor(OVAL_COLOR);
g.fillOval(rectY, rectX, rectWidth, rectWidth);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("DrawFoo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new DrawFoo());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
put this line as the first statment in your paint method super.paint(g);
it will be good to place also Graphics2D g2 = (Graphics2D)g; after above statment to use the improved performance and extra methods offered by Graphics2D
I'm working through some simple applications to get familiar with Swing and running into problems.
I'm attempting to have a frame containing an image (in a panel) along with buttons to zoom in/out from the image.
I have been able to make a frame with the added image work fine (albeit with some frame sizing issues, but that is another story), however, when I call the same component class to add it to a panel, nothing appears. I'm hoping one of you can help shed light on the situation.
CODE:
Image Frame - Is working as shown
class ImageFrame extends JFrame{
public ImageFrame(){
setTitle("Java Image Machine");
init();
pack();
}
public final void init(){
//ZoomPanel zoomPanel = new ZoomPanel();
//ImagePanel imagePanel = new ImagePanel();
ImageComponent component = new ImageComponent();
//this.add(zoomPanel, BorderLayout.CENTER);
this.add(component);
//this.add(imagePanel, BorderLayout.SOUTH);
}
}
However, using the ImagePanel or adding the ZoomPanel simultaneously with the direct ImageComponent call, does not:
class ImagePanel extends JPanel{
public ImagePanel(){
//setBorder(BorderFactory.createLineBorder(Color.black));
ImageComponent component = new ImageComponent();
add(component);
}
}
Component class:
class ImageComponent extends JComponent{
public ImageComponent(){
try{
image = ImageIO.read(new File("test1.bmp"));
}
catch ( IOException e ){
e.printStackTrace();
}
System.out.println("W: " + image.getWidth(this) + " H: " + image.getHeight(this));
}
public void paintComponent( Graphics g ){
super.paintComponent(g);
if (image == null)
return;
width = image.getWidth(this);
height = image.getHeight(this);
//System.out.println("Image should be painted");
g.drawImage(image, 0, 0, null);
}
private Image image;
public int width;
public int height;
}
It works fine for me ( I just tested the ImageComponent class):
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class Test {
/**
* Default constructor Test.class
*/
public Test() {
initComponents();
}
public static void main(String[] args) {
/**
* Create GUI and components on Event-Dispatch-Thread
*/
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Test test = new Test();
}
});
}
/**
* Initialize GUI and components (including ActionListeners etc)
*/
private void initComponents() {
JFrame jFrame = new JFrame();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//add ImageComponent to JFrame instance
jFrame.add(new ImageComponent());
//pack frame (size JFrame to match preferred sizes of added components and set visible
jFrame.pack();
jFrame.setVisible(true);
}
}
class ImageComponent extends JComponent {
private Image image;
public int width;
public int height;
public ImageComponent() {
try {
image = ImageUtils.scaleImage(300, 300, ImageIO.read(new URL("http://harmful.cat-v.org/software/_java/java-evil-edition.png")));
//image = ImageIO.read(new URL("http://harmful.cat-v.org/software/_java/java-evil-edition.png"));//uses images scale
} catch (Exception e) {
e.printStackTrace();
}
//so we can set the JPanel preferred size to the image width and height
ImageIcon ii = new ImageIcon(image);
width = ii.getIconWidth();
height = ii.getIconHeight();
}
//so our panel is the same size as image
#Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (image == null) {
return;
}
width = image.getWidth(this);
height = image.getHeight(this);
g.drawImage(image, 0, 0, null);
}
}
//class used for scaling images
class ImageUtils {
static Image scaleImage(int width, int height, BufferedImage filename) {
BufferedImage bi;
try {
bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(filename, 0, 0, width, height, null);
} catch (Exception e) {
return null;
}
return bi;
}
}
problem might be the path to your file, or the fact that JPanel width and height will not be the same as the pictures thus we override getPrefferedSize(...) of JPanel and return correct size according to Image
Have you tried adding repaint() calls after adding the appropriate components in?
i.e.
class ImagePanel extends JPanel{
public ImagePanel(){
//setBorder(BorderFactory.createLineBorder(Color.black));
ImageComponent component = new ImageComponent();
add(component);
repaint();
}
}
Also double check that you are adding the ImagePanel (containing the ImageComponent) to the ImageFrame, and calling .setVisible(True).