I've been struggling to get this to work. The only solution (but terrible solution) I found was re creating a new window every frame which is horrible for performance and other obvious reasons. Here is what I have but I'm unsure about how I can go about redrawing every frame. Or if there's another approach I can take to achieve the same functionality, how can I go about doing it?
public static Window w = null;
@SuppressWarnings("serial")
private static void initializeWindow(final Dimension d) {
int windowHeight = d.height - 1;
w = new Window(null) {
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
//painting goes here (but it only seems to draw for one frame)
//for some repainting doesn't seem to work
}
@Override
public void update(Graphics g) {
paint(g);
System.out.println(true);
}
};
w.setAlwaysOnTop(true);
w.setBounds(0, 0, d.width, windowHeight);
w.setBackground(new Color(0, true));
w.setVisible(true);
}
I tried the code block attached and I expected to be able to update the window every frame with newly painted stuff.
You problem is pretty basic - you need some way to update the UI on a regular bases.
Your problem is further complicated by the fact that Swing is single thread and NOT thread safe. Lucky for you, the Swing team fore saw this issue and provided the Swing Timer
class.
Start by seeing Concurrency in Swing and How to Use Swing Timers for more details.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame window = new JFrame();
window.setUndecorated(true);
window.setBackground(new Color(0, true));
window.add(new TestPane());
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
}
});
}
public class TestPane extends JPanel {
enum Direction {
UP, DOWN;
}
private Timer timer;
private Direction direction = Direction.UP;
private double yDelta = 2;
private double yPos = 380;
private Shape ball = new Ellipse2D.Double(0, 0, 20, 20);
public TestPane() {
setOpaque(false);
timer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (direction == Direction.UP) {
yPos -= yDelta;
yDelta -= 0.006;
if (yDelta <= 0.0) {
yDelta = 0;
direction = Direction.DOWN;
}
if (yPos < 0) {
yPos = 0;
direction = Direction.DOWN;
}
} else if (direction == Direction.DOWN) {
yPos += yDelta;
yDelta += 0.01;
if (yDelta > 2.0) {
yDelta = 2.0;
}
if (yPos + ball.getBounds().height > getHeight()) {
yPos = getHeight() - ball.getBounds().height;
direction = Direction.UP;
yDelta = 2;
}
}
repaint();
}
});
}
@Override
public void addNotify() {
super.addNotify();
timer.start();
}
@Override
public void removeNotify() {
timer.stop();
super.removeNotify();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
g2d.setColor(Color.RED);
g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2d.translate(190, yPos);
g2d.fill(ball);
g2d.dispose();
}
}
}