I have a animation class which simply draws two circles and a line (no main method), in another class i have a main method which is passed the animation class as a object and should show the two circles that I have drawn but it doesn't show, it only shows the window none of the circles or the line that I have done, if i was to put the main method in my animation class it will work perfectly, this is a user error somehow but I'm not sure what or why.
The animation method in separate class.
import javax.swing.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.Graphics.*;
import javax.swing.JApplet;
public class Animation extends JApplet{
public void init(){
}
public static void createAndShowGUI(JApplet j)
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
frame.setSize(500,500);
frame.getContentPane().add("Center", j);
}
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D) g;
int x=50;
int y=10;
g2.setPaint(Color.black);
g2.draw(new Line2D.Double(x,y,50,400));
drawT(g2);
drawH(g2);
//create a method that translates
}
public void drawH(Graphics2D g2)
{
int y=25;
g2.setColor(Color.blue);
drawCircle(y,g2);
}
public void drawT(Graphics2D g2){
int y=100;
g2.setColor(Color.green);
drawCircle(y,g2);
}/*
public void raceLoop(){
long startingTime = System.currentTimeMillis();
long cumTime=startingTime;
while(mve.hposition<70){
long timePassed = System.currentTimeMillis()-cumTime;
cumTime += timePassed;
//mve.update(timePassed);
}
}*/
public void drawCircle(int y, Graphics2D g2)
{
g2.fillOval(50,y,50,50);
}
}
The Main Method
import javax.swing.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.Graphics.*;
import javax.swing.JApplet;
public class Race {
public static void main(String[] args) {
JApplet applet = new JApplet();
Animation animie = new Animation();
animie.createAndShowGUI(applet);
}
}
You don't need to (or want) extend from JApplet if all you're going to is use a JFrame. You're better of (in any case), extending from JPanel (as this can then be added to a JApplet or JFrame)
You've not added anything to the JFrame, so, in fact, you program is doing exactly what you told it to.
You should very rarely need to override the paint method of a top level container (like JApplet or JFrame), instead, use JPanel and override it's paintComponent method.
You should always call super.paintXxx, the paint methods chain together to paint the various aspects of the application and it will end in tears if you break this chain.
You might like to have a read through
Creating a GUI With JFC/Swing
Performing Custom Painting
Painting in AWT and Swing
For some more background
Looks like you're passing the wrong reference to the createAndShowGui(..) method.
Try this on your Race class:
import javax.swing.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.Graphics.*;
import javax.swing.JApplet;
public class Race {
public static void main(String[] args) {
Animation animie = new Animation();
animie.createAndShowGUI(animie);
}
}
Related
I have two classes below: And I'm trying to make it so that calling FilledFrame would make certain shapes. I've tested it with a Line below, but it doesn't show up on the GUI. Is there something I'm doing wrong here? I also need to make a Card class that is able to modify some rectangle's positions, so would I need to make a graphics object in the main and enter it into FilledFrame and my Card class?
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import javax.swing.*;
public class FilledFrame extends JFrame implements ActionListener {
static int FRAME_WIDTH = 500;
static int FRAME_HEIGHT = 100;
Graphics g = getGraphics();
public FilledFrame () {
g.drawLine(1, 1, 100, 100);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setVisible(true);
}
private void createComponents() {
...
}
private void createCards() {
...
}
#Override
public void actionPerformed(ActionEvent e) {
}
public static void draw (Graphics g) {
g.fillRect(0, 50, 100, 150);
}
}
Main class:
import java.awt.Graphics;
import java.awt.Shape;
import java.awt.geom.Line2D;
import java.awt.geom.Line2D.Float;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.Canvas;
import javax.swing.JComponent;
import javax.swing.JPanel;
public class Main {
public static void main (String args[]) {
FilledFrame frame = new FilledFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();
}
}
Is there something I'm doing wrong here?
Sorry to say, but you're guessing at how to do Swing drawing, and while this might work with simple Java concepts, it won't for something as complex as Swing graphics.
Problems include:
Trying to draw directly within the JFrame -- never do this, but instead draw in a JPanel.
Calling getGraphics() on a component to get a Graphics resource. This will lead to your getting an unstable and short-lived Graphics object that can lead to either failed painting or NullPointerExceptions
Not drawing in an appropriate painting method.
You're using int literals in your drawing method parameters rather than int variables, making any drawing that you do do, fixed -- you can never move or change it.
Instead I suggest that you:
Create a class that extends JPanel and paint in that class.
Draw within this class's protected void paintComponent(Graphics g) method.
Don't forget to call the super's paintComponent method within your override so that your GUI cleans up any dirty pixels.
Then place that JPanel into the JFrame that needs to display it.
Use int fields (variables) not int literals (so-called "magic" numbers) for most of your drawing method parameters so that your drawings can change if you so desire while the program runs.
And most important, read and study the standard Swing graphics tutorials.
Resources:
The Really Big Index: the main tutorial where you should start.
Using Swing Components: how to create Swing GUI's
Lesson: Performing Custom Painting: introductory tutorial to Swing graphics
Painting in AWT and Swing: advanced tutorial on Swing graphics
Hi I want to make a window, a GUI, and put an image in it.
I watched a YT tutorial (https://www.youtube.com/watch?v=Ap20Qw77TzY) and copied everything similar but the Window I make has no image at all. I tried different file types like .jpg and different window sizes, matching the picture size but it doesn't help.
That's my code, I get no real errors, except a warning of:
The serializable class main does not declare a static final serialVersionUID field of type long,line 8
This method has a constructor,line 25
Code
package main;
import java.awt.Graphics;
import java.awt.Toolkit;
import javax.swing.*;
public class main extends JFrame {
/**
* author jan
*/
public main(String title){
super (title);
}
public void paint(Graphics gr) {
super.paint(gr);
gr.drawImage(Toolkit.getDefaultToolkit().getImage("Koppenhagen\\Pictures\\Herz.png"), 0, 0, this);
}
public static void main(String[] args) {
main window = new main("Mein Test!");
window.setSize(160,160);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
}
Use ImageIO.read over Toolkit.getImage, it will throw a IOException of the image can't be load for some reason
Check the location of the image. Your example is looking for a file in Koppenhagen\\Pictures, relative to the execution context of the program. You could use File#exists to check if the file actually exists where you think it is
Don't load resources within the any paint method, loading images can take time and painting should run as fast as possible
I'd discourage you from overriding paint of top level containers like JFrame. A JFrame contains a JRootPane, which contains, amongst other things, a contentPane all of which can be painted independently of its parent container. Instead, start with a JPanel and override its paintComponent method instead, then add this to an instance of JFrame
Here's a simple Swing application that draws an image.
You have to put the image in the same directory as the Java code.
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.JScrollPane;
import javax.swing.SwingUtilities;
public class DrawImage implements Runnable {
#Override
public void run() {
JFrame frame = new JFrame("Image");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollPane = new JScrollPane(new ImagePanel(getImage()));
frame.add(scrollPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.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, this);
}
}
}
I am trying to figure out how to repaint() a class that extends the JComponent. I want to have each class extend JComponent and then supply its own paintComponent(). (super.paintComponent(). This way I can make a circle class or whatever class that I want to make and then I can repaint() it when ever I want to as long as it is added to the JPanel that goes in the JFrame. Below are all of the code that are needed to run.
Class 1:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
public class DDHGenericFrame extends JFrame {
private static final long serialVersionUID = 1L;
/* User defined class that is below */
DDHGenericPanel d = new DDHGenericPanel();
public DDHGenericFrame() {
initUI();
}
public final void initUI() {
add(d);
setSize(650, 350);
setTitle("Lines");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
DDHGenericFrame ex = new DDHGenericFrame();
ex.setVisible(true);
}
}
Class 2:
import java.awt.Graphics;
import javax.swing.JPanel;
class DDHGenericPanel extends JPanel {
private static final long serialVersionUID = 1L;
DDHGenericPanel() {
System.out.println("DDH Generic JPanel");
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//paint code goes here of whatever
}
}
Class 3:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
public class DDHCircleOne extends JComponent {
private static final long serialVersionUID = 1L;
int counter = 0;
public DDHCircleOne() {
counter++;
System.out.println("DDHCircle Constructor");
}
public void paintComponent(Graphics g2) {
super.paintComponent(g2);
Graphics2D c2D = (Graphics2D) g2;
c2D.setColor(Color.yellow);
c2D.fillRect(0, 0, getSize().width, getSize().height);
if (counter % 2 == 2) {
System.out.println("RED");
counter++;
c2D.setColor(Color.red);
c2D.fillRect(0, 0, getSize().width, getSize().height);
} else {
System.out.println("BLUE");
counter++;
c2D.setColor(Color.blue);
c2D.fillRect(0, 0, getSize().width, getSize().height);
}
}
}
The above three classes are what I have in my package. I want DDHCircleOne to be able to repaint it self whenever an instance of it is created and calls the method repaint(). This way I can just make a class that extends JComponent and then override the paintComponent() and then call repaint().
If I had a button that said repaint in red and another button that says repaint in blue the circle or whatever I had in the frame will repaint itself when the variableName.repaint() is called.
doughauf#outlook.com
public void paintComponent(Graphics g) {
super.paintComponent(g);
repaint();
}
Never invoke repaint() in a painting method. This will cause an infinite loop.
There is no need for you generic panel. You can add a component to any panel.
If you want the color of the circle to change, then you need to change a property of your component. For example you can just use the setForeground(...) method to change the color:
//c2D.setColor(Color.red);
c2D.setColor( getForeground() );
So when you click on your button you just invoke circle.setForeground(Color.RED);
The setForeground() method of JComponent will invoke the repaint() method on the component for you.
So I am trying to get into simple animations and virtual physics and whatnot. I am trying to animate a ball so that it slowly grows as time passes by. The code I have here is pretty much exactly as it is in a Java For Dummies book I have with the exception of a few things such as: getting rid of constants for the size of the applet (this.setSize(500, 500) vs this.setSize(WIDTH, HEIGHT) and declaring WIDTH and HEIGHT earlier). The changes were simple and would not effect the program. (I would know as I've taken a Java course in school). Anyway, I'm starting here with Applets and I can't get the program to run past two iterations. Down in the paint function I have a System.out.println(d) to check how many times the diameter of the ellipse grows. However the only output I see is "21" then "22". The applet continues to run via the applet viewer however nothing else is printed even though it should continue to grow. Anyone know what's wrong?
As a side note I should mention I am using NetBeans 7.2 and selecting "Run File" to run it.
package GraphicsTesting;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.applet.*;
import java.util.concurrent.*;
public class Main extends JApplet
{
private PaintSurface canvas;
#Override
public void init()
{
this.setSize(500,500);
canvas = new PaintSurface();
this.add(canvas, BorderLayout.CENTER);
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(3);
executor.scheduleAtFixedRate(new AnimationThread(this), 0L, 20L, TimeUnit.MILLISECONDS);
}
}
class AnimationThread implements Runnable
{
JApplet c;
public AnimationThread(JApplet C)
{
this.c = c;
}
public void run()
{
c.repaint();
}
}
class PaintSurface extends JComponent
{
int d = 20;
#Override
public void paint(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint
(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
d+=1;
System.out.println(d);//This is to test
Shape ball = new Ellipse2D.Float(200, 200, d, d);
g2.setColor(Color.RED);
g2.fill(ball);
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication3;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.Timer;
import javax.swing.JApplet;
import javax.swing.JComponent;
public class Main extends JApplet {
private PaintSurface canvas;
private Timer timer;
#Override
public void init() {
this.setSize(500, 500);
canvas = new PaintSurface();
this.add(canvas, BorderLayout.CENTER);
// ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(3);
// executor.scheduleAtFixedRate(new AnimationThread(this), 0L, 20L, TimeUnit.MILLISECONDS);
timer = new Timer(20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
canvas.repaint();
}
});
timer.start();
}
}
class PaintSurface extends JComponent {
int d = 20;
#Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
d += 1;
System.out.println(d);//This is to test
Shape ball = new Ellipse2D.Float(0, 0, d, d);
g2.setColor(Color.RED);
g2.fill(ball);
}
}
You are calling repaint() on a thread that is not the Event Dispatch Thread
so the UI is not updated. There are other ways to do this, but internally javax.swing.Timer calls the actionPerformed method inside the Event Dispatch Thread so the UI is updated.
UPDATE: You could see the applet in action using java webstart: https://tetris-battle-bot.googlecode.com/files/launch.jnlp
The above answer does work. However, looking at your original code there is one little itty bitty misconception that, it appears, neither of you caught. In the constructor of the animation thread you have JApplet C as a parameter rather than JApplet c. To clarify, you accidently capitalized the c. The capitlization of the C caused you to set this.c = c which basically assigned it to itself. It wasn't needed to rewrite the entire code at all.
I discovered the Robot class yesterday, and thought it was pretty cool. Today I wanted to experiment with it and see what was possible; so I decided I wanted to make a program that took a screenshot of the entire screen, and rendered out an image pixel by pixel on a JPanel. I have the program finished (two classes), but it isn't working and I can't find out why (I HAVE looked over the code a few times). Here's the code:
(FIRST CLASS)
import java.awt.AWTException;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
public class One {
public static void main(String[] args) {
BufferedImage screenCap = null;
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
try {
screenCap = new Robot().createScreenCapture(screenRect);
Two imageRenderer = new Two(screenCap, screenRect);
imageRenderer.doRender();
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
frame.add(imageRenderer);
frame.pack();
} catch (AWTException e) {
e.printStackTrace();
}
}
}
(SECOND CLASS)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
public class Two extends JPanel {
private BufferedImage screenCap;
private Rectangle screenRect;
private Color pixelRGB;
//c1 and c2 are the x and y co-ordinates of the selected pixel.
private int c1, c2;
public Two(BufferedImage sC, Rectangle rect) {
screenCap = sC;
screenRect = rect;
setPreferredSize(new Dimension(rect.width, rect.height));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.WHITE);
g.setColor(pixelRGB);
g.drawRect(c1, c2, 1, 1);
}
public void doRender() {
for(int i=0; i<screenRect.width; i++) {
for(int j=0; j<screenRect.height; j++) {
pixelRGB = new Color(screenCap.getRGB(i, j));
c1 = i;
c2 = j;
repaint();
}
}
}
}
I have googled around this problem to no avail.
Can anyone tell me what I'm doing wrong?
In order to make it work, just replace your paintComponent() method in your class Two with the following:
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.WHITE);
g.drawImage(screenCap, 0, 0, getWidth(), getHeight(), null);
}
You can also get rid of the doRender() method.
Two should probably be an instance of a JLabel that is displaying screenCap. E.G.
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Screenshot {
public static void main(String[] args) throws Exception {
Rectangle screenRect = new Rectangle(
Toolkit.getDefaultToolkit().getScreenSize());
final BufferedImage screenCap =
new Robot().createScreenCapture(screenRect);
Runnable r = new Runnable() {
#Override
public void run() {
JOptionPane.showMessageDialog(null, new ImageIcon(screenCap));
}
};
SwingUtilities.invokeLater(r);
}
}
Drop it in a scroll pane if you wish to be really neat about it. Batteries not included.
In case it is not obvious: A JOptionPane uses a JLabel to render an ImageIcon.
Each time you repaint, you paint white over the whole panel, then do only a single pixel. So after each one, you'll only get one pixel. It also shouldn't be necessary to call repaint many times. In fact, when you call repaint, it does not immediately actually call paintComponent. It simply submits a request to repaint, which swing will eventually do. And it might not be one-to-one. E.g., many calls to repaint might result in only one call to paintComponent. You should try to write code so that a single call to paintComponent will completely display the component.
To do this, you can use g.drawImage to display a BufferedImage. See this post for more information on displaying an image in a JPanel.