JFrame components being able to call paintComponent through repaint, although using flowlayout - java

I have a JFrame in FlowLayout with multiple JLabels added to it, but when I call repaint on the JLabels, their paintComponent is not being called. If I remove the FlowLayout, only the last JLabel added shows up and repaints properly. I tried to use a panel but it didn't work. I'm not sure I'm using it properly though.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class RacingLetters {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
final JFrame jframe = new JFrame();
jframe.setTitle("Racing letters");
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//jframe.setExtendedState(Frame.MAXIMIZED_BOTH);
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - jframe.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - jframe.getHeight()) / 2);
jframe.setLocation(x, y);
jframe.setMinimumSize(new Dimension(500, 200));
FlowLayout fl = new FlowLayout();
jframe.setLayout(fl);
//jframe.setLayout(null);
jframe.setVisible(true);
StringBuffer[] stringBufferArray = new StringBuffer[20];
char ch = 'A';
int yy = 20;
for (int i = 0; i < 5; i++) {
stringBufferArray[i] = new StringBuffer("");
BufferThread bt = new BufferThread(stringBufferArray[i], ch, 10, yy);
//pane.add(bt);
jframe.add(bt);
new Thread(bt).start();
ch++;
yy += 20;
}
}
});
}
}
..
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JLabel;
public class BufferThread extends JLabel implements Runnable {
char ch;
StringBuffer sb;
int x,y;
BufferThread(StringBuffer sb, char ch,int x, int y) {
this.sb = sb;
this.ch = ch;
this.x = x;
this.y = y;
}
#Override
public void run() {
Random rand = new Random();
for (int i = 0; i < 5; i++) {
sb.append(ch);
System.out.println(x + " " + y + " " + ch);
repaint();
try {
Thread.sleep(rand.nextInt(500));
} catch (InterruptedException ex) {
Logger.getLogger(BufferThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void paintComponent(Graphics g) {
//System.out.println(x + " " + y + " " + ch);
//System.out.println("aaaa");
//stem.out.println(sb);
Graphics2D g2 = (Graphics2D) g;
Font f = new Font("Serif", Font.PLAIN, 24);
//if (sb.toString().indexOf("E") < 0)
g2.drawString(sb.toString(), x, y);
}
}

The core problem is that the JLabel isn't providing any information back to the frame's layout manager about how big it would like to be. Nor is it actually telling the frame's layout manager that it's updated and needs to be resized.
Why you're trying to paint text on a label is beyond me, seen as that's what a label does by design.
You should avoid using Thread when dealing with Swing components and should use javax.swing.Timer and SwingWorker where possible.
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Ticker {
public static void main(String[] args) {
new Ticker();
}
public Ticker() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
frame.add(new TickerLabel());
frame.setSize(100, 100);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TickerLabel extends JLabel {
private int counter;
public TickerLabel() {
Timer timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (counter > 4) {
((Timer)e.getSource()).stop();
} else {
String text = getText();
text += (char)(((int)'A') + counter);
setText(text);
}
counter++;
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
}
}

Related

Java apps (based on JSwing) performance consuming?

I'm new to Java Programming. Recently I'm developing a mini game with JSWing. However, after coding for awhile the in-game FPS dropped terribly. When I tracked it on Task Manager I had result like this:
Can someone tell me what's wrong? I only used loops, JLabel with icons, Paint Graphics methods, mouseMotionEvent in my code.
Here is the code in the main game
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Game extends JPanel {
int numb = 2;
int pts = 5;
Kitty[] Kitties = new Kitty[4];
public Game() {
for (int i = 0; i < Kitties.length; i++)
Kitties[i] = new Kitty();
}
#Override
public void paint(Graphics graphics) {
BufferedImage img = null;
try {
img = ImageIO.read(getClass().getResourceAsStream("city.jpg"));
} catch (IOException e) {
System.out.println("java io");
}
graphics.drawImage(img, 0, 0, null);
//paints square objects to the screen
for (int i = 0; i < numb;i++) {
Kitties[i].paint(graphics);
}
}
public void update(TheJPanel frame) {
if (frame.a >= 0 && frame.a < 500) numb = 2;
if (frame.a>= 500) numb = 3;
for (int i = 0; i< numb; i++) {
int disty = 500 - Kitties[i].squareYLocation;
int distx = Kitties[i].squareXLocation - frame.x;
if ( Kitties[i].squareYLocation < 600 && disty <= 5 && disty >= -80 && distx < 260 && distx > -100){
frame.a +=pts;
if (Kitties[i].kittype == 6) frame.a += pts;
if (frame.a >= 500) {
Kitties[i].fallSpeed = Kitties[i].FallSpeedlvl2();
pts = 10;
}
Kitties[i].squareYLocation = -200;
Kitties[i].generateKittype();
Kitties[i].generateRandomXLocation();
Kitties[i].generateRandomFallSpeed();
frame.point.setText("Point:" + String.valueOf(frame.a));
frame.lives.setText("Lives:" + String.valueOf(frame.count));
}
if(Kitties[i].squareYLocation > 610){
frame.count--;
Kitties[i].generateKittype();
Kitties[i].generateRandomXLocation();
Kitties[i].generateRandomFallSpeed();
Kitties[i].squareYLocation = -200;
}
if (Kitties[i].squareYLocation >=605) frame.catFall(Kitties[i].squareXLocation);
if(Kitties[i].squareYLocation <= 610){
Kitties[i].squareYLocation += Kitties[i].fallSpeed;
}
}
}
public static void main(String[] args) throws InterruptedException {
Game game = new Game();
TheJPanel frame = new TheJPanel();
frame.add(game);
frame.setVisible(true);
frame.setSize(1000, 1000);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setTitle("Saving kitties");
frame.setResizable(false);
frame.setLocationRelativeTo(null);
while (frame.count>0) {
game.update(frame);
game.repaint();
Thread.sleep(4);
}
if (frame.count == 0) {
JOptionPane.showMessageDialog(null, "You lost!", "Game over!", JOptionPane.ERROR_MESSAGE);
game.setVisible(false);
frame.getContentPane().removeAll();
frame.getContentPane().repaint();
frame.bask.setVisible(false);
frame.background.setVisible(false);
}
}
}
Here is the code for the main Jframe
package game;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
/**
*
* #author Imba Store
*/
public class TheJPanel extends JFrame implements MouseMotionListener {
protected int x;
protected int a = 0;
protected int count = 20;
protected JLabel bask = new JLabel();
protected JLabel background = new JLabel();
protected JLabel point = new JLabel();
protected JLabel lives = new JLabel();
Timer fall;
protected int time =0;
public TheJPanel() {
this.addMouseMotionListener(this);
InitContent();
}
protected void InitContent() {
Icon img = new ImageIcon(getClass().getResource("basket.png"));
bask.setIcon(img);
Icon themes = new ImageIcon(getClass().getResource("city2.png"));
background.setIcon(themes);
background.setBounds(0, 699, 1000, 300);
point.setFont(new java.awt.Font("Trebuchet MS", 1, 35));
point.setText("Point:" + String.valueOf(a));
point.setBounds(20,908,240,50);
point.setForeground(Color.white);
lives.setBounds(800, 908,200,50);
lives.setFont(new java.awt.Font("Trebuchet MS", 1, 35));
lives.setForeground(Color.white);
lives.setText("Point:" + String.valueOf(count));
point.setOpaque(false);
add(point);
add(lives);
add(bask);
add(background);
bask.setSize(400,148);
}
#Override
public void mouseMoved (MouseEvent me)
{
x = me.getX();
background.setBounds(0, 699, 1000, 300);
bask.setBounds(x, 700, 400, 148);
}
#Override
public void mouseDragged (MouseEvent me)
{
}
public void catFall(int getX){
Icon fell = new ImageIcon(getClass().getResource("kitty-fall.png"));
JLabel fellcat = new JLabel();
fellcat.setIcon(fell);
fellcat.setBounds(getX, 760, 220, 220);
add(fellcat);
add(background);
fall = new Timer(1500, new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae) {
getContentPane().remove(fellcat);
}
});
fall.setRepeats(false);
fall.start();
}
}
And this is the class for the falling cats
package game;
/**
*
* #author Imba Store
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
public final class Kitty extends JLabel {
protected int squareXLocation;
protected int squareYLocation = -200;
protected int fallSpeed = 1;
protected int kittype;
Random rand = new Random();
public int generateRandomXLocation(){
return squareXLocation = rand.nextInt(800);
}
public int generateRandomFallSpeed(){
return fallSpeed = rand.ints(3, 4).findFirst().getAsInt();
}
public int FallSpeedlvl2() {
return fallSpeed = rand.ints(3,7).findFirst().getAsInt();
}
public int generateKittype() {
return kittype = rand.ints(1,8).findFirst().getAsInt();
}
#Override
public void paint(Graphics g) {
BufferedImage img = null;
BufferedImage thugcat = null;
try {
img = ImageIO.read(getClass().getResourceAsStream("kitty.png"));
thugcat = ImageIO.read(getClass().getResourceAsStream("thug-kitty.png"));
} catch (IOException e) {
System.out.println("Java IO");
}
if (kittype == 6) {
g.drawImage(thugcat, squareXLocation, squareYLocation, null);
}
else g.drawImage(img, squareXLocation,squareYLocation,null);
}
public Kitty(){
generateRandomXLocation();
generateRandomFallSpeed();
generateKittype();
}
public void paint(Graphics graphics) {
BufferedImage img = null;
try {
img = ImageIO.read(getClass().getResourceAsStream("city.jpg"));
Custom painting is done by overriding paintComponent(...) not paint(). The first statement should then be super.paintComponent().
A painting method is for painting only. Don't do I/O in the painting method. This will cause the image to be read every time you repaint the panel.
Thread.sleep(4);
Sleeping for 4ms is not enough. That will attempt to repaint 250 times a second which is too often. There is no need for the frame rate to be that fast.
Kitty[] Kitties = new Kitty[4];
Variable names should not start with an upper case character. Most of your names are correct. Be consistent!
point.setBounds(20,908,240,50);
Don't use setBounds(). Swing was designed to be used with layout managers. Set a layout manager for you background and then add the components.
public int FallSpeedlvl2() {
Methods should NOT start with an upper case character. Again, most are correct. Be Consistent!!!

Java catch the ball Game

I am having trouble with my Java project for school.
The plan was to make a simple game where you need to catch the ball and if you catch the ball you will get points.
At the moment I have 2 problems:
I have no idea how I make the balls appear at a random width and make it stay at that width (cause random value is constantly changing ).
How can I make a statement that checks if the catcher caught the ball?
This is my current code:
import instruct.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import javax.swing.Timer;
public class opdracht extends WindowPanel implements MouseMotionListener {
List<comet> comets;
Image afb1;
Image afb2;
Image comet;
int xmuis;
int score;
int random;
int h;
int plaats;
static int randomNum;
private static final int D_W = 700;
private static final int X_INC = 10;
public opdracht() throws IOException {
score = 0;
h = -100;
afb1 = ImageIO.read(new File("afb/space.jpg"));
afb2 = ImageIO.read(new File("afb/pipe.png"));
BufferedImage cometbuf = ImageIO.read(new File("afb/comet.png"));
File output = new File("comet.png");
ImageIO.write(cometbuf, "png", output);
comet = ImageIO.read(new File("comet.png"));
addMouseMotionListener(this);
try {
drawcomet();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
plaats = randomNum;
comets = new LinkedList<>();
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Iterator<comet> it = comets.iterator();
while (it.hasNext()) {
comet ball = it.next();
if (ball.h > D_W) {
it.remove();
System.out.println(comets.size());
} else {
ball.h += X_INC;
repaint();
}
}
}
});
timer.start();
}
public void paintComponent(Graphics g) {
g.drawImage(afb1, 0, 0, 1200, 800, this);
g.setColor(Color.yellow);
g.setFont(new Font("TimesRoman", Font.PLAIN, 30));
g.drawString("score = " + score, 1020, 30);
for (comet ball : comets) {
ball.drawcomet(g);
}
g.drawImage(afb2, xmuis, 730, 70, 75, this);
}
public static void randInt(int min, int max) {
// NOTE: Usually this should be a field rather than a method
// variable so that it is not re-seeded every call.
Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
randomNum = rand.nextInt((max - min) + 1) + min;
System.out.print(randomNum);
}
public void drawcomet() throws InterruptedException {
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
comets.add(new comet(comet));
}
}, 0, 2, TimeUnit.SECONDS);
}
public class comet {
protected int h;
Image comet;
public comet(Image image) {
comet = image;
}
public void drawcomet(Graphics g) {
g.drawImage(comet, plaats, h, 75, 50, null);
}
}
public void mouseMoved(MouseEvent e) {
xmuis = e.getX();
repaint();
}
public void mouseDragged(MouseEvent e) {
// do something
}
public static void main(String[] a) throws IOException {
new opdracht().createGUI();
}
}
package instruct;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class WindowPanel extends JPanel {
JFrame frame;
public WindowPanel() {
this.setPreferredSize(new Dimension(1200, 800));
this.setFocusable(true);
this.requestFocusInWindow();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// System.out.println( "class: "+ getClass().getName() );
frame.setTitle("Space Game");
}
protected void createAndShowGUI() {
frame = new JFrame();
frame.setSize(1200, 800);
frame.setLocation(300, 100);
frame.setResizable(false);
frame.add(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
// Create a new blank cursor.
Cursor blankCursor =
Toolkit.getDefaultToolkit().createCustomCursor(cursorImg, new Point(0, 0),
"blank cursor");
// Set the blank cursor to the JFrame.
frame.getContentPane().setCursor(blankCursor);
}
public void createGUI() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public JFrame getFrame() {
return frame;
}
}
First question: "I have no idea how i make the ball's appear at a random width."
I assume you want to give the ball (= an instance of the comet class) a random x position (= the plaats field)? You could make the following changes (which make the randomNum field no longer required, this could now be a local variable):
//plaats = randomNum;
plaats = randInt(0, 1200);
// more code...
//public static void randInt(int min, int max) {
public static int randInt(int min, int max) {
// more code...
return randomNum;
}
Second question: "And how can make a statement that checks if catcher cached ball."
To determine whether the ball is catched, you could compare xmuis to plaats when the y coordinate of the ball (the h field?) is equal to the top of the pipe (around 730).

Java graphic not painting properly

I've written the following code
import java.awt.BorderLayout;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
final public class Test
{
JFrame frame;
DrawPanel drawPanel;
boolean up = false;
boolean down = true;
boolean left = false;
boolean right = true;
private int timeStep = 0;
private int ballYTravel = 100;
private int BALL_NUM = 24;
public static void main(String... args)
{
new Test().go();
}
private void go()
{
frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawPanel = new DrawPanel();
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.setResizable(false);
frame.setSize(800, 600);
frame.setLocationByPlatform(true);
frame.setVisible(true);
moveIt();
}
class DrawPanel extends JPanel
{
private static final long serialVersionUID = 1L;
public double getY(int i, int t) {
return 200 + ballYTravel / 2 * (Math.sin(timeStep * (i / 200 + 0.08)));
}
public void paintComponent(Graphics g)
{
for (int k = 0; k < BALL_NUM; k++ ) {
g.fillRect(100 + 20 *k , (int) getY(k, timeStep), 6, 6);
}
timeStep++;
}
}
private void moveIt()
{
while (true)
{
try
{
Thread.sleep(10);
}
catch (Exception e)
{
e.printStackTrace();
}
frame.repaint();
}
}
}
It runs and animates, however it is not animating in the same fashion as the Javascript code I referenced it from which can be found here http://codepen.io/anon/pen/ZYQoQZ
any help in understanding why is appreciated
There are (possibly) two basic problems...
In getY, you are ignoring the parameter t and using timeStep instead, while, technically, this probably isn't going to make a MASSIVE difference, it is an area of concern
You have an integer division issue. i/200 will result in int result, where you really want a double. Change it to i/200d
For example...
import java.awt.Dimension;
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;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
final public class Test {
private int timeStep = 0;
private final int ballYTravel = 100;
private final int BALL_NUM = 24;
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();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DrawPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
class DrawPanel extends JPanel {
private static final long serialVersionUID = 1L;
public DrawPanel() {
new Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timeStep++;
repaint();
}
}).start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 200);
}
public double getY(int i, int t) {
return 100 + ballYTravel / 2 * (Math.sin(t * (i / 200d + 0.08)));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int k = 0; k < BALL_NUM; k++) {
g.fillRect(10 + 20 * k, (int) getY(k, timeStep), 6, 6);
}
}
}
}
You're also breaking the paint chain, which is going to cause you issues in the long run, make sure you are calling super.paintComponent...
For more details see...
Performing Custom Painting
Painting in AWT and Swing
Concurrency in Swing
How to use Swing Timers
Initial Threads
Your transliteration reveals several problems:
Swing GUI objects should be constructed and manipulated only on the event dispatch thread.
Don't use setSize() when you really mean to override getPreferredSize().
Invoke pack() to let the container adopt its preferred size.
Use javax.swing.Timer to pace the animation.
Revised code, incorporating #Mad's fix and using drawOval():
import java.awt.BorderLayout;
import java.awt.Dimension;
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;
final public class Test {
JFrame frame;
DrawPanel drawPanel;
private int timeStep = 0;
private int ballYTravel = 100;
private int BALL_NUM = 24;
public static void main(String... args) {
new Test().go();
}
private void go() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawPanel = new DrawPanel();
frame.add(BorderLayout.CENTER, drawPanel);
frame.setResizable(false);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
Timer t = new Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
drawPanel.repaint();
}
});
t.start();
}
});
}
private class DrawPanel extends JPanel {
public double getY(int i, int t) {
return 200 + ballYTravel / 2 * (Math.sin(t * (i / 200d + 0.08)));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int k = 0; k < BALL_NUM; k++) {
g.drawOval(100 + 20 * k, (int) getY(k, timeStep), 8, 8);
}
timeStep++;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(700, 500);
}
}
}

Swing form gets freezed

According to http://docs.oracle.com/javase/7/docs/technotes/guides/2d/flags.html#opengl
I set the system property as following in order to JVM uses the gpu opengl hw acceleration if available.
there is no crash, and the verbose message says the pipeline is activated OpenGL pipeline enabled for default config on screen 0.
public static void main(String args[]) {
System.setProperty("sun.java2d.opengl", "True");
try {
UIManager.setLookAndFeel(new WindowsClassicLookAndFeel());
} catch (Exception ex) {}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new RootForm().setVisible(true);
}
});
//no difference
// java.awt.EventQueue.invokeLater(new Runnable() {
// public void run() {
// new RootForm().setVisible(true);
// }
// });
//no difference
// new Thread(new Runnable() {
// #Override
// public void run() {
// new RootForm().setVisible(true);
// }
// }).start();
}
but the swing form gets freezed! even repaint() call doesn't work.
What is the problem would be?
Platform: Win7X64, GPU: AMD HD5870 (updated driver).
Thanks in advance.
EDIT
I tried it several times and I got it work. and no the new problem. it works randomly. very weird. works whenever it wants.
Works fine for me...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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 TestOpenGL {
public static void main(String args[]) {
System.setProperty("sun.java2d.opengl", "True");
new TestOpenGL();
}
public TestOpenGL() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int yPos = 0;
private int yDelta = 2;
private JLabel label;
public TestPane() {
setLayout(new GridBagLayout());
label = new JLabel("Bouncy, Bouncy...");
add(label);
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
yPos += yDelta;
if (yPos > getHeight()) {
yPos = getHeight();
yDelta *= -1;
} else if (yPos < 0) {
yPos = 0;
yDelta *= -1;
}
label.setText("Bouncy, Bouncy...# " + yPos);
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.GREEN);
int x = (getWidth() - 2) / 2;
g2d.drawOval(x, yPos - 2, 4, 4);
g2d.dispose();
}
}
}

SwingWorker, Thread.sleep(), or javax.swing.timer? I need to "insert a pause"

I'm working on a memory game and I want to set it up so I click the first "card", then the second and if they are not the same the second card shows for a few seconds then they return to the "non-flipped" position.
I tried using SwingWorker, Thread.sleep and SwingTimer but I cant get it to work. With Thread.sleep the second card wont "flip" if it's a duplicate it waits the amount of sleep time and disappears. If its not a match it waits "face down" and after the sleep timer the first card does flip back. This happens regardless of where I place the Thread.sleep.
With Swing Timer it only appears to "change the timer" while I'm interacting with the cards so I end up flipping 8 cards before it activates.
I've had no luck with SwingWorker and I'm not even sure it will work for what I'm looking for.
This is the code I have:
class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
for(int index = 0; index < arraySize; index++)
{
if(button[index] == e.getSource())
{
button[index].setText(String.valueOf(cards.get(index)));
button[index].setEnabled(false);
number[counter]=cards.get(index);
if (counter == 0)
{
counter++;
}
else if (counter == 1)
{
if (number[0] == number[1])
{
for(int i = 0; i < arraySize; i++)
{
if(!button[i].isEnabled())
{
button[i].setVisible(false);
}
}
}
else
{
for(int i = 0; i < arraySize; i++)
{
if(!button[i].isEnabled())
{
button[i].setEnabled(true);
button[i].setText("Card");
}
}
}
counter = 0;
}
}
}
}
}
Basically what I need is for this code to execute when the counter == 1, and the card is not a match:
button[index].setText(String.valueOf(cards.get(index)));
button[index].setEnabled(false);
Then a pause so the card is revealed for that time, and finally it resumes to returning the card to its face down position.
This is what I tried with Thread.sleep():
class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
for(int index = 0; index < arraySize; index++)
{
if(button[index] == e.getSource())
{
button[index].setText(String.valueOf(cards.get(index)));
button[index].setEnabled(false);
number[counter]=cards.get(index);
if (counter == 0)
{
counter++;
}
else if (counter == 1)
{
if (number[0] == number[1])
{
for(int i = 0; i < arraySize; i++)
{
if(!button[i].isEnabled())
{
button[i].setVisible(false);
}
}
}
else
{
try
{
Thread.sleep(800);
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
for(int i = 0; i < arraySize; i++)
{
if(!button[i].isEnabled())
{
button[i].setEnabled(true);
button[i].setText("Card");
}
}
}
counter = 0;
}
}
}
}
}
Thanks in advance for any advice
Use javax.swing.Timer to schedule a future event to trigger. This will allow you to make changes to the UI safely, as the timer is triggered within the context of the Event Dispatching Thread.
The problem with been able to flip multiple cards simultaneously has more to do with you not setting up a state that prevents the user from flipping cards then the use of timers.
The following example basically only allows one card to be flipped per group at a time.
Once a card has been flipped in both groups, the timer is started. When it is triggered, the cards are reset.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.LinearGradientPaint;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class FlipCards {
public static void main(String[] args) {
new FlipCards();
}
public FlipCards() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Card extends JPanel {
private BufferedImage image;
private boolean flipped = false;
private Dimension prefSize;
public Card(BufferedImage image, Dimension prefSize) {
setBorder(new LineBorder(Color.DARK_GRAY));
this.image = image;
this.prefSize = prefSize;
}
#Override
public Dimension getPreferredSize() {
return prefSize;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
LinearGradientPaint lgp = new LinearGradientPaint(
new Point(0, 0),
new Point(0, getHeight()),
new float[]{0f, 1f},
new Color[]{Color.WHITE, Color.GRAY});
g2d.setPaint(lgp);
g2d.fill(new Rectangle(0, 0, getWidth(), getHeight()));
if (flipped && image != null) {
int x = (getWidth() - image.getWidth()) / 2;
int y = (getHeight() - image.getHeight()) / 2;
g2d.drawImage(image, x, y, this);
}
g2d.dispose();
}
public void setFlipped(boolean flipped) {
this.flipped = flipped;
repaint();
}
}
public class CardsPane extends JPanel {
private Card flippedCard = null;
public CardsPane(List<BufferedImage> images, Dimension prefSize) {
setLayout(new GridBagLayout());
MouseAdapter mouseHandler = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (flippedCard == null) {
Card card = (Card) e.getComponent();
card.setFlipped(true);
flippedCard = card;
firePropertyChange("flippedCard", null, card);
}
}
};
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(4, 4, 4, 4);
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 0.25f;
for (BufferedImage img : images) {
Card card = new Card(img, prefSize);
card.addMouseListener(mouseHandler);
add(card, gbc);
}
}
public Card getFlippedCard() {
return flippedCard;
}
public void reset() {
if (flippedCard != null) {
flippedCard.setFlipped(false);
flippedCard = null;
}
}
}
public class TestPane extends JPanel {
private CardsPane topCards;
private CardsPane bottomCards;
private Timer resetTimer;
public TestPane() {
resetTimer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
topCards.reset();
bottomCards.reset();
}
});
resetTimer.setRepeats(false);
resetTimer.setCoalesce(true);
PropertyChangeListener propertyChangeHandler = new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
Card top = topCards.getFlippedCard();
Card bottom = bottomCards.getFlippedCard();
if (top != null && bottom != null) {
resetTimer.start();
}
}
};
BufferedImage[] images = new BufferedImage[4];
try {
images[0] = ImageIO.read(new File("./Card01.png"));
images[1] = ImageIO.read(new File("./Card02.jpg"));
images[2] = ImageIO.read(new File("./Card03.jpg"));
images[3] = ImageIO.read(new File("./Card04.png"));
Dimension prefSize = getMaxBounds(images);
List<BufferedImage> topImages = new ArrayList<>(Arrays.asList(images));
Random rnd = new Random(System.currentTimeMillis());
int rotate = (int) Math.round((rnd.nextFloat() * 200) - 50);
Collections.rotate(topImages, rotate);
topCards = new CardsPane(topImages, prefSize);
topCards.addPropertyChangeListener("flippedCard", propertyChangeHandler);
List<BufferedImage> botImages = new ArrayList<>(Arrays.asList(images));
int botRotate = (int) Math.round((rnd.nextFloat() * 200) - 50);
Collections.rotate(botImages, botRotate);
bottomCards = new CardsPane(botImages, prefSize);
bottomCards.addPropertyChangeListener("flippedCard", propertyChangeHandler);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(4, 4, 4, 4);
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(topCards, gbc);
add(bottomCards, gbc);
} catch (Exception e) {
e.printStackTrace();
}
}
protected Dimension getMaxBounds(BufferedImage[] images) {
int width = 0;
int height = 0;
for (BufferedImage img : images) {
width = Math.max(width, img.getWidth());
height = Math.max(height, img.getHeight());
}
return new Dimension(width, height);
}
}
}

Categories