I am new on java. I want to create an abstract factory in java. I have a class point and I want to extend other classes ( circle, rectangle ) from this.
Here is my code. It says repaint is undefined..
import javax.swing.*;
import java.awt.*;
import java.awt.Component;
import javax.swing.*;
public class Circle extends Point {
public void Draw() {
repaint();
}
public void paint(Graphics g) {
g.drawOval(this.x, this.y, 10, 10);
}...
The class Point simply encapsulates an x and y integer value. It is not derived from java.awt.Component so therefore repaint cannot be invoked.
For custom painting in Swing extend JComponent or JPanel and override paintComponent rather than paint. Remember to invoke super.paintComponent(g).
See: Performing Custom Painting
repaint() method is part of java.awt.Component.Point is not a subclass of java.awt.Component. You can't use it that way.
Related
First class
package com.mudd.render;
import java.awt.Dimension;
import javax.swing.JFrame;
import com.mudd.game.Game;
public class render {
int width = 500;
int height = 600;
Game g = new Game();
public void show(){
JFrame gameWindow = new JFrame("..");
gameWindow.setPreferredSize(new Dimension(width, height));
//gameWindow.setIconImage(new ImageIcon(imgURL).getImage());
gameWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameWindow.pack();
gameWindow.add(g);
gameWindow.setVisible(true);
}
public static void main(String[] args) {
render game = new render();
game.show();
}
}
Second class
package com.mudd.game;
import java.awt.Graphics;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Game extends JPanel {
public void paint(Graphics g){
g.fillOval(10, 10, 500, 500);
System.out.println("Test");
}
}
What is causing my Test print statement to be printed twice? If I add other priintlns it will also print them both out. I've been learning Java from Head First Java and I've done other small command line projects but nothing like this has ever happened to me.
Swing graphics are passive -- you don't call the painting methods directly yourself, but rather the JVM calls them. They are sometimes possibly called at your suggestion such as when you call repaint() but even this is never a guarantee, and they are sometimes possibly called at the suggestion of the platform, such as when it determines that your application has "dirty" pixels that need cleaning. So you have to plan for this -- the painting method should contain no code that changes the state of the object nor should it contain business logic code. Instead it should have code for painting and nothing more.
For more details on this, please see:
Lesson: Performing Custom Painting: introductory tutorial to Swing graphics
Painting in AWT and Swing: advanced tutorial on Swing graphics
Side recommendations:
Override the JPanel's paintComponent method, not its paint method
Use the #Override annotation for any method override
Don't forget to call the super's method in your override.
This code repaints a random oval, rectangle, and line with different colors on the screen. The problem is that I'm trying to change the background color each time it repaints, but the backgrounds doesn't repaint. Please help.
package events;
import java.awt.*;
import java.awt.event.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class Paint extends JPanel {
static Paint g;
boolean change = true;
int x = 0;
int y = 0;
public void paintComponent(Graphics g) {
g.fillOval(x, y, 50, 50);
}
void circles() {
Color color = new Color(0, 0, 0);
repaint();
}
}
Get rid of the static Paint variable. Your class doesn't need any static variables.
how would i change the background then?
The painting method should NOT change the properties of the class. It should only paint the component based on the current properties.
So you need to do something like:
Create a method like setRandomBackground(). This method will create a Color object that you can use in the paintComponent() method. At the end of this method you should invoke repaint(), which will tell Swing to paint the component.
Get rid of new Paint()
get rid of Thread.sleep() // never tell a painting method to sleep.
get rid of repaint() // never tell a painting method to repaint itself, this will create an infinite loop.
Finally, read the Swing tutorial on Custom Painting for more information and working examples to learn the basics.
Also, variable names (R, G, B) should NOT be upper cased.
I'm trying to make a rectangle to move across the screen, but instead it's just repainting and not getting rid of the preceding rectangle making it look like a giant rectangle across the screen. Any help would be appreciated, here's my code:
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.*;
#SuppressWarnings("serial")
public class Test extends JFrame implements ActionListener{
int x=50;
Timer tm = new Timer(30,this);
public static void main(String[] args){
new Test();
}
public Test(){
this.setSize(700, 500);
this.setTitle("Drawing Shapes");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public void paint(Graphics g){
Graphics2D graph2 = (Graphics2D)g;
Shape Rect = new Rectangle2D.Float(x, 50, 50, 30);
graph2.setColor(Color.RED);
graph2.fill(Rect);
tm.start();
}
public void actionPerformed(ActionEvent e){
x=10+x;
repaint();
}
}
Draw in a JPanel that is held by and displayed within the JFrame. Don't draw directly in the JFrame as this risks drawing over things that shouldn't be messed with such as root panes, borders, child components,... Also you lose the benefits of automatic double buffering by drawing directly in the JFrame's paint method leading to choppy animation.
You should override the JPanel's paintComponent method not its paint method.
Always call the super's painting method in your own painting method (here it again should be paintComponent). This is your problem. So again, your paintComponent(Graphics g) override painting method should call super.paintComponent(g); on its first line. This will erase the old images.
You're breaking the paint chain...
public void paint(Graphics g){
// Broken here...
Graphics2D graph2 = (Graphics2D)g;
Shape Rect = new Rectangle2D.Float(x, 50, 50, 30);
graph2.setColor(Color.RED);
graph2.fill(Rect);
tm.start();
}
You MUST call super.paint. See Painting in AWT and Swing and Performing Custom Painting for more details about painting in Swing...
Top level containers are not double buffered and it is not recommended to paint directly to them, instead, create a custom component which extends from something like JPanel and override it's paintComponent method (calling super.paintComponent before performing any custom painting)
As a general rule of thumb, you should avoid extending from top level containers like JFrame, as you are not adding any new functionality to the class and they lock you into a single use-case, reducing the re-usability of your classes
DON'T call tm.start inside the paint method, you should do nothing in the paint methods except paint, never try and modify the state or otherwise perform an action which might indirectly modify the state of a component, this is a good way to have you program consume your CPU
To add to what other have already stated,
I've noticed that you use this.setLocationRelativeTo(null) for a simple application. Not saying it is bad, but you might want to check this thread to make sure it is what you want.
How to best position Swing GUIs?
In this video drawing() method is called in main class. When we remove drawing() in the main method it still draws the shape. How can we avoid this situation ?
shapes class:
import java.awt.*;
import javax.swing.*;
public class shapes{
public static void main(String[] args){
JFrame frame = new JFrame("Test");
frame.setVisible(true);
frame.setSize(400,200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
draw object = new draw();
frame.add(object);
object.drawing();
}
}
Draw class:
import java.awt.*;
import javax.swing.*;
public class draw extends JPanel{
public void drawing(){
repaint();
}
public void paintComponent(){
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(10,15,100,100);
}
}
There are some minor issues with the code, but I assume that it's only a small snippet for demonstration purposes. For details, have a look at Performing Custom Painting.
Actually, this tutorial would also answer your question, but to summarize it:
The paintComponent method will be called automatically, "by the operating system", whenever the component has to be repainted. The call to repaint() only tells the operating system to call paintComponent again, as soon as possible. So you can call repaint() to make sure that something that you canged appears on the screen as soon as possible.
If you explicitly want to enable/disable certain painting operations, you can not influence this by preventing paintComponent from being called. It will be called anyhow. Instead, you'll introduce some flag or state indicating whether something should be painted or not.
In your example, this could roughly be done like this:
import java.awt.*;
import javax.swing.*;
public class Draw extends JPanel{
private boolean paintRectangle = false;
void setPaintRectangle(boolean p) {
paintRectangle = p;
repaint();
}
#Override
public void paintComponent(){
super.paintComponent(g);
if (paintRectangle) {
g.setColor(Color.BLUE);
g.fillRect(10,15,100,100);
}
}
}
You can then call the setPaintRectangle method to indicate whether the rectangle should be painted or not.
New Details:
Repaint method of my JPanel object does not work when called from inside actionPerformed event of my main class. It DOES work inside the ImageViewer method of the main class ImageViewer but does not work inide the actionPerformed method of this class.
These are the essential parts of my code which are not working properly ( repainting part ):
Main Class:
/**
* #(#)NeatImageViewer.java
*
* NeatImageViewer application
*
* #author
* #version 1.00 2010/11/1
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
public class NeatImageViewer extends JFrame implements ActionListener {
GraphicsPanel gp;
NeatImageViewer() {
//... window components ...
}
public static void main(String[] args) {
NeatImageViewer niv = new NeatImageViewer();
niv.setSize(500,500);
niv.setLocationRelativeTo(niv);
niv.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
//...
gp = new GraphicsPanel();
gp.img = img;
gp.repaint(); //<!--- Not Working!
this.add(gp);
//...
}
}
GraphicsPanel Class:
/**
* #(#)GraphicsPanel.java
*
*
* #author
* #version 1.00 2010/11/1
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
public class GraphicsPanel extends JPanel {
BufferedImage img;
GraphicsPanel() {
super();
}
protected void paintComponent(Graphics g) {
//paint method isn't executed???
super.paintComponent(g);
System.out.println("Paint!");
}
}
You have to override paintComponent(Graphics g) instead of paint(Graphics g).
So, the method you posted should be renamed to paintComponent.
EDIT: Have you pack()'ed your frame when your initialization is done?
EDIT: The repaint() method does nothing when the component isn't visible. So, you have to add it first to the JFrame, pack() the frame. After packing it, repainting isn't needed anymore.
In Swing you don't use a Canvas. You do custom painting on a JPanel or JComponent and you override the paintComponent(...) method as already stated. Read the Swing tutorial on Custom Painting for more information and working examples.
Also, with Swing there is no need to create a custom components to show an image. You just use a JLabel with an ImageIcon. Read the section on "How to Use Icons".
Bookmark the tutorial for all the Swing basics.
Edit:
When you add a component to a visible GUI the basic code should be:
panel.add( ... );
panel.revalidate();
panel.repaint();
(I'm Skyfe but from another IP so ain't "logged in" and couldn't comment)
I'm sorry but I don't get what's the problem???
I offered my code and it is NOT executing the paintComponent function upon calling repaint from the actionPerformed method. Just copy paste my code and compile it with a java compiler and it does NOT execute the paintComponent method upon performing an action which I can tell because I used a System.out.println() method inside the paint method. And no it does not paint anything because I'm just trying to check whether it calls the paint method AT ALL because I put a system output inside the paintComponent method which is not executed when using repaint. It was just a test and it didn't work.
So what you mean by where is the SSCCE, this is all the code I have. I compiled exactly the code I posted in my main post and the problem with it is that it does not show any system output when an action was performed ( and the repaint event was called ). I fail to see what misses in my post?