So i want my methods to change the background color of my Frame every like 0.2 seconds and i tried a lot of diferent things like new methods and Threat sleep/wait but nothing worked even though trying it with System.out.print did. I have no idea what could work now so would be ice if someone helped me out, thank you beforehand!
PS.: dont mind the variable and method names was having fun with my friends xD
public void poggersModeOn()
{
f.setTitle("Insane rainbow pogg mode!!!!1!!!11!!1!! ");
int rot = (int)(Math.random()*255+1);
int gruen = (int)(Math.random()*255+1);
int blau = (int)(Math.random()*255+1);
f.setBackground(new Color(rot, gruen, blau));
}
public void poggersModeOff()
{
f.setTitle("Navigationssystem");
f.setBackground(new Color(255, 255, 255));
}
public void pogmethode() {
while(pogmode==true)
{
poggersModeOn();
//wait function right here
}
}
Assuming your using Swing, then you should use a Swing Timer, see How to Use Swing Timers
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
Timer timer = new Timer(250, new ActionListener() {
private Random rnd = new Random();
#Override
public void actionPerformed(ActionEvent e) {
int red = rnd.nextInt(255);
int green = rnd.nextInt(255);
int blue = rnd.nextInt(255);
setBackground(new Color(red, green, blue));
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
}
Why? Because Swing is single threaded (and not thread safe). See Concurrency in Swing for more details
Related
I have a class which create a JFrame with an image but everytime I create the class and run the method to instantiate it, it doesn't appear. However, I have noticed that if I was to create the exact same class and run the same method in the main then the frame appears.
This is most of the code from the class with the JFrame that I am trying to create:
JFrame myFrame= new JFrame();
public void CreateFrame()
{
JLabel background=new JLabel(new ImageIcon("image.jpg"));
myFrame.add(background);
background.setLayout(new FlowLayout());
myFrame.setLayout(new GridLayout(1,1));
myFrame.setSize(360,250);
myFrame.setUndecorated(true);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
myFrame.setLocation((dim.width/2-170), dim.height/2-125);
myFrame.pack();
myFrame.setVisible(true);
}
If I run the code
MyClass mc = new MyClass();
mc.CreateFrame();
in a method in another class it doesn't come up. However, if I run the exact same code in a main method, it works.
For example, this doesn't work:
Example 1
public class otherClass extends JFrame
{
public void MethodA()
{
MyClass mc = new MyClass();
mc.CreateFrame();
}
public static void main(String[] args)
{
otherClass oc = new otherClass();
oc.MethodA();
}
}
but this does work
Example 2
public class otherClass extends JFrame
{
public void MethodA()
{
//CODE
}
public static void main(String[] args)
{
otherClass oc = new otherClass();
oc.MethodA();
MyClass mc = new MyClass();
mc.CreateFrame();
}
}
Can anyone see where I'm going wrong? Sorry if a stupid mistake, I'm still getting to grips with Java.
Thanks
EDIT
import javax.swing.ImageIcon;
import javax.swing.JWindow;
import javax.swing.JLabel;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.imageio.ImageIO;
import java.util.Timer;
import java.util.Date;
import javax.swing.JFrame;
public class MyClass
{
JFrame homeFrame = new JFrame();
public void createFrame()
{
JLabel background=new JLabel(new ImageIcon("images.jpg"));
myFrame.add(background);
background.setLayout(new FlowLayout());
myFrame.setLayout(new GridLayout(1,1));
myFrame.setSize(360,250);
myFrame.setUndecorated(true);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
myFrame.setLocation((dim.width/2-170), dim.height/2-125);
myFrame.setAlwaysOnTop(true);
myFrame.pack();
myFrame.setVisible(true);
durationOfTime();
}
public void durationOfTime()
{
MainProgram mp = new MainProgram();
long startTime = System.currentTimeMillis();
long elapsedTime = 0L;
int count =0;
while (elapsedTime < 2*1000)
{
if(count==0)
{
mp.launchInitiation();
}
count+=1;
elapsedTime = (new Date()).getTime() - startTime;
}
myFrame.setVisible(false);
mp.homeFrame.setVisible(true);
}
public static void main(String[] args)
{
MyClass mc = new MyClass();
mc.createFrame();
}
}
Full code from class with JFrame trying to make. I am trying to use this JFrame as a splash screen but whatever class I call
MyClass mc = new MyClass();
mc.createFrame();
from, it just doesn't appear. Two seconds do pass by before my main GUI appears up but this method is supposed to be called in a login type frame. However, I have tested it with a blank JFrame / GUI to appear upon button click also and it still doesn't appear.
EDIT2
I also previously tried this SplashScreen example by # http://examples.oreilly.com/jswing2/code/ch08/SplashScreen.java but I couldn't get it to work (same problem, appears when called from main but not when called from action listener)
import java.awt.*;
import javax.swing.*;
public class SplashScreen extends JWindow {
private int duration;
public SplashScreen(int d) {
duration = d;
}
// A simple little method to show a title screen in the center
// of the screen for the amount of time given in the constructor
public void showSplash() {
JPanel content = (JPanel)getContentPane();
content.setBackground(Color.white);
// Set the window's bounds, centering the window
int width = 450;
int height =115;
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
int x = (screen.width-width)/2;
int y = (screen.height-height)/2;
setBounds(x,y,width,height);
// Build the splash screen
JLabel label = new JLabel(new ImageIcon("oreilly.gif"));
JLabel copyrt = new JLabel
("Copyright 2002, O'Reilly & Associates", JLabel.CENTER);
copyrt.setFont(new Font("Sans-Serif", Font.BOLD, 12));
content.add(label, BorderLayout.CENTER);
content.add(copyrt, BorderLayout.SOUTH);
Color oraRed = new Color(156, 20, 20, 255);
content.setBorder(BorderFactory.createLineBorder(oraRed, 10));
// Display it
setVisible(true);
// Wait a little while, maybe while loading resources
ClassToLoad ctl = new ClassToLoad();
try {
Thread.sleep(duration);
ctl.initiate();
} catch (Exception e) {}
setVisible(false);
}
public void showSplashAndExit() {
showSplash();
System.exit(0);
}
public static void main(String[] args) {
// Throw a nice little title page up on the screen first
SplashScreen splash = new SplashScreen(10000);
// Normally, we'd call splash.showSplash() and get on with the program.
// But, since this is only a test...
splash.showSplashAndExit();
}
}
I added the code in the lines with ClassToLoad and this SplashScreen is called on an action listener, what happens is the program waits the 2 seconds that I tell it to, no frame appears, and then the main class that I wanted to load while the splash screen is visible loads. I tried this method first but this didn't work which lead to me using the code listed above this edit
EDIT 3
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestFrame extends JFrame implements ActionListener
{
JPanel thePanel = new JPanel(null); //layout
JButton button = new JButton();
public void startGUI()
{
this.setLayout(new GridLayout(1,1));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CREATEMYPANEL();
this.add(thePanel);
this.setTitle("NO_TITLE_SET");
this.setSize(400,400);
this.setVisible(true);
this.setResizable(true);
}
public void CREATEMYPANEL()
{
button.setLocation(242,151);
button.setSize(100,50);
button.addActionListener(this);
button.setText("button");
thePanel.add(button);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==button)
{
System.out.println("button has been pressed ");
SplashScreen splash = new SplashScreen(1000);
splash.showSplash();
}
}
public static void main(String[] args )
{
TestFrame tf = new TestFrame();
tf.startGUI();
}
}
An example of where I call splash screen from. Still doesn't work. Also, just a note that the image I am loading is a local image
Apologies for bad question formatting
Your code works for me except for some details I noticed:
You're calling setSize(...) and then calling pack(). Probably your image isn't being loaded and thus your JFrame has a size of 0, 0. (And thus it looks like it never appears). .pack() and .setSize(...) are mutually exclusive.
You're setting the JLabel's layout manager to FlowLayout but never adding anything to it. (You can safely remove it)
I see you're importing java.util.Timer if you want to dispose the JFrame after 2 seconds, then you should be using a javax.swing.Timer instead. Otherwise you could get problems related to threading.
Also don't forget to place your program on the Event Dispatch Thread (EDT) as Swing is not thread safe
Following above recommendations you can have this code:
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class SplashscreenSample {
private JFrame myFrame;
private JLabel background;
private Timer timer;
public void createFrame() {
timer = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myFrame.dispose();
#SuppressWarnings("serial")
JFrame frame = new JFrame(getClass().getSimpleName()) {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
};
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
timer.stop();
}
});
myFrame = new JFrame(getClass().getSimpleName());
try {
background = new JLabel(new ImageIcon(new URL("http://cdn.bulbagarden.net/upload/thumb/6/6b/175Togepi.png/250px-175Togepi.png")));
} catch (MalformedURLException e) {
e.printStackTrace();
}
myFrame.add(background);
timer.setInitialDelay(2000);
timer.start();
myFrame.setLayout(new GridLayout(1, 1));
myFrame.setUndecorated(true);
myFrame.setAlwaysOnTop(true);
myFrame.pack();
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
myFrame.setLocation((dim.width/2-170), dim.height/2-125);
myFrame.setVisible(true);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new SplashscreenSample().createFrame());
}
}
Or you can use the Splashscreen class...
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;
public class SplashScreen extends JWindow {
private int duration;
public SplashScreen(int d) {
duration = d;
}
// A simple little method to show a title screen in the center
// of the screen for the amount of time given in the constructor
public void showSplash() {
ImageIcon icon = null;
try {
icon = new ImageIcon(new URL("http://www.cqsisu.com/data/wallpapers/5/718448.gif"));
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
JPanel content = (JPanel) getContentPane();
content.setBackground(Color.white);
// Set the window's bounds, centering the window
int width = icon.getIconWidth();
int height = icon.getIconHeight();
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
int x = (screen.width - width) / 2;
int y = (screen.height - height) / 2;
setBounds(x, y, width, height);
// Build the splash screen
JLabel label = new JLabel(icon);
JLabel copyrt = new JLabel("Copyright 2002, O'Reilly & Associates", JLabel.CENTER);
copyrt.setFont(new Font("Sans-Serif", Font.BOLD, 12));
content.add(label, BorderLayout.CENTER);
content.add(copyrt, BorderLayout.SOUTH);
Color oraRed = new Color(156, 20, 20, 255);
content.setBorder(BorderFactory.createLineBorder(oraRed, 10));
// Display it
setVisible(true);
// Wait a little while, maybe while loading resources
loadResources();
setVisible(false);
}
public void loadResources() {
TestFrame tf = new TestFrame();
try {
Thread.sleep(duration);
tf.startGUI();
} catch (Exception e) {
}
}
public static void main(String[] args) {
SplashScreen splash = new SplashScreen(10000);
splash.showSplash();
}
}
Try creating and setting the frame visible in a constructor of the class.
Could it be that while your program is counting
while (elapsedTime < 2*1000)
{
if(count==0)
{
mp.launchInitiation();
}
count+=1;
elapsedTime = (new Date()).getTime() - startTime;
}
it is blocking for said 2 seconds and waiting for this method to finish, return back to the create method and then just finish that one?
it seems this could be a better comment, but i need 50 rep for some reason to comment.
I need a one-time pause in this program for what I'm trying to do. I display some text in a Java Swing JFrame, repaint shows it, I wait 1.5 sec, then I change the text.
Basically, I started with this:
statusLabel.setText(s);
appFrame.repaint();
Thread.sleep(1500);
statusLabel.setText(y);
appFrame.repaint();
But this wasn't working. Thread.sleep() would invoke before repaint had finished, meaning s would never be shown. I read a lot of places that you're not supposed to use Thread.sleep() in swing applications because it pauses all threads, even the threads trying to repaint, and that to pause something triggered by actionPerformed() you need to use a Java Swing Timer.
Which is all well and fine, except I can't find a single place that offers a decent explanation on how they work. Since, as far as I can tell, timers are specifically used for repeating events on a timer. I just want a 1.5 second delay between 2 repaints.
I tried doing this...
statusLabel.setText(s);
appFrame.repaint();
Timer timer = new Timer(1500, new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
}
});
timer.setInitialDelay(1500);
timer.setRepeats(false);
timer.start();
statusLabel.setText(y);
appFrame.repaint();
...adding a timer with a 1.5 sec initial delay, no repeating, and no body to its actionPerformed event, so that it literally does nothing but wait that 1.5 sec, but it didn't work.
As coded in your example, it looks like the timer would "work", it just doesn't do anything because the actionPerformed method is empty. You might be thinking that timer.start() blocks and waits for the timer to trigger, but it fact it returns immediately. The way timers work is that the timer's actionPerformed method will be invoked from the UI thread when it is supposed to be. Placing code inside the actionPerformed method of a timer is a good way to update the UI state periodically.
Have you tried placing statusLabel.setText(y); inside the actionPerformed method of your ActionListener?
statusLabel.setText(s);
Timer timer = new Timer(1500, new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
statusLabel.setText(y);
}
});
timer.setRepeats(false);
timer.start();
If that's still not working, then consider providing a runnable example which demonstrates your problem. This will result in less confusion and better responses
Updated
What you "seem" to be wanting to do, is set up a series of events which get trigger at different times...Rather then using separate Timers, you should be using a single Timer like a loop, each time it ticks, you check it's state and make some decisions about what should be done, for example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Flashy {
public static void main(String[] args) {
new Flashy();
}
public Flashy() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
private JLabel flash;
private JButton makeFlash;
protected static final Color[] FLASH_COLORS = new Color[]{Color.BLUE, Color.RED, Color.GREEN, Color.YELLOW};
protected static final int[] FLASH_DELAY = new int[]{1000, 2000, 3000, 4000};
private int flashPoint;
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
flash = new JLabel("Flash");
flash.setOpaque(true);
makeFlash = new JButton("Make Flash");
add(flash, gbc);
add(makeFlash, gbc);
makeFlash.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
flashPoint = -1;
Timer timer = new Timer(0, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Timer timer = ((Timer)e.getSource());
flashPoint++;
if (flashPoint < FLASH_COLORS.length) {
flash.setBackground(FLASH_COLORS[flashPoint]);
System.out.println(FLASH_DELAY[flashPoint]);
timer.setDelay(FLASH_DELAY[flashPoint]);
} else {
flash.setBackground(null);
timer.stop();
makeFlash.setEnabled(true);
}
}
});
timer.setInitialDelay(0);
timer.start();
makeFlash.setEnabled(false);
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Now, if you wanted to do something really fancy, you could devise a series of key frames over a given period of time.
This means that you could change the duration of the animation, without needing to change any other piece of code, for example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Flashy {
public static void main(String[] args) {
new Flashy();
}
public Flashy() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
private JLabel flash;
private JButton makeFlash;
protected static final Color[] FLASH_COLORS = new Color[]{Color.BLUE, Color.RED, Color.GREEN, Color.YELLOW};
protected static final double[] FLASH_DELAY = new double[]{0, 0.2, 0.4, 0.6};
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
flash = new JLabel("Flash");
flash.setOpaque(true);
makeFlash = new JButton("Make Flash");
add(flash, gbc);
add(makeFlash, gbc);
makeFlash.addActionListener(new ActionListener() {
private int playTime = 10000;
private long startTime;
private int currentFrame = -1;
#Override
public void actionPerformed(ActionEvent e) {
startTime = System.currentTimeMillis();
Timer timer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Timer timer = ((Timer) e.getSource());
long now = System.currentTimeMillis();
long duration = now - startTime;
double progress = (double) duration / (double) playTime;
int keyFrame = 0;
for (keyFrame = 0; keyFrame < FLASH_DELAY.length; keyFrame++) {
double current = FLASH_DELAY[keyFrame];
double next = 1d;
if (keyFrame + 1 < FLASH_DELAY.length) {
next = FLASH_DELAY[keyFrame + 1];
}
if (progress >= current && progress < next) {
break;
}
}
if (keyFrame < FLASH_COLORS.length) {
flash.setBackground(FLASH_COLORS[keyFrame]);
}
if (duration >= playTime) {
timer.stop();
makeFlash.setEnabled(true);
flash.setBackground(null);
}
}
});
timer.setInitialDelay(0);
timer.start();
makeFlash.setEnabled(false);
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
A much more advanced concept, which is demonstrated in this answer
In an attempt to make a very simple bullet-hell game to learn about java, I ran into a roadblock: repaint() wasn't calling paintComponent().
Here is the entire program, which for now simply draws an image I created 50 times per second onto a JPanel, which rests on a JFrame.
/*
* Bullet hell, by Nematodes
*/
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class bulletHell extends JFrame
{
private static final long serialVersionUID = 0L;
JPanel gamePanel = new JPanel();
int gameTimerDelay = 20;
int x, y = 0;
BufferedImage lightOrb;
javax.swing.Timer gameTimer;
public static void main(String[] args)
{
bulletHell createFrame = new bulletHell();
createFrame.frameConstructor();
}
public void frameConstructor()
{
// Construct frame and frame components
setTitle("Bullet hell");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
getContentPane().setLayout(new GridBagLayout());
setVisible(true);
GridBagConstraints gridConstraints;
gridConstraints = new GridBagConstraints();
gridConstraints.gridx = 0;
gridConstraints.gridy = 0;
gamePanel.setBackground(Color.BLACK);
gamePanel.setPreferredSize(new Dimension(700, 700));
getContentPane().add(gamePanel, gridConstraints);
pack();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds((int) (0.5 * (screenSize.width - getWidth())),
(int) (0.5 * (screenSize.height - getHeight())), getWidth(), getHeight());
try
{
lightOrb = ImageIO.read(new File("C:/Users/Owner/Downloads/orb.bmp"));
}
catch(IOException e)
{
System.out.println("An issue occurred while trying to read orb.bmp");
}
// Start timer that draws game objects 50 times per second (50 FPS)
gameTimer = new javax.swing.Timer(gameTimerDelay, gameTimerAction);
gameTimer.setInitialDelay(0);
gameTimer.start();
}
ActionListener gameTimerAction = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
repaint();
}
};
class GraphicsPanel extends JPanel
{
public GraphicsPanel()
{
}
// Draw all of the components
#Override
public void paintComponent(Graphics g)
{
Graphics2D g2D = (Graphics2D) g;
super.paintComponent(g2D);
g2D.drawImage(lightOrb, x, y, this);
g2D.dispose();
}
}
}
After some debugging with breakpoints and println methods, I can confirm that the correct image is being read, the timer in gameTimerAction is being called 50 times per second, and repaint() is not invoking paintComponent() at all.
I am somewhat new to Java programming, and might just be missing something simple.
Edit: Problem has been solved by changing gamePanel to a GraphicsPanel object. Unfortunately, this also means that my much larger pong project (which this project's flawed drawing logic was essentially copied from) only worked by a miracle, and might be unstable with certain code additions.
I can immediately see several problems:
Most Important: You never instantiate a GraphicsPanel object, nor do you add it to anything. The paintComponent(...) method will never be called on a JPanel that is neither rendered nor created. Why not make your gamePanel variable a GraphicsPanel object and not a JPanel object?
You never change x and y in your Timer, and so without change, no animation will occur.
Also you're calling dispose on a Graphics object given to you by the JVM, something you should never do. This breaks the Swing painting chain making the graphics of your GUI unstable.
So keep at it, you'll get there.
For example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class BulletExample extends JPanel {
public static final String IMG_PATH = "http://www.i2clipart.com/cliparts/f/0/5/8/clipart-blue-circle-f058.png";
private static final int PREF_W = 700;
private static final int PREF_H = PREF_W;
private static final int TIMER_DELAY = 20;
private BufferedImage bullet;
private int bulletX;
private int bulletY;
public BulletExample() throws IOException {
URL imgUrl = new URL(IMG_PATH);
bullet = ImageIO.read(imgUrl);
new Timer(TIMER_DELAY, new BulletListener()).start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bullet != null) {
g.drawImage(bullet, bulletX, bulletY, this);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class BulletListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
bulletX++;
bulletY++;
repaint();
}
}
private static void createAndShowGui() throws IOException {
// create the drawing JPanel
BulletExample mainPanel = new BulletExample();
JFrame frame = new JFrame("BulletExample");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// add it to the JFrame
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
createAndShowGui();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
This question already has answers here:
How to draw in JPanel? (Swing/graphics Java)
(4 answers)
Closed 9 years ago.
Hi im making a project for my studies and im new in java. I need to do a game - Arkanoid. What i wanted to do is a game manu with 2 buttons "New game" and "Quit". Someone from stackoverflow.com rebuild my menu code but it still doesnt work :( After clicking a "New Game" im getting blank frame :(. Probably becouse of Gra constructor. How constructor of Gra need to look like to make it works with my menu code.
Here is the code (i will paste all Arkanoid class code and most important parts of Gra class):
Arkanoid class:
package arkanoid;
import javax.swing.*;
import java.awt.event.*;
public class Arkanoid extends JFrame
{
private static final long serialVersionUID = 5647459635833443178L;
public Arkanoid() {
super("Arkanoid");
setSize(500,400);
setTitle("Arkanoid BETA");
setLocationRelativeTo(null);
setResizable(false);
final JPanel panel = new JPanel();
setContentPane(panel);
panel.add(new JButton(new AbstractAction("New game") {
public void actionPerformed (ActionEvent e) {
panel.removeAll();
panel.add(new Gra()); //constructor of Gra need to return some Panel i think but i dont know how to do that
panel.revalidate();
panel.repaint();
}
}));
panel.add(new JButton(new AbstractAction("Quit") {
public void actionPerformed (ActionEvent e) {
Arkanoid.this.setVisible(false);
}
}));
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Arkanoid frame = new Arkanoid();
frame.setVisible(true);
}
});
}
}
Gra class:
package arkanoid;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JOptionPane;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class Gra extends JPanel
{
/*some not important variables*/
Pilka pilka;
Paletka paletka;
Cegla cegla_tab[];
Serce serce_tab[];
Timer timer;
public Gra()
{
addKeyListener(new TAdapter());
setFocusable(true);
cegla_tab = new Cegla[liczba_cegiel];
serce_tab = new Serce[max_zycia];
//setDoubleBuffered(true);
timer = new Timer();
timer.scheduleAtFixedRate(new ScheduleTask(), 1000, 10);
}
public void addNotify()
{
super.addNotify();
start_gry();
}
public void start_gry()
{
pilka = new Pilka();
paletka = new Paletka();
/* painting a bricks and lifes for game start */
}
public void koniec_gry() //end of a game
{
czas_konca = System.currentTimeMillis();
gra = 3;
timer.cancel();
}
public void paint(Graphics g)
{
super.paint(g);
//repaiting ball positions, bricks and paddle
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
private class TAdapter extends KeyAdapter
{
public void keyReleased(KeyEvent e)
{
paletka.klawisz_puszczony(e);
}
public void keyPressed(KeyEvent e)
{
paletka.klawisz_wcisniety(e);
}
}
class ScheduleTask extends TimerTask
{
public void run()
{
if(paletka.czy_pausa()==false)
{
pilka.przesun();
paletka.przesun();
czy_zderzenie();
repaint();
}
}
}
public void czy_zderzenie()
{
//checking a collisions with bricks
}
}
You need to override paintComponent, not paint.
Also, Gra's constructor does return a JPanel. The constructor will return the object you're constructing, which in this case is a Gra, which is also a JPanel. This is polymorphism at work.
Oh, and as per the comment above, you really shouldn't be disposing of the graphics object.
I have written an application inside a JFrame window, and would like to have an error message pop up if that is needed. However, when I call "JOptionPane.showMessageDialog()", the application freezes and the only way to stop it is by using task manager.
Here is a trimmed down version of my code:
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.JFrame;
public class GameMain {
public JFrame jframe;
public Canvas canvas;
private AtomicReference<Dimension> canvasSize = new AtomicReference<Dimension>();
public void initialize(int width, int height) {
try {
Canvas canvas = new Canvas();
JFrame frame = new JFrame("testapp");
this.canvas = canvas;
this.jframe = frame;
ComponentAdapter adapter = new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
resize();
}
};
canvas.addComponentListener(adapter);
canvas.setIgnoreRepaint(true);
frame.setSize(640, 480);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(canvas);
frame.setVisible(true);
Dimension dim = this.canvas.getSize();
} catch (LWJGLException le) {
le.printStackTrace();
}
JOptionPane.showMessageDialog(null, "oops!");
}
public void resize()
{
Dimension dim = this.canvas.getSize();
canvasSize.set(dim);
dim = null;
}
}
Does anyone know why it might be doing that?
private void ShowMessage(String message) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JOptionPane.showMessageDialog(null, message);
}
});
}
Try to pass the frame instead of null there
JOptionPane.showMessageDialog(null, "oops!");
And don't mix awt and swing (JFrame and Canvas) together
That's because you have passed true to setAlwaysOnTop of the JFrame.Try passing false.
setAlwaysOnTop(false);