Redrawing frame using JPanel - java

I am beginner with java; I have recently moved from another programming language and I only know basics.
I have a problem with redrawing using JPanel. I can draw text when I create new object, but I have problems redrawing it. Function tick() is called in short intervals by Main class and is supposed to redraw JPanel.
package main;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
class Surface extends JPanel{
private void doDrawing(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawString("Hello World! "+Main.integer, 50, 50);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
}
class Display extends JFrame {
public Display() {
Surface surface = new Surface();
setTitle("salami");
setSize(400, 300);
}
public void tick() {
surface.redraw();
}
}

Actually, you redraw the JPanel.
Here's the simplest example I have of a redrawn JPanel. It's a clock that's redrawn every 200 milliseconds.
You create the GUI first, then use a Runnable in a Thread or a Swing Timer to update the GUI periodically.
And here's the code.
package com.ggl.testing;
import java.awt.Color;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class SimpleClock implements Runnable {
private JFrame frame;
private JPanel panel;
private JTextField clockDisplay;
private Timer timer;
#Override
public void run() {
frame = new JFrame("Clock");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent event) {
exitProcedure();
}
});
createClockPanel();
frame.add(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
timer = new Timer(this);
new Thread(timer).start();
}
private void createClockPanel() {
panel = new JPanel();
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 6));
clockDisplay = new JTextField(12);
clockDisplay.setEditable(false);
clockDisplay.setHorizontalAlignment(JTextField.CENTER);
panel.add(clockDisplay);
}
public void exitProcedure() {
timer.setRunning(false);
frame.dispose();
System.exit(0);
}
public void setText(String text) {
clockDisplay.setText(text);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new SimpleClock());
}
public class Timer implements Runnable {
private volatile boolean running;
private SimpleClock clock;
private SimpleDateFormat timeFormat;
public Timer(SimpleClock clock) {
this.clock = clock;
this.running = true;
this.timeFormat = new SimpleDateFormat("h:mm:ss a");
}
#Override
public void run() {
while (running) {
displayTime();
sleep();
}
}
public void displayTime() {
final Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();
final String s = timeFormat.format(date);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
clock.setText(s);
}
});
}
public void sleep() {
try {
Thread.sleep(200L);
} catch (InterruptedException e) {
}
}
public synchronized void setRunning(boolean running) {
this.running = running;
}
}
}

You need to add your extened JPanel surface to your JFrame
public Display() {
Surface surface = new Surface();
add(surface);
setTitle("salami");
setSize(400, 300);
}
If this does not work post a SSCCE

Related

Repainting-Thread doesn't repaint Inner-Class JPanel

