I've been struggling to get an image to show up for some time now. Ive read a few different things, and all of them seem to have different ways of showing images. Can someone tell me what I'm doing wrong? I'm trying to make a program that uses 2 classes to make a picture show up in a frame. I guess what I don't understand still is what a Graphics object is, what a Graphics2D object is and how its different, and what method from what class do I call in order to make an image show up. Here is my code:
public class Smiley {
private BufferedImage smileyFace;
private Graphics2D renderWindow;
private Dimension smileyPosition;
private File smileyFile;
public Smiley() {
try{
smileyFile = new File("C:\\Users\\MyName\\Desktop\\smiley.png");
smileyFace = ImageIO.read(smileyFile);
}
catch (Exception e){
System.out.println("There was an error finding or reading the file \" smiley.png.\"");
}
MainScreen.graphicPane.drawImage(smileyFace,50,50, null);
}
and the second class:
public class MainScreen extends JFrame{
public static MainScreen ms;
public static Graphics2D graphicPane;
public static void main (String[] args){
MainScreen ms = new MainScreen();
Smiley newSmiley = new Smiley();
}
public MainScreen(){
super("Main Screen Window");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setSize(500,800);
this.getContentPane().setBackground(Color.black);
graphicPane = (Graphics2D) this.getContentPane().getGraphics();
}
}
the program compiles with no errors and nothing is reported back to me about not finding the file.
Your going to need some sore of paint method. For that you will require a Component to paint on. You need to learn a GUI framework, like Swing. There are clear compoents you can paint on like a JPanel. With that panel you need to override its paintComponent method.
The Graphcics object is what the component uses to actually paint the graphic onto the component.
The Graphics2D object just extends the capabilities of the Graphics object.
You should take a look at the Swing tuorial and the **Graphics toturial
To get your program running though you would do something like this
public class DrawPanel extends JPanel {
BufferedImage smileyFace;
public DrawPanel() {
try{
smileyFile = new File("C:\\Users\\MyName\\Desktop\\smiley.png");
smileyFace = ImageIO.read(smileyFile);
}
catch (Exception e){
System.out.println("There was an error finding or reading the file \" smiley.png.\"");
}
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(smileyFace,50,50, this);
}
#Override
public Dimension getPreferredSize(){
return new Dimension(500, 500);
}
}
Then you can instantiate that panel in another class, adding it to a JFrame to run it
public class Main {
public static void main(String[] args) {
SwingUtiliites.invokeLater(new Runnable(){
public void run() {
JFrame frame = new JFrame();
frame.add(new DrawPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}
You are calling this in your constructor for your Smiley class.
MainScreen.graphicPane.drawImage(smileyFace,50,50, null);
If you are going to paint the image yourself you need to override paintComponent() in a component that gets added to your main screen.
Or just add the image to a JLabel that you added to the main screen.
You draw image in wrong way.
For using drawImage() you need to use that in paintComponent() method of JComponent(for example JPanel), examine next code:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.beans.Transient;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example extends JFrame {
public Example() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Smiley());
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) {
new Example();
}
class Smiley extends JPanel{
private BufferedImage smileyFace;
Smiley(){
try {
File smileyFile = new File("C:\\Users\\MyName\\Desktop\\smiley.png");
smileyFace = ImageIO.read(smileyFile);
} catch (Exception e) {
System.out
.println("There was an error finding or reading the file \" smiley.png.\"");
}
}
#Override
#Transient
public Dimension getPreferredSize() {
return new Dimension(smileyFace.getWidth(),smileyFace.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(smileyFace, 0,0, this);
}
}
}
or you can add your image to JLabel and that do all for you, change Smile class like next:
class Smiley extends JPanel{
Smiley(){
ImageIcon icon = new ImageIcon("C:\\Users\\MyName\\Desktop\\smiley.png");
JLabel l = new JLabel(icon);
add(l);
}
}
ALso read more about customPaintings.
Related
I need help to add an image to the separate JFrame, but I can't seem to get it to work. Like I want the image to open in a separate frame like when I run this code it opens a blank JFrame. d help to add an image to the separate JFrame, but I can't seem to get it to work. Like I want the image to open in a separate frame like when I run this code it opens a blank JFrame.
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import javax.swing.JFrame;
class PPJJ extends JFrame implements ActionListener, KeyListener
{
public void paint(Graphics g) {
Toolkit t=Toolkit.getDefaultToolkit();
Image i=t.getImage("tenor.gif");
g.drawImage(i, 120,100,this);
}
public static void main(String[] args)
{
JFrame frame = new JFrame("VOLUNTEER FOR THING");
PPJJ obj = new PPJJ();
JPanel panel = new JPanel();
JLabel lname = new JLabel("Enter your name here");
JTextField tname = new JTextField(21);
JButton btn = new JButton("Click");
btn.addActionListener(obj);
tname.addKeyListener(obj);
panel.add(lname);
panel.add(tname);
panel.add(btn);
frame.add(panel);
frame.setSize(300, 130);
frame.show();
frame.setLocationRelativeTo(null);
PPJJ m = new PPJJ();
JFrame f =new JFrame();
//f.add(m);
f.setSize(500,500);
f.setVisible(true);
frame.add(new JLabel(new ImageIcon("volunteer.jpeg")));
}
public void actionPerformed(ActionEvent e)
{
String s = e.getActionCommand();
if(s.equals("Click here")){
JOptionPane.showMessageDialog(null , "THANKS FOR SIGNING UP");
}
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode()==KeyEvent.VK_ENTER){
JOptionPane.showMessageDialog(null , "THANKS FOR SIGNING UP");
}
}
#Override
public void keyReleased(KeyEvent arg) {}
#Override
public void keyTyped(KeyEvent arg) {}
}
Oh, animated GIFs 😓.
Image handling isn't simple in most cases, but animated GIFs are whole other level of pain ... I mean fun.
Normally, I prefer to use ImageIO.read, but ImageIO returns a BufferedImage and it's not (easily) possible to then render animated GIFs through it.
The "easy" route of displaying animated GIFs is by using Image or ImageIcon.
The first step is get your image "embedded" within your application context (assuming that you're not allowing the user to select the image). How this is done will depend on your IDE and build system (Eclipse and Netbeans allow you to simply include them in the src folder, when you're not using Maven).
Next, you want to use Class#getResource to obtain a URL reference to the embedded resource. In this case, you can use ImageIO.read, ImageIcon(URL) or Toolkit#getImage(URL) to load the image. But, as I've said, ImageIO.read isn't going to help you.
Next, you need a component which can render the image, lucky for us, Swing can do this pretty much auto magically for use, all we need to do is make sure the component is passed as the ImageObserver reference, for example...
public class BackgroundPane extends JPanel {
private Image image;
public BackgroundPane(Image image) {
this.image = image;
}
#Override
public Dimension getPreferredSize() {
Image image = getBackgroundImage();
return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(this), image.getHeight(this));
}
public Image getBackgroundImage() {
return image;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Image image = getBackgroundImage();
if (image == null) {
return;
}
int x = (getWidth() - image.getWidth(this)) / 2;
int y = (getHeight() - image.getHeight(this)) / 2;
g.drawImage(image, x, y, this);
}
}
Also, note, JLabel supports animated GIFs via it's icon property as well, but look at How to set a background picture in JPanel for reasons why you shouldn't use a JLabel as a background container.
Now, all we need to do is load the image, pass it to the background, add what ever content we need to the component and show it, easy, or at least it should be. ImageIcon and Toolkit#getImage both off load the reading of the image to a background thread, so inspecting the images dimensions before the image is loaded will return 0x0 😓, so, we need to wait for it to load (this is why I prefer ImageIO.read as it won't return until the image is loaded or an error occurs).
Something like...
Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/images/kitty.gif"));
BackgroundPane backgroundPane = new BackgroundPane(image);
// Did I mention I had this workflow, but ImageIO doesn't
// support animated images, without a lot of work
MediaTracker mt = new MediaTracker(backgroundPane);
mt.addImage(image, 0);
mt.waitForAll();
// The image is now loaded, hooray for us
Runnable example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JLabel;
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 {
Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/images/kitty.gif"));
BackgroundPane backgroundPane = new BackgroundPane(image);
// Did I mention I had this workflow, but ImageIO doesn't
// support animated images, without a lot of work
MediaTracker mt = new MediaTracker(backgroundPane);
mt.addImage(image, 0);
mt.waitForAll();
backgroundPane.setLayout(new GridBagLayout());
JLabel label = new JLabel("All your kitty is belong to us");
label.setForeground(Color.WHITE);
backgroundPane.add(label);
JFrame frame = new JFrame();
frame.add(backgroundPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class BackgroundPane extends JPanel {
private Image image;
public BackgroundPane(Image image) {
this.image = image;
}
#Override
public Dimension getPreferredSize() {
Image image = getBackgroundImage();
return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(this), image.getHeight(this));
}
public Image getBackgroundImage() {
return image;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Image image = getBackgroundImage();
if (image == null) {
return;
}
int x = (getWidth() - image.getWidth(this)) / 2;
int y = (getHeight() - image.getHeight(this)) / 2;
g.drawImage(image, x, y, this);
}
}
}
Please note...
If you're not using an animated GIF, then you can just use ImageIO.read instead of Toolkit#getImage and you won't need to wait (as ImageIO.read works in the current thread), in which case the code would look more like...
try {
BackgroundPane backgroundPane = new BackgroundPane(ImageIO.read(getClass().getResource("/images/kitty.gif")));
backgroundPane.setLayout(new GridBagLayout());
JLabel label = new JLabel("All your kitty is belong to us");
label.setForeground(Color.WHITE);
backgroundPane.add(label);
JFrame frame = new JFrame();
frame.add(backgroundPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
(the BackgroundPane code doesn't change)
I was working on this lab in class and when I tried changing the background color it would stay at its default of white can someone please explain where I my programming went wrong.
import javax.swing.*;
import java.awt.*;
public class DemoPoly extends JFrame {
// constructor
public DemoPoly() {
// defines Frame characteristics
int size = 300;
setSize(size,size);
setTitle("a random window");
getContentPane().setBackground(Color.red);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main (String[] args){
// instantiates a JFrame
// exits on close (opional)
JFrame object = new DemoPoly();
}
public void paint (Graphics g){
// This provides the Graphics object g, where
// you are going to use you graphics primitive
// to paint on the content pane of the frame.
int[] arr = {0,100,100,0};
int[] yarr = {0,0,100,100};
Square object = new Square(arr,yarr,Color.red);
AbstractPolygon randSquare = new Square(arr, yarr, Color.red);
}
I see a couple of problems in your code:
Extending JFrame is like saying your class is a JFrame, JFrame is a rigid container, instead create your GUI based on JPanels. See Java Swing extends JFrame vs calling it inside of class for more information.
You're breaking the paint chain by removing the super.paint(g) call on the paint(...) method. When changing your GUI to extend JPanel instead of JFrame you should use the paintComponent(...) method instead. Take the Lesson: Performing Custom Painting in Swing.
You forgot to add #Override notation on the paint(...) method.
You're not placing your program on the Event Dispatch Thread (EDT) which could cause threading issues.
You can solve this by changing your main() method like this:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//Your constructor here
}
});
}
Instead of setting the JFrame size, override the getPreferredSize() method and call pack(). See Should I setPreferred|Maximum|MiniumSize in Java Swing?. The general consensus says yes.
Your problem gets solved by adding
super.paint(g);
on the paint(...) method:
#Override
public void paint(Graphics g) {
super.paint(g); //Never remove this
//Your code goes here
}
With all the above recommendations taken into account, your code should look like this now:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class DemoPoly {
private JFrame frame;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new DemoPoly().createAndShowGui();
}
});
}
public void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
CustomPanel cp = new CustomPanel();
cp.setBackground(Color.RED);
frame.add(cp);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}
class CustomPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
}
Which produces this output (and is the same output that you'll get with your current code but better because it gives you more control over your components)
I'm don't understand your question. But here is code for change your background to RED;
public class DemoPoly extends JFrame {
public DemoPoly() {
// defines Frame characteristics
int size = 300;
setSize(size, size);
setTitle("a random window");
//change background here
getContentPane().setBackground(Color.red);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
// instantiates a JFrame
// exits on close (opional)
JFrame object = new DemoPoly();
}
}
Your code is well. Maybe use #override in your paint method.
I've created a JFrame.
Inside this JFrame, I've created a JPanel.
Inside this JPanel I've created another JPanel (lets call it "A").
I've drawn in "A" a rectangle, and wanted to create buttons using graphics.
There is no rectangle in my gui. I could see that the paintComponent() method inside "A" is not being invoked.
Code:
The JPanels: (the child JPanel is inner class)
public class MemoryPanel extends JPanel {
public MemoryPanel(){
setPreferredSize(new Dimension(350,448));
}
#Override
public void paintComponent(Graphics g) {
//POSITIONING
setLayout(new BorderLayout());
//CREATE MEMORY BUTTONS
MemButton a=new MemButton();
//Drawing Rectangles for Memory
add(a,BorderLayout.CENTER);
}
private class MemoryButton extends JPanel{
public MemoryButton(){
setLayout(null);
setPreferredSize(new Dimension(87,40));
}
#Override
public void paintComponent(Graphics g){
Graphics2D td= (Graphics2D)g;
td.drawRect(0, 0, 20, 20);
}
}
}
You should program the JButtons first in order for your graphics to work as buttons. I belive this post will help you with that:
Creating a custom button in Java
I you want a rectangle to be the background for your buttons you can draw it in your main panel and add the buttons on it. Try using different Layouts to mantain some order.
I've made a simple GUI to test your code and the rectangle appears correctly.
I made no relevant changes in the code that you posted.
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class SimpleJFrameProgram extends JFrame {
private static final long serialVersionUID = 1L;
public SimpleJFrameProgram() {
super("TEST");
initComponents();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
private void initComponents() {
MemoryPanel memoryPanel = new MemoryPanel();
this.add(memoryPanel);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
new SimpleJFrameProgram();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
I've applyed minor changes to your MemoryPanel: replaced MemButton by your MemoryButton and fill the rectangle in red to improve its visibility for the test. Without this last change, the rectangle appears too.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class MemoryPanel extends JPanel {
public MemoryPanel(){
setPreferredSize(new Dimension(350,448));
}
#Override
public void paintComponent(Graphics g) {
// POSITIONING
setLayout(new BorderLayout());
// CREATE MEMORY BUTTONS
MemoryButton a = new MemoryButton();
// Drawing Rectangles for Memory
add(a,BorderLayout.CENTER);
}
private class MemoryButton extends JPanel{
public MemoryButton(){
setLayout(null);
setPreferredSize(new Dimension(87,40));
}
#Override
public void paintComponent(Graphics g) {
Graphics2D td = (Graphics2D) g;
td.setColor(Color.red);
td.fillRect(0, 0, 20, 20);
}
}
}
This is the obtained result:
Maybe your problem is located on initializing the parent JFrame.
Changing the class name of MemoryButton fixed it.
I had another package with the same class name.
I searched all over the Internet but could not find out why the circle is appears to be distorted beyond the middle of the JFrame(sorry,no image because i needed 10 reputation to post images).
I checked my code but found no errors.I'm a newbie to java GUI programming .
This is my code so far:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class test1 extends JPanel implements MouseMotionListener
{
private static final long serialVersionUID = -2068330714634802982L;
public int Mousex,Mousey;
public void init()
{
addMouseMotionListener(this);
}
public void mouseMoved(MouseEvent e)
{
Mousex=e.getX();
Mousey=e.getY();
repaint();
}
public void mouseDragged(MouseEvent e){}
public void paintComponent(Graphics g)
{
Graphics2D g2=(Graphics2D)g;
g2.setColor(Color.GREEN);
g2.fillOval(Mousex,Mousey,50,50);
}
public static void main(String[] args)
{
test1 t=new test1();
JFrame frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1305,650);
frame.setLocationRelativeTo(null);
frame.getContentPane().add(t);
frame.setResizable(true);
frame.setVisible(true);
}
}
You need to call
t.init();
to register the MouseMotionListener. Also super.paintComponent(g); in the needs to be invoked in the paintComponent method to repaint the parent container otherwise the last rectangle wont be clearly visible.
You are never calling init() on your panel so you don't add the MouseMotionListener to the panel. Try adding
t.init();
after creating your panel object. Alternatively, add a constructor to your class that adds the MouseMotionListener instead, so it's adden right when you create an object of the class:
public test1 () {
addMouseMotionListener(this);
}
This is for an assignment, so I'd rather not ask for help, but I can't seem to see what I'm doing wrong. The code will eventually create a window, with an image as the background, and then using information in a text file, place other images at specific points, and the user can zoom in.
At the moment I'm just trying to get an image displayed onto a JPanel inside a JFrame, and I can't seem to get it to work. Could somebody please point out what exactly I'm doing that's leading to the image not displaying?
Code for Map class:
import javax.swing.*;
public class Map extends JPanel
{
static final long serialVersionUID = 1;
public Map()
{
}
public JPanel createContentPane()
{
//Creating a base JPanel to place everything on
JPanel rootGUI = new JPanel();
//Setting the Layout Manager to null to place everything manually
rootGUI.setLayout(null);
rootGUI.setOpaque(true);
return rootGUI;
}
private static void createAndShowGUI()
{
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Test for image");
//Create and set up the content pane
Map demo = new Map();
frame.setContentPane(demo.createContentPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setResizable(false);
Hospital hDemo = new Hospital();
frame.add(hDemo);
frame.setVisible(true);
}
public static void main(String[] Args)
{
//Schedule a job for the event-dispatching thread
//Creating and showing this applications GUI
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
And Code for the hospital class:
import javax.swing.*;
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
public class Hospital extends JPanel
{
static final long serialVersionUID = 2;
public static BufferedImage hospitalImage;
public Hospital()
{
super();
try
{
hospitalImage = ImageIO.read(new File("src\\hospital.jpg"));
}
catch (IOException ex)
{
//Not handled
}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(hospitalImage, 50, 50, this);
repaint();
}
}
You haven't defined the size of your Hospital Panel.
update to:
public Hospital()
{
super();
setSize( /* size */ );
try
{
hospitalImage = ImageIO.read(new File("src\\hospital.jpg"));
}
catch (IOException ex)
{
//Not handled
}
}
or use a different layoutManager in your JFrame/ContentPane like Borderlayout
in that case you could add the Hospital to your Frame as
frame.add(hDemo, BorderLayout.CENTER);
visual guide to layoutmanagers
Problem is in path you are passing here: hospitalImage = ImageIO.read(new File("src\\hospital.jpg"));
Easy solution would be to load your image as a stream:
InputStream stream = getClass().getResourceAsStream("hospital.jpg");
hospitalImage = ImageIO.read(stream);
stream.close();