I am having a problem using the repaint method in the following code.Please suggest how to use repaint method so that my screen is updated for a small animation.
This is my code :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class movingObjects extends JPanel {
Timer timer;
int x = 2, y = 2, width = 10, height = 10;
public void paintComponent(final Graphics g) { // <---- using repaint method
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
g.setColor(Color.red);
g.drawOval(x, y, width, height);
g.fillOval(x, y, width, height);
x++;
y++;
width++;
height++;
}
};
new Timer(100, taskPerformer).start();
}
}
class mainClass {
mainClass() {
buildGUI();
}
public void buildGUI() {
JFrame fr = new JFrame("Moving Objects");
movingObjects obj = new movingObjects();
fr.add(obj);
fr.setVisible(true);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fr.setSize(1300, 700);
}
public static void main(String args[]) {
new mainClass();
}
}
Don't try to delay the actual painting. The component needs to be painted when it is asked to be painted.
Instead, use your timer to modify some state in MovingObjects. In your case the state you want to change is x, y, width and height. When your timer fires, increment those values and call repaint().
Then in your paintComponents method, you would just use those values to paint the component
public void paintComponent(Graphics g) {
g.setColor(Color.red);
g.drawOval(x,y,width,height);
g.fillOval(x,y,width,height);
}
Edit
Not sure what you're having trouble with, but calling repaint() is not difficult:
ActionListener taskPerformer=new ActionListener() {
public void actionPerformed(ActionEvent ae) {
x++;
y++;
width++;
height++;
repaint();
}
};
new Timer(100,taskPerformer).start();
Related
I am trying to learn the paint method and get a ball to move across the frame. here is my code so far. w=.
I currently have two classes One is the main and one for the ball.
this is the main class
import java.awt.;
import javax.swing.;
public class PaintTest extends JPanel {
int x = 0;
int y = 0;
public void moveBall(){
x = x + 1;
y = y + 1;
}
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setSize(500,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Ball ball = new Ball(x,y);
while(true){
ball.moveBall();
repaint();
}
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g.setColor(Color.magenta);
g.drawLine(0,100,500,100);
g.drawLine(0,101,500,101);
g.drawLine(0,102,500,102);
g.drawLine(0,103,500,103);
g2.fillOval(x,y,35,35);
}
}
and here is the ball class
public class Ball {
int x,y;
public Ball(int x, int y){
this.x = x;
this.y = y;
}
}
now when i compile I get an error saying cannot find symbol ball in class PaintTest even though I am calling it from the class Ball. I am aware of the repaint error as i do not know what to put in front of it.
Draw in a JPanel
In its paintComponent method not in its paint method -- this gives you double buffering.
Call the super's paintComponent method in your override. This allows the JPanel to do housekeeping drawing including erasing the oval image at its old position.
Don't use a while (true) loop as this can cause serious Swing threading issues. Use a Swing Timer instead.
In the Swing Timer, increment your animation variables and then call repaint(). This will tell Swing to repaint the component which will re-draw the oval in the new location.
Don't guess at this stuff as that leads to frustration since Swing graphics coding is a different beast. Instead check the tutorials. You can find links to the Swing tutorials and to other Swing resources here: Swing Info. Also check out Performing Custom Painting with Swing.
Graphics2D goodies: RenderingHints can be used to smooth out your image jaggies.
More Graphics2D goodies: Stroke can be used to draw thicker lines when needed.
For example:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
#SuppressWarnings("serial")
public class PaintTest extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
private static final int TIMER_DELAY = 20;
private static final Stroke STROKE = new BasicStroke(5f);
private int x;
private int y;
public PaintTest() {
new Timer(TIMER_DELAY, new TimerListener()).start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// to smooth graphics
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.magenta);
Stroke initialStroke = g2.getStroke();
g2.setStroke(STROKE);
g.drawLine(0, 100, 500, 100);
g2.setStroke(initialStroke);
g2.fillOval(x, y, 35, 35);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
x++;
y++;
repaint();
}
}
private static void createAndShowGui() {
PaintTest mainPanel = new PaintTest();
JFrame frame = new JFrame("PaintTest");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
You have to put the paintComponent method in a JPanel. You can do it by using something like this.
JPanel panel = new JPanel(){
#Overide
public void paintComponent(Graphics g){
super.paint();
// Draw Stuff Here
}
};
The reason you are not getting the ball to move across the frame is that you are not calling the repaint method. You should do so on a thread.
Thread th = new Thread(new Runnable(){
#Overide
public void run(){
while(frame.isVisible()){
ball.moveBall();
panel.repaint();
try{Thread.sleep(5);}catch(Exception e){e.printStackTrace();}
}
}
});
Also, why are you making ball a instance of the PaintTest class? To get only one frame and ball you would want to add a class named Ball and use that to make an instance:
public class Ball{
int x, y;
public Ball(int x, int y){
this.x = x;
this.y = y;
}
}
That is why you were getting 2 frames.
Then you would want to get rid of the x and y variables in the main class. To make an instance using this class you would do:
Ball ball = new Ball(x, y);
Then to paint the ball in the paintComponent method you would do:
g.fillOval(ball.x, ball.y, 35, 35);
You didn't call the repaint(); method.
You don't need the y + 1 part.
Instead of using the while(true) loop, you should use a for loop.
You didn't call the super.paint() method.
You didn't use any Thread.sleep(), which made the ball move across instantaneously.
Here is the code:
import java.awt.*;
import javax.swing.*;
public class PaintTest extends JFrame {
int x = 8;
int y = 30;
public void moveBall(){
x = x + 1;
//y = y + 1;
try{
Thread.sleep(500);
} catch(InterruptedException e){
}
repaint();
}
public static void main(String[] args){
PaintTest frame1 = new PaintTest();
PaintTest ball = new PaintTest();
for(int i = 0; i<100; i++){
//while(true){
ball.moveBall();
}
}
public PaintTest() {
super("Paint Test");
setSize(500,500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D) g;
super.paint(g);
super.paint(g2);
g.setColor(Color.magenta);
g.drawLine(0,100,500,100);
g.drawLine(0,101,500,101);
g.drawLine(0,102,500,102);
g.drawLine(0,103,500,103);
g.fillOval(x,y,35,35);
}
}
This code will make the ball move across the screen VERY slowly. If you want to speed it up, change the number of miliseconds in the Thread.sleep(miliseconds) part to a smaller number of miliseconds.
I'm currently trying to make a game with a GUI that needs to paint new things on the screen on button clicks. For example:
public class GUI() extends JPanel {
public void paintComponent() {
/*
*Basic initial set up here
*/
// ***** Call method here on mouse click *****
}
public void setUpGUI() {
JFrame mainFrame = new JFrame();
GUI paintGUI = new GUI();
clickDetector click = new clickDetector();
mainFrame.addMouseListener(click);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setSize(500, 500);
mainFrame.getContentPane().add(paintGUI);
mainFrame.setVisible(true);
}
public static void main(String args[]) {
GUI gui = new GUI();
gui.setUpGUI();
}
}
I need to implement a method in the // ***** Call method here on mouse click ***** that will paint on the new additions to the frame (in my case these are circles that represent pieces on the board) but I'm unsure of how to do this on a button click. How can I repaint the frame each time the mouse is clicked so that I can modify my game board?
----EDIT----
Here is my paintComponent code, along with the listener being used to repaint.
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Method called");
g.setColor(Color.red);
for(int y = 0; y < 6; y++) {
for(int x = 0; x < 7; x++) {
g.fillOval(x*70 + 10, y*70 + 10, 50, 50);
}
}
g.setColor(Color.BLACK);
g.fillRect(0, 430, 500, 50);
g.setColor(Color.white);
g.drawString("CONNECT FOUR", 250, 450);
g.setColor(Color.LIGHT_GRAY);
click.paintPiece(g);
}
public void mouseClicked(MouseEvent e) {
this.repaint();
}
Here is the method that paintComponent should be calling, but is not
public void paintPiece(Graphics g) {
int x = getMouseX() + 10;
int y = mover.getRow() + 10;
g.fillOval(x, y, 50, 50);
}
Just create a mouse listener:
MouseListener listen = new MouseListener()
{
void mouseClicked(MouseEvent e){}
void mouseReleased(MouseEvent e){}
void mousePressed(MouseEvent e){paintGUI.repaint();}
void mouseExited(MouseEvent e){}
void mouseEntered(MouseEvent e){}
};
paintGUI.addMouseListener(listen);
Every time you click inside of the JPanel, you should now see it repaint. Likewise, if you want to update when a JButton is pressed, just use ActionListener instead:
ActionListener listen = new ActionListener()
{
public void actionPerformed(ActionEvent e){paintGUI.repaint();}
}
button.addActionListener(listen);
This should be placed in your setUpGUI() method.
Add a Action Event listener to the button.
Oracle Docs Action Event Listener
In the actionPerformed method add whatever needs to be added then call
repaint();
This changes will let you paint a rectangle each time you click on the frame
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GUI extends JPanel implements MouseListener{
private Rectangle rect;
private int width = 100;
private int height = 100;
public GUI(int x, int y, int width, int height)
{
rect = new Rectangle(x, y, width, height);
}
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
g2d.draw(rect);
}
public void mouseClicked(MouseEvent e) {
rect = new Rectangle(e.getX(), e.getY(), width, height);
repaint();
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
public void setUpGUI() {
JFrame mainFrame = new JFrame();
mainFrame.addMouseListener(this);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setSize(500, 500);
mainFrame.getContentPane().add(this);
mainFrame.setVisible(true);
}
public static void main(String args[]) {
GUI gui = new GUI(0,0,100,100);
gui.setUpGUI();
}
}
Notice the MouseListener was implemented by the GUI class and when you are trying to initialize the MouseListener for the frame, you are just putting this as parameter, which will refer to the GUI class and therefore to your JPanel
I have this simple paint code that should draw but instead it moves the oval around the panel.
When I remove super.paintComponent(g) line the program works it paints and not just move the oval, but I keep reading that we should not remove this line, so what can I do to leave the line in but still get the desired results?
class OraclePaint extends JFrame {
public static void main(String[] args) {
OraclePaint ss = new OraclePaint();
ss.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ss.add(new MyPanel());
ss.setSize(250, 200);
ss.setVisible(true);
}
}
class MyPanel extends JPanel {
private int x = -10, y = -10;
public MyPanel() {
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent event) {
x = event.getX();
y = event.getY();
repaint();
}
}); // end call to addMouseMotionListener
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillOval(x, y, 22, 22);
}
}
Based on the description, I assume that you want something like "a simple paint program".
It is correct to invoke super.paintComponent(g) as the first line of an overridden paintComponent. And it is true that this erases the background (that is, everything that was painted before will be deleted).
In Swing, everything that you want to paint has to be painted in the paintComponent method (or in any method that is called from there, and receives the same Graphics object).
If you want to "save" everything that you have painted, you have to paint everything into an image (that is, into a BufferedImage), and paint this image in your paintComponent method.
There are some other issues with the code, but without changing too much of the remaining code, this could roughly (!) be achieved like this:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
class OraclePaint extends JFrame {
public static void main(String[] args) {
OraclePaint ss = new OraclePaint();
ss.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ss.add(new MyPanel());
ss.setSize(250, 200);
ss.setVisible(true);
}
}
class MyPanel extends JPanel {
private BufferedImage image = null;
public MyPanel() {
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent event) {
if (image != null) {
// Paint into the image
Graphics g = image.getGraphics();
g.setColor(Color.BLACK);
g.fillOval(event.getX(), event.getY(), 22, 22);
g.dispose();
repaint();
}
}
}); // end call to addMouseMotionListener
}
// Make sure that the image is not 'null' and that
// it has the same size as this panel
private void validateImage()
{
if (image == null)
{
image = new BufferedImage(getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
}
if (image.getWidth() != getWidth() || image.getHeight() != getHeight())
{
BufferedImage newImage = new BufferedImage(getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics g = newImage.getGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
image = newImage;
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
validateImage();
g.drawImage(image, 0, 0, null);
}
}
change your MyPanel to this:
class MyPanel extends JPanel
{
private int x2 = 0, y2 = 0;
private int x1 = 0, y1 = 0;
public MyPanel()
{
addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseDragged( MouseEvent event )
{
x2 = event.getX();
y2 = event.getY();
repaint();
}
}
); // end call to addMouseMotionListener
addMouseListener(new MouseListener() {
#Override
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
}
});
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.fillOval(x1, y1, x2, y2);
}
}
I want to move a pixel in a JFrame but use of Thread.Sleep(1000) method eventuate to crash my JFrame. why this problem happen? and how solve it?
Thank You
public class Main {
public static void main(String[] args) throws InterruptedException {
JFrame mainFrame = new JFrame("Sadra Graphics");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SadraGraphics sadraGraphics = new SadraGraphics();
sadraGraphics.setPreferredSize((new Dimension(640,480)));
mainFrame.getContentPane().add( sadraGraphics );
mainFrame.pack();
mainFrame.setVisible(true); }}
public class SadraGraphics extends JPanel {
public void paintComponent (Graphics g){
super.paintComponent(g);
this.setBackground(Color.white);
for (int i = 0; i <=639; i++) {
g.setColor(Color.red);
g.drawLine(i, i * 3 / 4, i, i * 3 / 4);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
g.setColor(Color.white);
g.drawLine(i,i*3/4,i,i*3/4);
}
}
}
Don't use Thread.sleep. Even if you were to use it, you never want to use it in the paintComponent method.
Instead use a javax.swing.Timer, that will update some variables and repaint every so many milliseconds
public SadraGraphics() {
Timer timer = new Timer(1000, new ActionListener(){
public void actionPerformed(ActionEvent e) {
// do something here that will refresh some variables that you
// are using to paint, then call repaint()
repaint();
}
});
timer.start();
}
See more at How to use Swing Timers
Here a simple runnable example
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame mainFrame = new JFrame("Sadra Graphics");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SadraGraphics sadraGraphics = new SadraGraphics();
sadraGraphics.setPreferredSize((new Dimension(640, 480)));
mainFrame.getContentPane().add(sadraGraphics);
mainFrame.pack();
mainFrame.setVisible(true);
}
});
}
}
class SadraGraphics extends JPanel {
int x1 = 0;
int y1 = 50;
int x2 = 0;
int y2 = 200;
public SadraGraphics() {
Timer timer = new Timer(30, new ActionListener() {
public void actionPerformed(ActionEvent e) {
x1 += 2;
x2 += 2;
repaint();
}
});
timer.start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(x1, y1, x2, y2);
}
}
Side Note
Run Swing apps from the EDT using SwingUtilities.invokeLater.
paintComponent should be protected not public
Don't set the background from with the paintComonent method. You can either do it from the constructor or instead you can paint the background in the paintComponent method by doing this
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
Please note I haven't tested this on a Windows-machine only on a Mac-machine. I'm not so sure whether this also occurs on a Windows-machine...
When I resize my Java-application the content is invisible. I already found a way to fix it after resizing it, but not while the user is resizing the window.
I'm not using Swing or something because it makes my binary so slow (in my opinion).
The structure is like this:
Frame My main-window
Container Content view of main-window
Container-based subviews that including the paint(Graphics g)-method
I've added all listeners to My main-window and now I'm able to redraw the Content-view after resizing the window.
public void componentResized(ComponentEvent e) {
this.contentView.paint(this.contentView.getGraphics());
}
I am beware of the fact using the paint(getGraphics())-method isn't a really good way to do this, but since the repaint()-method doesn't do anything at all, it's the only working possibility.
While resizing, all painted content becomes invisible. However, when I add a Button-instance to my Content-view and resize my Main-window, the button doesn't get invisible.
I am able to trace the 'live'-resize event:
public void componentMoved(ComponentEvent e) {
System.out.println("Live-resize");
}
When I start resizing this method is not being called.
While resizing it generates "Live-resize" in my log every single pixel I resize the window.
When I stop resizing this method is not being called, the componentResized-method does.
When I add my repaint-method (or the official repaint-method) to the 'live'-resize event like this, I still get the output, however, it's not repainting or something
public void componentMoved(ComponentEvent e) {
System.out.println("Live-resize");
this.contentView.paint(this.contentView.getGraphics());
}
Or
public void componentMoved(ComponentEvent e) {
System.out.println("Live-resize");
this.contentView.repaint();
}
When I minimize my application to the dock and maximize the application again, the same thing happens, I guess that the same code is needed to fix this.
I'm not using Graphics2D or something, just Graphics.
Could you please explain me how I can repaint the views?
Thanks in advance,
Tim
For reference, here is the same program using Swing. Because JPanel is double buffered, it doesn't flicker as the mouse is released after resizing.
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class SwingPaint {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.add(new CirclePanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private static class CirclePanel extends JPanel {
private static final Random r = new Random();
public CirclePanel() {
this.setPreferredSize(new Dimension(320, 240));
this.setForeground(new Color(r.nextInt()));
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
CirclePanel.this.update();
}
});
}
public void update() {
this.setForeground(new Color(r.nextInt()));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension size = this.getSize();
int d = Math.min(size.width, size.height) - 10;
int x = (size.width - d) / 2;
int y = (size.height - d) / 2;
g.fillOval(x, y, d, d);
g.setColor(Color.blue);
g.drawOval(x, y, d, d);
}
}
}
I'm more familiar with Swing, but the article Painting in AWT and Swing distinguishes between system- and application-triggered painting. The example below shows how the system invokes paint() as the window is resized, while the application invokes repaint(), which calls update(), in response to a mouse event. The behavior is cross-platform.
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class AWTPaint {
public static void main(String[] args) {
Frame frame = new Frame();
frame.add(new CirclePanel());
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.pack();
frame.setVisible(true);
}
private static class CirclePanel extends Panel {
private static final Random r = new Random();
public CirclePanel() {
this.setPreferredSize(new Dimension(320, 240));
this.setForeground(new Color(r.nextInt()));
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
CirclePanel.this.repaint();
}
});
}
#Override
public void update(Graphics g) {
this.setForeground(new Color(r.nextInt()));
}
#Override
public void paint(Graphics g) {
Dimension size = this.getSize();
int d = Math.min(size.width, size.height) - 10;
int x = (size.width - d) / 2;
int y = (size.height - d) / 2;
g.fillOval(x, y, d, d);
g.setColor(Color.blue);
g.drawOval(x, y, d, d);
}
}
}
Okay, I finally fixed it.
Instead of redrawing it every time in the paint(Graphics g)-method, you need to buffer the output and only redraw that image (I kinda hoped Java would be already doing that, just like Obj-C).
public BufferedImage buffer;
public void redraw() {
buffer = new BufferedImage(
200, // height
300, // width
BufferedImage.TYPE_4BYTE_ABGR); // ABGR = RGBA, 4-byte (r, g, b, a) per pixel
Graphics g = buffer.getGraphics();
// do your drawing here
if (this.getGraphics()) {
// 'this' is already shown, so it needs a redraw
this.paint(this.getGraphics()); // little hack
}
}
public void update(Graphics g) {
this.paint(g);
}
public void paint(Graphics g) {
g.drawImage(buffer, 0, 0, this);
}
Now, when you minimize the window and maximize it again, the paintings remain. Only, the window's flickering now for .1-second or so, but I don't really care about that.