I want to make a little rain program in swing, but for some reason I cannot repaint the panel from another class. I tried using an inner class for the panel this time, but it doesn't seem to work with repainting it from another class/thread. Does someone know why?
sscce:
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
public class UI extends JFrame {
public static void main(String[] args) {
UI myProgram = new UI();
myProgram.setVisible(true);
}
public UI() {
this.setSize(new Dimension(500,300));
this.setBackground(Color.WHITE);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
UserPanel p = new UserPanel(this);
}
public class UserPanel extends JPanel implements ActionListener {
private Timer time = new Timer(1, this);
private UI myFrame;
public UserPanel(UI myFrame) {
this.myFrame = myFrame;
this.setSize(myFrame.getSize());
time.start();
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("painting");
g.setColor(Color.BLACK);
g.fillRect(this.getWidth()/2, this.getHeight()/2, 50,50);
}
}
}
UI Class (with inner class JPanel):
package Rain;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
public class UI extends JFrame {
public UI() {
this.setSize(new Dimension(500,300));
this.setBackground(Color.WHITE);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
UserPanel p = new UserPanel(this);
}
private class UserPanel extends JPanel implements ActionListener {
private Timer time = new Timer(1, this);
private UI myFrame;
private ArrayList<Raindrop> rain = new ArrayList<Raindrop>();
private static final int AMOUNT = 50;
private Random rand = new Random();
public UserPanel(UI myFrame) {
this.myFrame = myFrame;
this.setSize(myFrame.getSize());
for(int i = 0; i < AMOUNT; i++) {
createRain();
}
new Painter(this);
time.start();
}
public void createRain() {
float distance = rand.nextFloat() * 90 + 10;
int x = rand.nextInt(this.getWidth());
int y = 100;
rain.add(new Raindrop(distance,x,y));
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("tick");
for(Raindrop r : rain) {
r.fall();
}
}
public void paintComponent(Graphics g) {
System.out.println("painting");
g.setColor(this.getBackground());
g.fillRect(0,0,this.getWidth(),this.getHeight());
for(Raindrop r : rain) {
r.draw(g);
}
}
}
}
Painter:
package Rain;
import javax.swing.JPanel;
public class Painter extends Thread {
private JPanel p;
public Painter(JPanel p) {
this.p = p;
this.start();
}
public void run() {
while(true) {
System.out.println("trying to paint..");
p.repaint();
}
}
}
Console Output:
trying to paint..
tick
trying to paint..
tick
...
Expected Output:
trying to paint..
painting
tick
trying to paint..
...
The thread does work but it never calls the paintComponent(Graphics g) function in the panel
All Swing applications must run on their own thread, called EDT. (Hopefully, you start your application by calling SwingUtilities#invokelater method). So, repainting a component outside of Event Dispatch Thread is really bad bad (bad) idea. Instead of creating new Thread, repaint the component inside javax.swing.Timer's action listener since it will run in EDT.
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("tick");
for(Raindrop r : rain) {
r.fall();
}
repaint(); //repaint in EDT
}
Also, when you #Override paintComponent method, always start by calling super.paintComponent(g);
public void paintComponent(Graphics g) {
super.paintComponent(g);//let component get painted normally
System.out.println("painting");
g.setColor(this.getBackground());
g.fillRect(0,0,this.getWidth(),this.getHeight());
for(Raindrop r : rain) {
r.draw(g);
}
}
UPDATE after your SSCCE
In order a component to get painted, it must have a parent. You UserPanel p = new UserPanel(this); but you never add it to the frame:
UserPanel p = new UserPanel(this);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(p);
The complete SSCCE:
public class UI extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> { //Run in EDT
UI myProgram = new UI();
myProgram.setVisible(true);
});
}
public UI() {
super("title");//call super for frame
this.setSize(new Dimension(500, 300));
this.setBackground(Color.WHITE);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
UserPanel p = new UserPanel(this);
//Use border layout to make p fit the whole frame
getContentPane().setLayout(new BorderLayout());
getContentPane().add(p, BorderLayout.CENTER);
}
public class UserPanel extends JPanel implements ActionListener {
private Timer time = new Timer(1, this);
private UI myFrame;
public UserPanel(UI myFrame) {
this.myFrame = myFrame;
this.setSize(myFrame.getSize());
time.start();
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("painting");
g.setColor(Color.BLACK);
g.fillRect(this.getWidth() / 2, this.getHeight() / 2, 50, 50);
}
}
}
Don't ignore the SwingUtilities.invokeLater.

Java Swing multithread management with observer pattern

