/*If given constructor values draw moving circle
* But if it does not give him the values draws a line
*/
package samr;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
public class AX{
public static class panel extends JPanel{
public int w,c=1;
public panel(int start,int end){
int x=start;
int y=end;
w=x;
paint(?,x,y);
}
public panel(){
paint(?);
}
public void paint(Graphics e){
e.drawLine(0,0,500,500);
}
public void paint(Graphics g,int x,int y){
super.paint(g);
if(w<=y){
w=w+c;
if(w==x||w==y){c=c*-1;}
g.drawOval(w,0,50,50);
this.repaint();
}
}
}
public static void main(String[] arg){
JFrame f=new JFrame("test");
f.setBounds(100,100,500,500);
panel p=new panel(100,300);
f.add(p);
f.setVisible(true);
}
}
What I give instead graphics in constructor?
You don't, that's provided by the system, take a look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting works in Swing.
If you want to update the component, then you should call repaint
Painting in Swing is done via a passive algorithm, to improve performance, you should never modify the state or call any functionality which could modify the state of the UI from within any paint method, so you should remove the repaint call in your paint method.
By convention, we are encouraged to override paintComponent instead of paint, it's safer to do so.
Painting should paint the current state of the component, this means you will need to set some variables to the desired values and call repaint for them to updated.
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.
I need the simplest way to draw a line between to coordinates.
Since this drawing line in my code will be repeated more than 200 times in a loop i need the easiest way. I'm drawing the lines in a AWT panel component.
If you want to switch to Swing you would use the JPanel and overwrite the paintComponent() method.
import java.awt.Graphics;
import javax.swing.JPanel;
public class PanelWithLine extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(x1,y1,x2,y2);
}
}
You can than redraw everything by calling repaint() on your Jpanel.
You would probably change the coordinates and then call the repaint() method in your loop.
It's been a long time since I've used java.awt.Panel, but it should be something like:
class Foo extends Panel {
public void paint(Graphics g) {
super.paint(g);
g.drawLine(x1,y1,x2,y2);
g.drawLine(x3,y3,x4,y4);
//...
}
}
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.
This is my code so far with some print lines just to make sure it was actually even going into the method. For some reason NOTHING is being drawn on the canvas, I have a program similar to this as far as the drawing goes and it works fine. What is wrong with this one?
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.*;
public class gameOfLife implements ActionListener {
private int height;
private int width;
private Graphics g;
private JPanel panel;
private JFrame frame;
int[][] board= new int[40][40];
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
gameOfLife gui = new gameOfLife();
}
public gameOfLife() {
int height=400;
int width=400;
frame= new JFrame("Keegan's Game Of Life");
frame.setSize(new Dimension(height,width));
frame.setLayout(new BorderLayout());
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
g=frame.getGraphics();
drawBoard();
}
public void drawBoard() {
g.setColor(Color.BLUE);
g.drawLine(0, 0, 50, 50);
g.fillOval(50,50,10,10);
System.out.println("Done Drawing");
g.drawString("IT WORKED!", 100, 100);
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
Let's start with g=frame.getGraphics();
This is a very bad idea and not how custom painting is performed. getGraphics may return null and is generally only a snap shot of the last paint cycle. Anything painted to the Graphics context via this method will be destroyed on the next repaint cycle.
You should never maintain a reference to any Graphics context, they are transient and may not be the same object between paint cycles
Instead, create yourself a custom component (something like JPanel) and override it's paintComponent method
Check out Performing Custom Painting for more details
Updated
You can check out this simple example for an idea...
You can override paint(Graphics g) in your canvas, otherwise the drawing will disappear once the canvas is invalidated (e.g. moved or covered by another windows).
It might be easier to let your class extends JFrame and override the paint methods, otherwise you can use anonymous class e.g.
frame = new JFrame("Keegan's Game Of Life") { //override paint here }
However, if your application aims to create animation for Game Of Life, you should not be doing this in a JFrame, consider using JPanel or Canvas