Reputation: 13
Attempting to draw my rectangle across the screen horizontally in realtime. When I run this I get nothing but the JFrame. I'm not sure what I am missing aside from maybe some type of threading freeze to redraw the shape maybe?
public class ScreenTest extends JFrame {
int rectY = 50;
public ScreenTest()
{
setSize(300,200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
private class DrawPanel extends JPanel {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(80, rectY, 50, 50);
}
}
public void Draw()
{
DrawPanel test = new DrawPanel();
add(test);
while (rectY < 200)
{
rectY = rectY + 10;
test.repaint();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ScreenTest myWindow = new ScreenTest();
myWindow.Draw();
}
}
Upvotes: 1
Views: 52
Reputation: 49
it is working but is so fast that you can't see it, you need to make the loop which changes the Y coordinate slower with a delay. to solve it i used Thread.sleep() in the while loop:
package paquete;
import javax.swing.*;
import java.awt.*;
public class ScreenTest extends JFrame {
int rectY = 50;
public ScreenTest()
{
setSize(300,200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
private class DrawPanel extends JPanel {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(80, rectY, 50, 50);
}
}
public void Draw() throws InterruptedException {
DrawPanel test = new DrawPanel();
add(test);
while (rectY < 200)
{
rectY = rectY + 10;
Thread.sleep(100);
test.repaint();
}
}
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
ScreenTest myWindow = new ScreenTest();
myWindow.Draw();
}
}
i hope this helps you, you can change the duration changing the number inside the argument of Thread.sleep()
Upvotes: 0
Reputation: 347184
Swing is single threaded and not thread safe.
What this means is, you should not perform any kind of long running or blocking operations within the "Event Dispatching Thread", as this will stop the UI from been painted or responding to new events.
It also means you should not update the UI, or any state the UI relies on, from outside the context of the Event Dispatching Thread.
Your code "is" working, but because the while-loop
can run so fast, it's completing before the window is realised on the screen (visible and updatable). Swing is also optimised, so all the repaint
calls are likely been consolidated into a single repaint pass.
A better solution might to start with Swing `Timer, which acts as a pseudo repeating loop, but which is called on within the context of the Event Dispatching Thread.
Start by taking a look at Concurrency in Swing and How to Use Swing Timers for more details.
import java.awt.Color;
import java.awt.EventQueue;
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.Timer;
public class ScreenTest extends JFrame {
public ScreenTest() {
setSize(300, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
private class DrawPanel extends JPanel {
int rectY = 50;
private Timer timer;
// This is just convince
@Override
public void addNotify() {
super.addNotify();
timer = new Timer(25, new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
rectY += 1;
repaint();
}
});
// Otherwise it disappears to fast
timer.setInitialDelay(1000);
timer.start();
}
@Override
public void removeNotify() {
super.removeNotify();
timer.stop();
timer = null;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(80, rectY, 50, 50);
}
}
public void Draw() {
DrawPanel test = new DrawPanel();
add(test);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ScreenTest myWindow = new ScreenTest();
myWindow.Draw();
}
});
}
}
Upvotes: 1