My goal is to draw a rectangle and move it smoothly from left to right, using Observer pattern.
I have a Model class, which is the Observable where I put the coordinates of the rectangle, and a Display class which is the Observer and perform repaint each time the coordinates change in the Model.
The coordinates changes in the Model are made in a while loop inside a SwingWorker : at each iteration I increment the x coordinate by one, then sleep for 100 ms, then notify the Observer (the Display) which only task is to perform a repaint. As you see the repaint() method is called on the EDT like it is adviced to do.
The problem is that the move isn't smooth after about one second, the repaint frequency change and it seems that the rectangle is less and less repainted.
Here is the Model class :
import java.util.Observable;
import java.awt.EventQueue;
import javax.swing.SwingWorker;
public class Model extends Observable{
int xCoordinate;
Model(Display d){
SwingWorker<Void,Void> sw = new SwingWorker<Void,Void>(){
#Override
protected Void doInBackground() {
while(xCoordinate<600){
xCoordinate ++;
try {
Thread.sleep(100);
} catch (InterruptedException ex) {}
setChanged();
notifyObservers(xCoordinate);
}
return null;
}
};
addObserver(d);
sw.execute();
}
public static void main(String[] a){
EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
Display d = new Display();
Model m = new Model(d);
d.model = m;
}
});
}
}
And here is the Display class :
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Display extends JFrame implements Observer{
Model model;
int xCoordinate;
Display(){
getContentPane().add(new JPanel(){
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(xCoordinate, 1, 50, 50);
}
});
setSize(600, 600);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
#Override
/* arg is the updated xCoordinate*/
public void update(Observable o, Object arg) {
xCoordinate = (Integer)arg;
EventQueue.invokeLater(new Runnable(){
#Override
public void run() {
repaint();
}
});
}
}
I tried other methods, for instance using Timer in the Display, but that didn't work either. The SwingWorker maybe isn't useful here because calculations made on the SwingWorker thread are easy (increment by one) but I will need it for the heavy calculations I intend to do on my project (a pool game).
I also tried debugging by looking at time between two repaints (in Display) and time between two incrementations (in Model) and it was as expected about 100 ms each.
Thanks in advance
Okay, so as an initial test, I started with a Swing Timer...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Model model = new Model();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane(model));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
model.update();
}
});
timer.setInitialDelay(1000);
timer.start();
}
});
}
public class Model extends Observable {
private int xCoordinate;
public void update() {
xCoordinate++;
setChanged();
notifyObservers(xCoordinate);
}
public int getXCoordinate() {
return xCoordinate;
}
}
public class TestPane extends JPanel implements Observer {
private Model model;
public TestPane(Model model) {
this.model = model;
model.addObserver(this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g.setColor(Color.RED);
g.fillRect(model.getXCoordinate(), 1, 50, 50);
g2d.dispose();
}
#Override
public void update(Observable o, Object arg) {
System.out.println(arg);
repaint();
}
}
}
The thing I found was, you never call setChanged on the Observable, which during my testing, meant that it never called the Observers
I also did a test with a SwingWorker...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Model model = new Model();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane(model));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
SwingWorker worker = new SwingWorker() {
#Override
protected Object doInBackground() throws Exception {
Thread.sleep(1000);
while (true) {
model.update();
}
}
};
worker.execute();
}
});
}
public class Model extends Observable {
private int xCoordinate;
public synchronized void update() {
xCoordinate++;
setChanged();
notifyObservers(xCoordinate);
}
public synchronized int getXCoordinate() {
return xCoordinate;
}
}
public class TestPane extends JPanel implements Observer {
private Model model;
public TestPane(Model model) {
this.model = model;
model.addObserver(this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g.setColor(Color.RED);
g.fillRect(model.getXCoordinate(), 1, 50, 50);
g2d.dispose();
}
#Override
public void update(Observable o, Object arg) {
System.out.println(arg);
repaint();
}
}
}
Because of the thread synchronization issues, I synchronized access to the methods to ensure that values weren't changing between updates. Because you're using an Observer, could actually pass the "new state" to the Observer, so they aren't reliant on then value of the model at the time they use them.
Okay, so the long and short of it, you need to call setChanged on the Observable once it's been updated, so that notifyObservers will actually call the Observers
As someone undoubtedly point out, this approach suffers from inaccuracies in the timing, by it's nature, both Swing Timer and Thread.sleep only guarantee a "at least" timing and may verify between each update.
If you have a variable length operation, this will also affect the time between updates. Instead, you should be calculating the time it took you to perform your operation, subtract the amount of time you want to wait, you would then use this delay to calculate how long you want to "wait" between frames. You should also be using System.nanoTime over System.currentTimeMillis as it won't suffer from the same system clock synchronization issues

How does repaint() method behave inside an infinite for loop?

