Java: How to draw in a canvas?
Comment these two lines
//Graphics g=canvas.getGraphics();
//canvas.paint(g);
And change the paint method as follows.
@Override
public void paint(Graphics g) {
super.paint(g);
Rest is all fine. Hope it helps you to progress.
Drawing in Java using Canvas
Suggestions:
- Don't use Canvas as you shouldn't mix AWT with Swing components unnecessarily.
- Instead use a JPanel or JComponent.
- Don't get your Graphics object by calling
getGraphics()
on a component as the Graphics object obtained will be transient. - Draw in the JPanel's
paintComponent()
method. - All this is well explained in several tutorials that are easily found. Why not read them first before trying to guess at this stuff?
Key tutorial links:
- Basic Tutorial: Lesson: Performing Custom Painting
- More advanced information: Painting in AWT and Swing
Drawing Canvas on JFrame
I don't know what it is you're trying to do, but you should NEVER be calling paint
and especially not pass it null
.
Start by taking a look at Performing Custom Painting and Painting in AWT and Swing for details about how painting works.
In order to get the window to size to you component, you need to provide it some important information.
While Window#pack
is the method you are looking for, it will not help you unless you provide appropriate sizing hints.
In this case, you need to override the getPreferredSize
method of you component and provide an appropriate size value. Window#pack
will use this value to determine what size it needs to be in order to accommodate it.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestPaint {
public static void main(String[] args) {
new TestPaint();
}
public TestPaint() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.BLACK);
g.fillOval(100, 100, 30, 30);
}
}
}
The paint chain is very important and you should avoid breaking it at all coasts. Make sure you always call super.paintXxx
or be prepared for some serious weirdness
Also may want to have a read of Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
Draw and redraw on a canvas in swing
Here's one way to do it:
public class Renderer extends JComponent implements ActionListener {
private int x;
public Renderer() {
Timer timer = new Timer(1000/60, this);
timer.start();
x = 0;
}
@Override
public void paintComponent(Graphics g) {
super.paint(g);
// drawing code
g.setColor(Color.black);
g.drawOval(x, 0, 100, 100);
}
private void update() {
this.x++;
}
@Override
public void actionPerformed(ActionEvent e) {
update();
repaint();
}
}
Now just add this to your component (JPanel or whatever):
comp.add(new Renderer());
How to put buttons and canvas into jframe? (Java swing)
Here:
getContentPane().add(p);
getContentPane().add(new MyCanvas());
The first one adds your panel with your buttons to the frame. Then you add another thing to the frame!
Following your approach of placing everything manually, you rather add that canvas to your panel!
You disabled all means that would allow the JFrame resp. a layout manager to meaningfully place your panel and the canvas. Instead you push two elements into the frame, without telling the frame where that canvas should go to!
So you either need absolute placement for the canvas as well - or you step back and turn to a layout manager to do that for you.
Swing Timer and Painting on Canvas
When doing custom painting in Swing it is a good idea to subclass JPanel (it could be an anonymous class) and to store painting-related data in attributes somewhere accessible to the panel.
Your timer would not do any painting but rather manipulate the painting-related data. You should never attempt to do any painting on a graphics object outside of the EventDispatcherThread of Swing or outside of the paintComponent methods of JComponents. (refer to the documentation of these methods for further information)
Here is an example of how custom painting with a timer manipulating color could look like:
public static void main(String[] args) {
EventQueue.invokeLater(Example::new);
}
// this is the painting-related data that is being manipulated by the timer
private int currentColorIndex;
public Example() {
JFrame frame = new JFrame("Custom Painting");
frame.setSize(640, 480);
frame.setLocationRelativeTo(null);
Color[] allColors = {Color.RED, Color.BLUE, Color.GREEN,
Color.YELLOW, Color.ORANGE, Color.MAGENTA};
JPanel myCustomPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
// here the painting related data is being used by the custom JPanel implementation
g.setColor(allColors[currentColorIndex]);
g.fillRect(0, 0, getWidth(), getHeight());
}
};
frame.setContentPane(myCustomPanel);
Timer timer = new Timer(100, e -> {
// the timer does not use any graphics objects, etc, but rather manipulates our painting-related data
currentColorIndex = (currentColorIndex + 1) % allColors.length;
// whenever the painting-related data has changed we need to call repaint() on our custom JPanel implementation
myCustomPanel.repaint();
});
timer.setRepeats(true);
timer.start();
frame.setVisible(true);
}
Java Canvas when I resize the JFrame, the canvas stops drawing
I found the solution: different loops for draw and update:
public class MyCanvas {
public static void main(String[] args) {
new MyCanvas("MyCanvas",new Dimension(400,400));
}
private static final int frameRate = 1000 / 30;
private JFrame frame;
private JPanel panel;
private int delta;
private long lastLoopTime;
private volatile boolean running = false;
private int frameCount = 0;
public MyCanvas(String name, Dimension size) {
frame = new JFrame(name);
panel = new JPanel() {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
if (running) repaint();
}
};
frame.setContentPane(panel);
frame.setSize(size);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(size);
panel.setLayout(null);
frame.setResizable(true);
running = true;
frame.setVisible(true);
lastLoopTime = System.nanoTime();
new Thread(()->{
while (running) {
update();
frameCount++;
try {
Thread.sleep(frameRate);
} catch (InterruptedException e) {}
}
},"Game Loop").start();
}
int x = 30;
public final void update() {
x++;
}
public final void draw(Graphics g) {
g.setColor(Color.darkGray);
g.fillRect(0,0,getSize().width,getSize().height);
g.setColor(Color.gray);
g.fillRect(0,0,500,500);
g.setColor(Color.blue);
g.fillRect(x,30,300,300);
}
public final Dimension getSize() {
return frame.getSize();
}
public final void setSize(Dimension size) {
frame.setSize(size);
}
}
Related Topics
Do/Can Abstract Classes Replace Interfaces
String Array Initialization in Java
Jsoup Cookies for Https Scraping
Find Duplicate Element in Array in Time O(N)
Does Java Have Any Mechanism for a Vm to Trace Method Calls on Itself, Without Using Javaagent, etc
How to Convert Double[] to Double[]
Convert Bufferedinputstream into Image
Displaying Fancy Equations with Java
How to Convert Utf-8 to Us-Ascii in Java
Compareto with Primitives -> Integer/Int
Things Possible in Intellij That Aren't Possible in Eclipse
Java Naming Convention with Acronyms
Jackson/Hibernate, Meta Get Methods and Serialization
Arraylist Contains Case Sensitivity
Tomcat7 Starts Too Late on Ubuntu 14.04 X64 [Digitalocean]