Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm new in Java and currently my level is around printing text. Even though, I wanted to start with graphical content but sadly I didn't be able to do it.
I began with JFrame and everything went well but when I had to print images I had problem. Thanks to YouTube I could copy this piece of code where shows clearly (not enough for me, though) how to print an image in a JFrame.
import java.awt.Graphics;
import javax.swing.*;
public class Main extends JPanel{
public static void main(String[] args){
JFrame j = new JFrame("Image");
j.setSize(1080,720);
j.setVisible(true);
j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
j.add(new Main());
}
public void paintComponent(Graphics g){
super.paintComponent(g);
ImageIcon i = new ImageIcon("C:\\Users\\Hello\\Pictures\\picture.jpg");
i.paintIcon(this, g, 0, 0);
}
}
I honestly don't understand that. I looked for explanations on internet but no answer has really helped me out. What I don't comprehend is basically j.add(new Main()) (are we linking the same class?) and paintComponent(Graphics g)...
I don't think I've seen so many errors in a supposed teaching example.
Here's the rewritten code. You have to put the image in the same directory as the Java code to read the image.
package com.ggl.testing;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DrawImage implements Runnable {
#Override
public void run() {
JFrame j = new JFrame("Image");
j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
j.add(new ImagePanel(getImage()));
j.pack();
j.setLocationByPlatform(true);
j.setVisible(true);
}
private Image getImage() {
try {
return ImageIO.read(getClass().getResourceAsStream(
"StockMarket.png"));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new DrawImage());
}
public class ImagePanel extends JPanel {
private static final long serialVersionUID = -2668799915861031723L;
private Image image;
public ImagePanel(Image image) {
this.image = image;
this.setPreferredSize(new Dimension(image.getWidth(null), image
.getHeight(null)));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
}
}
Here are the important concepts to take from this code.
Always start a Java Swing application with a call to the SwingUtilities invokeLater method. This puts the creation and updates of the Swing components on the Event Dispatch thread (EDT).
As others have mentioned, read the images before you try and display them. This code will abend if the image is missing. This code will also work when you package your Java class in a JAR file, along with the image.
You don't set any sizes. You let the JFrame and JPanels calculate their own sizes using Swing layouts. In this particular example, the JPanel takes on the size of the image you read, and the JFrame is just large enough to hold the image JPanel.
You use Swing components. You only extend a Swing component when you want to override a method in the class. In this example, we used a JFrame and extended a JPanel.
Related
I'm following a Java course, and the current idea is to draw an image using Java Graphics2D. I'm following the steps one by one, but it seems not to be drawing anything. The panel is shown within the frame and everything is correct, but the image is not drawn. I'm using Java 15 and the course is Java 13.
JPanel class code:
public class MyPanel extends JPanel implements ActionListener {
Image ball;
int x = 0;
int y = 0;
MyPanel(){
this.setPreferredSize(new Dimension(PANEL_WIDTH,PANEL_HEIGHT));
this.setBackground(Color.BLACK);
ball = new ImageIcon("ball.png").getImage();
}
public void paint(Graphics g){
Graphics2D G2D = (Graphics2D) g;
G2D.drawImage(ball,x,y,null);}
JFrame class code:
public class MyFrame extends JFrame{
MyPanel panel;
MyFrame(){
panel = new MyPanel();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(panel);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
Main class code:
new MyFrame();
I picked out most of the relevant code.
First, I recommend reading through Performing Custom Painting and Painting in AWT and Swing to get a better idea of how painting in Swing should work.
I then suggest reading through Reading/Loading an Image
The "problem" with ImageIcon is that
It doesn't report any errors if the load fails
It loads the image in a second thread, which means you don't know (easily) when it's available
ImageIO on the hand will throw an error if the image can't be loaded, which is much easier to diagnose, and will only return AFTER the image is fully loaded and available.
One concept which can be hard to grasp when your starting is the concept of "embedded" resources. Java allows you to package "resources" along with your code. These resources live within the context of your programs class path and make it MUCH easier to load when compared to having to deal with external files.
Have a look Packaging and accessing run-time resources in a runnable Jar for some basics.
Depending on the IDE you're using, it's usually pretty easy to "copy" these resources into your project/src and allow the IDE to package itself.
The problem with a question like this is it's very, very hard for anyone to truely diagnose, as there are so many reasons why the image might not have loaded and the solution is usual one of trial and error.
Me, I'd start by just drawing some lines/rectangles and make sure that paint is been called. I'd then look at things like the image's size, to make sure it's not something like 0x0.
Runnable example
This is a simple runnable example based on comments I made above. I'm using NetBeans and the image was stored in the "Source Package" (so, along with the other source code) under the /images package
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage beachBall;
public TestPane() {
try {
beachBall = ImageIO.read(getClass().getResource("/images/BeachBall.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (beachBall == null) {
return;
}
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - beachBall.getWidth()) / 2;
int y = (getHeight() - beachBall.getHeight()) / 2;
g2d.drawImage(beachBall, x, y, this);
g2d.dispose();
}
}
}
It really looks like your image is not loaded.
As #MadProgrammer just told, new ImageIcon("ball.png") does not raise any error, and getImage() will always return something (not null), even if the file is not properly loaded.
To make sure your image is available, you can try ball.getWidth(null), and
if it returns -1, then something went wrong.
You can check the root path used by the JVM ("execution" location) with System.getProperty("user.dir"), the image file has to be exactly in this folder.
I tried your code with java 1.8 and it works well.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm very new to programming. I just started today and am following a book called learning java by Patrick Neimeyer and Daniel Leuck.
It started by asking me to create the Hello World ! programme, and did this by placing it in a JFrame which was all done in one class, it is now asking me two create another class in which will use a JComponent. I've tried creating another class and have just ended up going around in circles with errors.
This is my previous attempt. Can someone explain please what I'm meant to do?! I know it is fairly basic, but I am struggling.
It's telling me that the new code for the class is:
import java.awt.*;
class HelloComponent extends JComponent {
public void paintComponent( Graphics g ) {
g.drawString( "Hello, Java!", 125, 95 );
}
}
Where do I add this?
This is a rather perplexing way to start programming in Java. Even so, in this instance why would you not use a JLabel rather than creating your own JComponent?
In any case, as some of the comments already said, you need to add your JComponent to a JFrame.
An example below:
Example JFrame class
This class extends JFrame rather than creating and using a JFrame object. It also includes the main method as well, just to avoid another class. The main method runs the GUI on the event dispatch thread. This part is important, but not so much for a beginner.
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class ExampleFrame extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ExampleFrame frame = new ExampleFrame();
frame.createAndShow();
}
});
}
public void createAndShow() {
getContentPane().add(new HelloComponent());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Hello World Example");
pack();
setVisible(true);
}
}
HelloComponent
As before with your version, but sets the preferred size so that when the JFrame is 'packed' it sizes to the component. Additionally, I've used the Graphic font height metric to position the y-coordinate, since the drawString method places the y coordinate at the bottom left.
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JComponent;
public class HelloComponent extends JComponent {
private final int COMPONENT_WIDTH = 100;
private final int COMPONENT_HEIGHT = 30;
public HelloComponent() {
setPreferredSize(new Dimension(COMPONENT_WIDTH, COMPONENT_HEIGHT));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("Hello World", 0, g.getFontMetrics().getHeight());
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have a probably annoying request. Could someone demonstrate how to use one of these static Java swing utility methods? I am looking for a simple, extremely simple, example.
public static void paintComponent(java.awt.Graphics, java.awt.Component, java.
awt.Container, int, int, int, int);
public static void paintComponent(java.awt.Graphics, java.awt.Component, java.
awt.Container, java.awt.Rectangle);
These static Java swing methods are found in the javax.swing.SwingUtilities package.
Thank-you for reading this and any help given.
you can find some usages of most public api methods from grepcode. and here is yours.
EDIT
a running example may be like this
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater( () -> {
JFrame frame = new JFrame();
JPanel panel = new JPanel() {
JLabel label = new JLabel("<html>SwingUtilities.paintComponent method usage example");
{
label.setBorder(new LineBorder(Color.red));
}
protected void paintComponent(Graphics g) {
// render label which is not part of component hierarchy
// and paint it on this panel at location (10,10) with dimension (200,50)
SwingUtilities.paintComponent(g, label, this, 10, 10, 200, 50);
}
};
frame.setContentPane(panel);
frame.setSize(300, 200);
frame.setVisible(true);
});
}
}
I am trying to write a simple 2d animation engine in Java for visualizing later programming projects. However, I am having problems with the window refresh. On running, the frame will sometimes display a blank panel instead of the desired image. This begins with a few frames at a time at apparently random intervals, worsening as the program continues to run until the actual image only occasionally blinks into view. The code for processing each frame is run, but nothing in the frame is actually displayed. I believe the problem may come from my computer more than my code (certainly not from bad specs though), but am not sure. Help much appreciated.
Three classes. Code here:
package animator;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.applet.AudioClip;
public class APanel extends JPanel
{
public APanel(int l, int h){
setPreferredSize(new Dimension(l,h));
setLocation(80, 80);
setVisible(true);
setFocusable(true);
}
public Graphics renderFrame(Graphics g){
return g;
}
public void paintComponent(Graphics g) {
requestFocusInWindow();
renderFrame(g);
}
}
package animator;
import java.awt.*;
public class Animator extends APanel
//extending the APanel class allows you to code for different animations
//while leaving the basic functional animator untouched
{
public static final int SCREEN_X = 700;
public static final int SCREEN_Y = 700;
int frameNum;
public Animator() {
super(SCREEN_X, SCREEN_Y);
frameNum = 0;
}
public Graphics renderFrame(Graphics g) {
frameNum++;
g.drawString(""+frameNum,5,12);
return g;
}
}
package animator;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Runner {
int framerate = 30;
Animator a = new Animator();
JFrame j = new JFrame();
public Runner(){
j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
j.add(a);
start();
j.setSize(a.getPreferredSize());
j.setVisible(true);
}
public void start() {
Timer t = new Timer(1000/framerate, new ActionListener() {
public void actionPerformed(ActionEvent e){
j.getComponent(0).paint(j.getComponent(0).getGraphics());
//The following line of code keeps the window locked to a preferred size
// j.setSize(j.getComponent(0).getPreferredSize());
}
});
t.start();
}
public static void main(String[] args){
Runner r = new Runner();
}
}
There are some serious mistakes in your code which could be the cause or a factor of your problem...
j.setSize(a.getPreferredSize()); is irrelevant, simply use JFrame#pack, you get better results as it takes into account the frame decorations
j.setSize(j.getComponent(0).getPreferredSize()); use JFrame#setResizable and pass it false instead...
NEVER do j.getComponent(0).paint(j.getComponent(0).getGraphics()); this! You are not responsible for the painting of components within Swing, that's the decision of the RepaintManager. Just call j.repaint()
super(SCREEN_X, SCREEN_Y);...just override the getPreferredSize method and return the size you want.
setLocation(80, 80); irrelevant, as the component is under the control of a layout manager
setVisible(true); (inside APanel)...Swing components are already visible by default, with the exception of windows and JInternalFrames
And finally...
public void paintComponent(Graphics g) {
requestFocusInWindow();
renderFrame(g);
}
There is never any need for this method to be made public, you NEVER want someone to be able to call it, this will break the paint chain and could have serious ramifications in the ability for the component to paint itself properly.
You MUST call super.paintComponent before performing any custom painting, otherwise you could end up with all sorts of wonderful paint artifacts and issues
Never modify the state of a component from within a paint method...while it "might" not be an immediate issue calling requestFocusInWindow(); within your paintComponent could have side effects you don't know about...
Instead, it should look more like...
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
renderFrame(g);
}
I want to load images in JFrame such a way that it should look like it is video.
For that I thought that I will change Images so much faster (20 images/sec.)
but Problem is when new Image get load its shows fully black window.
I dont know Why it happens.
Suggest me where I goes wrong.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.io.*;
import javax.imageio.ImageIO;
class VideoI extends JPanel {
private Image img;
private Graphics graphics;
ImageIcon icon;
VideoI(){
icon=new ImageIcon("D:\\Videos\\1.jpg");
add(icon);
}
public void paintComponent(Graphics g) {
graphics=g;
repeatImgs();
}
public void repeatImgs(){
for(int i=0;i<25;i++)
{ try{
img=ImageIO.read(new File("D:\\Videos\\"+i+".jpg"));
graphics.drawImage(img, 0, 0, null);
System.out.println(""+i);
Thread.sleep(1000);
}catch(Exception e){System.out.println(""+i+":"+e);}
}
}
}
public class Video extends JFrame
{
public static void main(String args[])
{
new Video().start();
}
public void start()
{
VideoI panel = new VideoI();
add(panel);
setVisible(true);
setSize(1300,800);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
You are blocking the event dispatch thread. Use a swing Timer to repaint the component at the desired frequency.
You should never, ever sleep() in the EDT. What you want is essentially
public void paintComponent(Graphics g) {
// No loops or delays, just fetch the next image, preferrably it has been
// already been loaded by another thread.
g.drawImage(getNextImage(), 0, 0, null);
}
And a timer task:
ActionListener timerTask = new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
panel.repaint();
}
};
Timer timer = new Timer(50, timerTask);
When you want to start the video, just call timer.start().
Finally, you should also wrap creating the GUI with SwingUtilities.invokeLater().
You're sending the Event Dispatch Thread (the UI update thread) to sleep, that's why you get screen issues.
Try loading and switching images in a worker thread (have a look at the SwingWorker JavaDoc).
I'm no Swing expect, but I would guess this happens because you stop the Swing thread with the Thread.sleep. You should do the image changing and timing outside of the swing thread and use SwingUtilities.invokeLater to draw the Image. Also you need to sleep 50ms, not a whole second for 20fps. Using a ScheduledExecutorService whould fit here.
Also you always load the image from disc, when it needs to be rendered. This could be to slow. It would be better to load all image on start up and then just change the image.