I have this code,
import java.awt.*;
import java.applet.*;
public class FirstApplet extends Applet
{
int len;
char ch;
String msg="Hello World ";
public void init()
{
setBackground(Color.CYAN);
setForeground(Color.WHITE);
}
public void start()
{
System.out.println("Inside Start");
repaint();
}
public void paint(Graphics g)
{
System.out.println("Inside paint");
g.drawString(msg,200,200);
}
}
It outputs a CYAN coloured background with Hello World on it.And on the console(cmd),it outputs-
Inside Start
Inside paint
Now if I modify the code to this-
import java.awt.*;
import java.applet.*;
public class FirstApplet extends Applet
{
String msg="Hello World ";
int len;
char ch;
public void init()
{
setBackground(Color.CYAN);
setForeground(Color.WHITE);
}
public void start()
{
System.out.println("Inside Start");
for(;;)
{
repaint();
}
}
public void paint(Graphics g)
{
System.out.println("Inside paint");
g.drawString(msg,200,200);
}
}
It outputs a white coloured screen with no text on it,and on the console it just outputs-
Inside Start
I am unable to understand the output of second program,Although I am calling the repaint() inside the for loop every time yet why the colour of the applet window is not changing to CYAN colour and why its not printing "Inside paint" on the console?Can somebody please help me out.
You're tying up the GUI's event thread with your infinite loop, so that although repaint() is being called, the GUI's event thread is unable to act on it. Consider using a Swing Timer or a background thread instead.
For example, and continuing with your 1890's Applet example:
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.*;
public class PaintEg extends Applet {
String msg = "Hello World ";
int len;
char ch;
public void init() {
setBackground(Color.CYAN);
setForeground(Color.WHITE);
}
public void start() {
System.out.println("Inside Start");
new Thread(new Runnable() {
public void run() {
for (;;) {
repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
public void paint(Graphics g) {
System.out.println("Inside paint");
g.drawString(msg, 10, 20);
}
}
Better maybe is a Swing example that uses a Swing Timer and performs basic animation:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class PaintEg2 extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private static final int TIMER_DELAY = 30;
private String msg = "Hello World ";
private int msgX = 0;
private int msgY = 0;
public PaintEg2() {
setBackground(Color.CYAN);
setForeground(Color.WHITE);
setFont(new Font(Font.SANS_SERIF, Font.BOLD, 20));
new Timer(TIMER_DELAY, new TimerListener()).start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString(msg, msgX, msgY);
}
#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) {
msgX++;
msgY++;
repaint();
}
}
private static void createAndShowGui() {
PaintEg2 mainPanel = new PaintEg2();
JFrame frame = new JFrame("PaintEg2");
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();
}
});
}
}
Note that in your code repaint() is being called and is being executed, but the paint manager is unable to act on this because it does so on the GUI's event thread. If the GUI's event thread is tied up, no painting can be done.
For more on how painting is done in Swing and AWT, please read Painting in AWT and Swing

window crash in java game development

