How to Make Canvas with Swing

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.

Sample Image

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



Leave a reply



Submit