I'm learning Java, and I've converted File type into Image using IOException, but how can I use my new Image outside of try/catch?
try {
File obraz = new File("C:\\Users\\ender\\Pictures\\logo.jpg");
Image image = ImageIO.read(obraz);
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(image);
}
Because now IntelliJ does not recognize image.
In this case - as paintComponent will be called often, and you want to load the image just once, put the image in a field.
private Image image;
...() {
try {
File obraz = new File("C:\\Users\\ender\\Pictures\\logo.jpg");
image = ImageIO.read(obraz);
} catch (IOException ex) {
ex.printStackTrace();
}
}
...() throws IOException {
File obraz = new File("C:\\Users\\ender\\Pictures\\logo.jpg");
image = ImageIO.read(obraz);
}
#Override
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
if (image != null) {
g2.drawImage(image);
}
}
I have shown two solutions:
catching the exception as done now: but one should do something, give an error message to the user that file logo.jpg does not exist
passing the exception on by throws, often the better solution.
The convention is to use #Override as this catches typos like public void paintComponent(Graphics2D g) or public void painComponent(Graphics g).
Related
I used some of the information around this site to find out to use URLs to get images into a jar file; which I want to be able to be used alone. But when I make the jar file with BlueJ, only some images show up.
Its a blackjack game, and only the table canvas shows up, while no cards ever do. Here's the code:
THIS WORKS (the table):
public class TableComponent extends JLabel{
BufferedImage table;
public TableComponent(){
URL finalTable = getClass().getResource("blackjackTableCanvas.jpg");
try {
table = ImageIO.read(finalTable);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
super.paintComponent(g2);
g2.drawImage(table, 0, 0, null);
}...}
but this does not (the cards):
public class CardRender2 extends JComponent{
BufferedImage image;
String val;
String suit;
String filename;
public CardRender2(Card card) {
this.val = card.value.face;
this.suit = card.suit.toString();
filename = this.fetchCardFileLabel();
URL cardview = getClass().getResource("\\card deck\\" + filename + ".png");
try {
image = ImageIO.read(cardview);
} catch (IOException e) {
e.printStackTrace();
}
}
public CardRender2(){
this.val = null;
this.suit = null;
filename = "DEALER_FIRST_CARD";
URL cardview = getClass().getResource("\\card deck\\DEALER_FIRST_CARD.png");
try {
image = ImageIO.read(cardview);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
super.paintComponent(g2);
g2.drawImage(image, 0, 0, null);
}...}
my cards are in a folder in the directory I try to import into BlueJ, whereas the table is in the directory root. There are 53 cards in there (incl dealer hidden card) and I'd rather not put all of then in the root. I tried to implement them similarly. How can I do this?
looks like changing from
URL cardview = getClass().getResource("\\card deck\\DEALER_FIRST_CARD.png");
to
URL cardview = getClass().getResource("card deck/DEALER_FIRST_CARD.png");
did the trick.
I have been trying this for hours now. I have a class that extends JComponent, and in its paintComponent I am trying to draw an image, but I am not being able to. Here is my code:
public class Main extends JComponent{
public static void main(String[] args) {
Main main = new Main();
JFrame frame = new JFrame(Info.getGameTitle());
frame.add(main);
frame.setSize(Info.getWidth(), Info.getHeight());
frame.setResizable(false);
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.out.println("Window closed");
System.exit(0);
}
});
frame.setAlwaysOnTop(true);
frame.setFocusable(true);
frame.setAutoRequestFocus(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Graphics g = main.getGraphics();
main.paint(g);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage image = null;
try {
image = ImageIO.read(new FileInputStream("images/01.jpg"));
}catch(FileNotFoundException e) {
System.out.println("Could not find file!");
e.printStackTrace();
}catch(IOException e) {
System.out.println("Could not read file!");
e.printStackTrace();
}
g.drawImage(image, 0, 0, this);
}
}
It is not throwing any exceptions, so the image appears to be loaded. However, nothing appears on the screen. If I try to draw shapes or text, that works fine.
What am I doing wrong?
EDIT: Now I have supplied a working example.
Be aware that your JComponent may be painted hundreds of times per second,
for example when it is partially obscured by another moving window.
So, performance of the paint methods is important, or else you get a "laggy" GUI.
Therefore I suggest to separate the time-consuming part (i.e. reading the image file) from the JComponent.
public class ImageComponent extends JComponent {
private BufferedImage image;
public void setImage(final BufferedImage image) {
this.image = image;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null)
g.drawImage(image, 0, 0, this);
}
}
Somewhere else in your code you read the image file and set it into the component:
BufferedImage image = null;
try {
image = ImageIO.read(new File(fullpathname+"/01.jpg"));
}catch(Exception e) {
System.out.println("Could not read file!");
e.printStackTrace();
}
ImageComponent component = new ImageComponent();
component.setImage(image);
Graphics g = main.getGraphics();
main.paint(g);
No, no, no, NO, NO! A infinite times NO! This is not how painting works!
Take a look at Performing Custom Painting and Painting in AWT and Swing for a better understanding of how painting works in Swing.
getGraphics can return null and will only return the last used context to paint the component, anything painted to it will be erased on the next paint cycle.
There is never a good reason to call paint manually, just don't do it.
You should be do something more along the lines of
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage img = null;
public TestPane() {
try {
img = ImageIO.read(new FileInputStream("..."));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (img != null) {
g2d.drawImage(img, 0, 0, this);
}
g2d.dispose();
}
}
}
If your image is still not showing up, I suspect that the image is misplaced.
new FileInputStream("images/01.jpg")
suggests that the image resides within the current directory from where the program is been executed, this is not always the same as where the program resides.
You can use System.getProperty("user.dir") to determine the current "working" directory and compare it to where you think the program resides. You can also use File#exists to test if the file exists or not, although, I would have expected the code to throw an IOException if that were the case.
A better long term solution would be to embedded the image within application (typically including it in the Jar), this removes the above issues.
In that case you'd need to use...
ImageIO.read(getClass().getResource("/images/01.jpg"));
to load the image
Try this:
Image image = ImageIO.read(new File(file));
g.drawImage(image, 0, 0, this);
Try this
BufferedImage image = null;
try {
image = ImageIO.read(new File(fullpathname+"/01.jpg"));
}catch(Exception e) {
System.out.println("Could not read file!");
e.printStackTrace();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
read throws more exceptions
IllegalArgumentException - if input is null.
IOException - if an error occurs during reading.
so catching the more general one (Exception) will cover it
I have written the following example to give something runnable of a problem I am having. When you press the button the controlWhichImage switches to 2. The problem is that when it switches from the original image to a copy the image disappears.
public class PainterDemo01 extends JPanel implements ActionListener {
BufferedImage createdImage;
BufferedImage img;
int controlWhichImage;
JFrame mainFrame;
JButton changePicture;
public PainterDemo01(){
changePicture = new JButton("Press");
changePicture.addActionListener(this);
controlWhichImage = 1;
mainFrame = new JFrame();
mainFrame.add(this);
this.add(changePicture);
mainFrame.setPreferredSize(new Dimension(600,600));
mainFrame.setVisible(true);
mainFrame.pack();
img = loadImage();
}
public BufferedImage loadImage(){
img = null;
try {
img = ImageIO.read(new File("/home/gerry/Desktop/100_0647.JPG"));
} catch (IOException e){
System.out.println("no file here");
}
return img;
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
loadImage();
if (createdImage == null){
this.createdImage = new BufferedImage(this.getWidth(),this.getHeight(), BufferedImage.TYPE_INT_ARGB);
}
Graphics g2 = this.createdImage.getGraphics();
if (controlWhichImage == 1){
g2.drawImage(img,0,0,img.getWidth(),img.getHeight(),null);
g.drawImage(img, 0,0,img.getWidth(),img.getHeight(),null);
g2.dispose();
}
if (controlWhichImage == 2){
//Draw bufferedImage on to to JPanel
g.drawImage(this.createdImage,this.createdImage.getWidth(),this.createdImage.getHeight(),null);
}
}
#Override
public void actionPerformed(ActionEvent e){
controlWhichImage = 2;
repaint();
}
public static void main(String[] args) {
// TODO code application logic here
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new PainterDemo01().setVisible(true);
}
});
}
}
The problem is that getGraphics (or better named createGraphics) is called outside the if statement, also for 2, hence both causing a resource leak (as no g2.dispose is called), and also a clean slate.
if (controlWhichImage == 1) {
Graphics g2 = createdImage.getGraphics();
g2.drawImage(img,0,0,img.getWidth(),img.getHeight(),null);
g2.dispose();
}
Also do things like loading the image outside the paint code.
See this question if you want to know how to copy an BufferedImage:
How to copy BufferedImage
Of course! You have to go and paint the image at the outskirts. Please use this
g.drawImage(this.createdImage, 0, 0, this.createdImage.getWidth(),this.createdImage.getHeight(),null);
Use img obj since its already instantiated but not createdImage obj, createdImage contains null since its just declared but not instantiated. If you use createdImage obj means if you perform any operation upon createdImage obj then you will get NullPointerException.
Graphics g2 = this.img.getGraphics();
---------
I'm trying to draw on a BufferedImage from a thread, then displaying said image on a canvas.
Everything works fine when I alter the BufferedImage from within the paintComponent-method of the Canvas, but as soon as I try to alter it from a running thread - nothing happens.
In other words; If I copy the Graphics2D-code from the thread to the paintComponent-method, everything works fine.
A snippet of my code (some of the variables/values are temporary):
class DrawThread implements Runnable
{
#Override
public void run()
{
while(true)
{
Graphics2D g2d = canvas.getImage().createGraphics();
g2d.setColor(Color.GREEN);
Rectangle rect2 = new Rectangle(10, 0, 20, 20);
g2d.draw(rect2);
g2d.dispose();
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
class RectangleCanvas extends Canvas
{
public BufferedImage image;
public RectangleCanvas()
{
this.setPreferredSize(new Dimension(280, 280));
image = new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB);
}
public synchronized BufferedImage getImage()
{
return this.image;
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(getImage(), 0, 0, this);
}
}
By unsing netbeans ide , I created a JDesktopPane inside the JFrame. and I cannot change the color of the jdesktopPane.. I tried all I can. But when I open the JFrame .. the JDesktopPane inside that JFrame is in some blue color background.
Please help me to change the background of JDesktopPane
I'm going to assume you're using GUI Builder with the default Nimbus look and feel (because you said you've tried everything, and I'll assume you've tried setBackground). The look and feel has the background set. But you have options around it.
You can just paint the background. You want to look at this answer for how to edit the auto-generated code. Then you can just to this, when you edit the code. Don't forget to hit ctrl+shift+I afterwards, to resolve all imports. I'm too lazy to write fully qualified names.
jDesktopPane1 = new javax.swing.JDesktopPane() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
}
};
If you want an image, you can paint an image
jDesktopPane1 = new javax.swing.JDesktopPane() {
private Image image;
{
try {
image = ImageIO.read(new URL("http://www.hdbackgroundspoint.com/wp-content/uploads/2013/12/16/345t34.jpeg"));
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
}
};
You could also override the Nimbus default DesktopPane[Enabled].backgroundPainter. See Nimbus Defaults here
public static void main(String[] args) {
try {
for (UIManager.LookAndFeelInfo laf : UIManager
.getInstalledLookAndFeels()) {
if ("Nimbus".equals(laf.getName())) {
UIManager.setLookAndFeel(laf.getClassName());
UIManager.getLookAndFeelDefaults().put(
"DesktopPane[Enabled].backgroundPainter",
new DesktopPainter());
}
}
} catch (Exception e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JDesktopPaneDemo();
}
});
}
static class DesktopPainter implements Painter<JComponent> {
private Image image;
public DesktopPainter() {
try {
image = ImageIO.read(new URL("http://www.hdbackgroundspoint.com/wp-content/uploads/2013/09/hh.jpeg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void paint(Graphics2D g, JComponent object, int width, int height) {
g.drawImage(image, 0, 0, width, height, null);
}
}