This is my code which would create a window that would takeover my full screen and would have a background colour of blue and would print "Hello World" in black, but when I run this application my screen freezes and the text "Hello World" comes out and after 5 seconds the thread terminates, but background colour does not changes and the screen becomes like this!
Can anyone point out what am I doing wrong?
This is my Screen class:
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Window;
import javax.swing.JFrame;
public class Screen {
private GraphicsDevice graphic_card;
public Screen() {
GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
graphic_card = environment.getDefaultScreenDevice();
}
public void set_full_screen(DisplayMode mode, JFrame window) {
window.setUndecorated(true);
window.setResizable(false);
graphic_card.setFullScreenWindow(window);
if ((mode != null) && (graphic_card.isDisplayChangeSupported())) {
try {
graphic_card.setDisplayMode(mode);
} catch (Exception exception) {
// No handling of exception
}
}
}
public Window getFullScreenWindow() {
return graphic_card.getFullScreenWindow();
}
public void restore_screen() {
Window window = graphic_card.getFullScreenWindow();
if (window != null) {
window.dispose();
}
graphic_card.setFullScreenWindow(null);
}
}
And this my Mayank class:
import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JFrame;
public class Mayank extends JFrame {
public static void main(String[] args) {
DisplayMode display_mode = new DisplayMode(800, 600, 16, DisplayMode.REFRESH_RATE_UNKNOWN);
Mayank mayank = new Mayank();
mayank.run(display_mode);
}
public void run(DisplayMode display_mode) {
setBackground(Color.BLUE);
setForeground(Color.BLACK);
setFont(new Font("Arial", Font.PLAIN, 24));
Screen game_screen = new Screen();
try {
game_screen.set_full_screen(display_mode, this);
try {
Thread.sleep(5000);
} catch (Exception exception) {
// No handling of exception
}
} finally {
game_screen.restore_screen();
}
}
public void paint(Graphics g) {
g.drawString("Hello World!!", 200, 200);
}
}
I don't know where you got this code, but it is so wrong.
I created a GUI that displays a blue background for 5 seconds, then changes the background to white.
Here's the GUI.
All Swing applications must start with a call to the SwingUtilities invokeLater method to put the creation and execution of Swing components on the Event Dispatch thread (EDT).
Always draw on a JPanel. Never draw directly on a JFrame.
Your timer blocked the EDT. You must put timing and update events in a separate thread. When you change the GUI from a separate thread, you must execute the invokeLater method to ensure the update of the drawing panel is done on the EDT.
Here's the code.
package com.ggl.testing;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Manyak implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Manyak());
}
#Override
public void run() {
JFrame frame = new JFrame("Hello Word Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DrawingPanel drawingPanel = new DrawingPanel();
frame.add(drawingPanel);
frame.pack();
frame.setVisible(true);
new Thread(new Delay(drawingPanel)).start();
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = -685508126882892538L;
private Color color;
public DrawingPanel() {
this.setPreferredSize(new Dimension(400, 400));
this.color = Color.BLUE;
}
public void setColor(Color color) {
this.color = color;
this.repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.BLACK);
g.setFont(new Font("Arial", Font.PLAIN, 24));
g.drawString("Hello World!", 120, 200);
}
}
public class Delay implements Runnable {
private DrawingPanel drawingPanel;
public Delay(DrawingPanel drawingPanel) {
super();
this.drawingPanel = drawingPanel;
}
#Override
public void run() {
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
drawingPanel.setColor(Color.WHITE);
}
});
}
}
}

The Dimension of my screen is not being measured, MacOSX and NetBeans

package spaceinvaders;
//#author AlexB
import java.awt.Color;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.event.KeyAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class SpaceInvaders extends KeyAdapter implements MouseListener {
private JFrame frame;
private JPanel panel;
public static int screenSizeX;
public static int screenSizeY;
private Dimension screenSize;
public SpaceInvaders() throws IOException
{
//screenSize = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
screenSize = Toolkit.getDefaultToolkit().getScreenSize(); //Finds the screen size
screenSizeX = (int)screenSize.getWidth(); //The length of the screen
screenSizeY = (int)screenSize.getHeight(); //The height of the screen
frame = new JFrame("Space Invaders");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setResizable(false);
frame.setSize(screenSizeX, screenSizeY);
panel = new MyPanel();
frame.getContentPane().add(panel);
frame.addMouseListener(this);
frame.addKeyListener(this);
spriteStore.getImage();
}
#Override
public void mouseClicked(MouseEvent me)
{
}
#Override
public void mousePressed(MouseEvent me)
{
}
#Override
public void mouseReleased(MouseEvent me)
{
}
#Override
public void mouseEntered(MouseEvent me)
{
}
#Override
public void mouseExited(MouseEvent me)
{
}
class MyPanel extends JPanel
{
#Override
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2D = (Graphics2D)g;
g2D.setColor(Color.BLACK);
g2D.fillRect(0,0, screenSizeX, screenSizeY);
g2D.drawImage(spriteStore.player, playerEntity.xCoord, screenSizeY-100, null);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
SpaceInvaders spaceInvaders;
try
{
spaceInvaders = new SpaceInvaders();
}
catch (IOException ex) {}
}
}
);
System.out.println("" + screenSizeX + "" + screenSizeY);
}
}
The question is why does my dimension not measure? When it prints out the screenSizeX and screenSizeY it provides the value 0 for both. I am using a mac, and netbeans, this code normally worked on a windows computer.

Categories