I am making a simple digital clock. I want to remove flicker from when program runs. I tried different sleep time but it doesn't help.
public class DigitalClock extends Applet implements Runnable{
Thread t=null;
int hrs=0, min=0, sec=0;
String tString="";
public DigitalClock(){
//TODO add required code
init();
}
public void init() {
// TODO Auto-generated method stub
setBackground(Color.BLACK);
}
public void start(){
t=new Thread(this);
t.start();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
DigitalClock dc=new DigitalClock();
JFrame f=new JFrame("Digital Clock");
f.setSize(300, 300);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(dc);
dc.start();
f.setVisible(true);
}
#Override
public void run() {
// TODO Auto-generated method stub
try {
while(true){
Calendar cal=Calendar.getInstance();
hrs=cal.get(Calendar.HOUR_OF_DAY);
min=cal.get(Calendar.MINUTE);
sec=cal.get(Calendar.SECOND);
tString=hrs+":"+min+":"+sec;
repaint();
Thread.sleep(40);
}
} catch (Exception e) {
// TODO: handle exception
}
}
public void paint(Graphics g){
g.setColor(Color.white);
g.drawString(tString, 50, 50);
}
}
How do i use paintComponent method. and will it help to reduce flicker?
Use a javax.swing.Timer instead of your sleep loop.
Related
Hi I'm studying the basics of java threads,
but I'd like to get some help because I don't understand the examples in the book.
https://imgur.com/a/pcdOq2n
In this example, when the user presses any key,
the yellow bar is filled with magenta and the bar's magenta is
reduced by a thread.
But the part I don't understand is if you press the key for a long time while bar is full,
the magenta of the bar does not reduce immediately when the key is released
when I checked. the fill() function was running for a certain time even when the key was released.
I want to know, why if the bar is full and the key is pressed for a long time,
the fill() function works for a certain time even when the key is released
and the bar does not reduce immediately.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class MyLabel extends JLabel {
private int barSize = 0;
private int maxBarSize;
public MyLabel(int maxBarSize) {
this.maxBarSize = maxBarSize;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.MAGENTA);
int width = (int) ( ( (double)( getWidth() ) )/maxBarSize *barSize );
if (width == 0) return;
g.fillRect(0, 0, width, this.getHeight());
}
synchronized void fill() {
if (barSize == maxBarSize) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
return;
}
}
barSize++;
repaint();
notify();
}
synchronized void consume() {
if (barSize == 0) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
return;
}
}
System.out.println("consume");
barSize--;
repaint();
notify();
}
}
class ComsumerThread extends Thread {
private MyLabel bar;
public ComsumerThread(MyLabel bar) {
this.bar = bar;
}
#Override
public void run() {
// TODO Auto-generated method stub
while(true) {
try {
sleep(100);
bar.consume();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
return;
}
}
}
}
public class TabAndThreadEx extends JFrame {
private MyLabel bar = new MyLabel(100);
public TabAndThreadEx(String title) {
super(title);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = getContentPane();
c.setLayout(null);
bar.setBackground(Color.orange);
bar.setOpaque(true);
bar.setLocation(20, 50);
bar.setSize(300, 20);
c.add(bar);
c.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
bar.fill();
}
});
setSize(350, 200);
setVisible(true);
c.setFocusable(true);
c.requestFocus();
ComsumerThread th = new ComsumerThread(bar);
th.start();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new TabAndThreadEx("Quickly press any key to fill the bar");
}
}
I'm going to create a JPanel Howto, which is rendering 6 images in order and then add the back button to go back to title.
I'm trying check if it call paintComponent method in class howto or not. And it doesn't so the value i is still 0 and end up stuck in loop
Here's my Howto class
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JPanel;
import Audio.HitSound;
import Graphic.DrawingUtility;
public class Howto extends JPanel implements Runnable{
private JButton back;
private static int i;
public Howto(){
this.setPreferredSize(new Dimension(800, 600));
this.setLayout(null);
repaint();
HitSound h = new HitSound();
i=0;
this.setVisible(true);
}
public void run() {
// TODO Auto-generated method stub
try {
while(i<6)
{
GameManager.frame.repaint();
Thread.sleep(10);
System.out.println("i: " + i);
}
} catch (Exception e) {
// TODO: handle exception
Thread.interrupted();
}
}
public void paintComponent(Graphics g){
if(GameManager.thread.isAlive()){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(DrawingUtility.getHowto(i), 0, 0, 800, 600,null);
i++;
}
}
}
and this what in my GameManager class
public static void startThread() {
thread = new Thread(howto);
thread.start();
}
public static void runHowto() {
howto = new Howto();
howto.setVisible(true);
frame.switchScene(howto);
howto.repaint();
startThread();
while (thread.isAlive()) {
//frame.repaint();
}
if (!thread.isAlive()) {
JButton back = new JButton();
back.setBorderPainted(false);
back.setContentAreaFilled(false);
back.setFocusPainted(false);
back.setOpaque(false);
back.setBounds(640, 446, 132, 132);
back.addMouseListener(new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
HitSound h = new HitSound();
h.play(3);
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
GameManager.goToTitle();
}
});
}
but when I call runHowto(); it's still looping and i == 0 and not increase i
So I think it's may have problem with paintComponent and repaint method
So please help me fixing it Thanks in advance :)
The while (thread.isAlive()) loop blocks the AWT Event Dispatch Thread (EDT).
You need to return to the event dispatch loop from runHowto. Have your Howto task to post back to the EDT with java.awt.EventQueue.invokeLater to construct your back button and presumably add it to a panel.
I have written the following code to handle an event incase a Jinternalframe is minimized or maximized.
jif.addComponentListener(new ComponentListener() {
public void componentResized(ComponentEvent e) {
Boolean isMax = ((JInternalFrame)e.getComponent()).isMaximum();
if(isMax == false)
{
// TODO Auto-generated method stub
}
else if(isMax == true )
{
// TODO Auto-generated method stub
}
}
public void componentMoved(ComponentEvent e) {
// TODO Auto-generated method stub
}
public void componentShown(ComponentEvent e) {
// TODO Auto-generated method stub
}
public void componentHidden(ComponentEvent e) {
// TODO Auto-generated method stub
}
}
);
The problem is that the isMax part gets triggered when the frame loads. I want this event to happen only after the Jinternalframe is completely loaded. Also i have noticed this event triggers when i minimize the container applet.
Is there any workaround for this?
You might be able to use a PropertyChangeListener and InternalFrameListener:
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
public class InternalFrameEventTest {
public JComponent makeUI() {
final JDesktopPane desktop = new JDesktopPane();
JPanel p = new JPanel(new BorderLayout());
p.add(desktop);
p.add(new JButton(new AbstractAction("New") {
#Override public void actionPerformed(ActionEvent e) {
JInternalFrame f = new JInternalFrame("title", true, true, true, true);
InternalFrameHandler handler = new InternalFrameHandler();
f.addInternalFrameListener(handler);
f.addPropertyChangeListener(handler);
f.setSize(240, 120);
f.setVisible(true);
desktop.add(f);
}
}), BorderLayout.NORTH);
return p;
}
public static void main(String... args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new InternalFrameEventTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class InternalFrameHandler implements PropertyChangeListener, InternalFrameListener {
//PropertyChangeListener
#Override public void propertyChange(PropertyChangeEvent e) {
if (JInternalFrame.IS_MAXIMUM_PROPERTY.equals(e.getPropertyName())) {
System.out.println("isMaximum: " + e.getNewValue());
}
}
//InternalFrameListener
#Override public void internalFrameClosing(InternalFrameEvent e) {
System.out.println("internalFrameClosing");
}
#Override public void internalFrameClosed(InternalFrameEvent e) {
System.out.println("internalFrameClosed");
}
#Override public void internalFrameOpened(InternalFrameEvent e) {
System.out.println("internalFrameOpened");
}
#Override public void internalFrameIconified(InternalFrameEvent e) {
System.out.println("internalFrameIconified");
}
#Override public void internalFrameDeiconified(InternalFrameEvent e) {
System.out.println("internalFrameDeiconified");
if (e.getInternalFrame().isMaximum()) {
System.out.println("isMaximum: " + e.getInternalFrame().isMaximum());
}
}
#Override public void internalFrameActivated(InternalFrameEvent e) {
System.out.println("internalFrameActivated");
}
#Override public void internalFrameDeactivated(InternalFrameEvent e) {
System.out.println("internalFrameDeactivated");
}
}
I'm right now trying to mix LWJGL and Swing so I can have Swing's GUI and LWJGLS Graphics... But it doesn't work, Thanks in advance.
Code :
/**
*
*/
public static TSudioQE TSudio;
private static final long serialVersionUID = -8495077485468477943L;
public static void main(String[] args) {
try {
TSudioQE tsudio = new TSudioQE();
} catch (LWJGLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public TSudioQE() throws LWJGLException {
setTitle("TSudio Quall Engine 1X");
JPanel p = new JPanel();
Canvas c = new Canvas();
Display.create();
Display.setParent(c);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
// set the color of the quad (R,G,B,A)
GL11.glColor3f(0.5f, 0.5f, 1.0f);
// draw quad
GL11.glBegin(GL11.GL_QUADS);
GL11.glVertex2f(100, 100);
GL11.glVertex2f(100 + 200, 100);
GL11.glVertex2f(100 + 200, 100 + 200);
GL11.glVertex2f(100, 100 + 200);
GL11.glEnd();
add(p);
setSize(800, 460);
setExtendedState(JFrame.MAXIMIZED_BOTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
#Override
public void windowOpened(WindowEvent e) {
// TODO Auto-generated method stub
}
#Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
}
#Override
public void windowClosed(WindowEvent e) {
// TODO Auto-generated method stub
}
#Override
public void windowIconified(WindowEvent e) {
// TODO Auto-generated method stub
}
#Override
public void windowDeiconified(WindowEvent e) {
// TODO Auto-generated method stub
}
#Override
public void windowActivated(WindowEvent e) {
// TODO Auto-generated method stub
}
#Override
public void windowDeactivated(WindowEvent e) {
// TODO Auto-generated method stub
}
I get the following error:
org.lwjgl.LWJGLException: Parent.isDisplayable() must be true
at org.lwjgl.opengl.Display.createWindow(Display.java:301)
at org.lwjgl.opengl.Display.setParent(Display.java:451)
at qq.application.TSudioQE.<init>(TSudioQE.java:47)
at qq.application.TSudioQE.main(TSudioQE.java:33)
Anyone who know how to fix it? It could be nice.
Have a great day :-)
The Canvas you set as parent for your Display has to be visible:
JFrame frame = new JFrame();
Canvas canvas = new Canvas();
frame.add(canvas);
frame.setVisible(true);
try
{
Display.setParent(canvas);
Display.create();
}
catch (LWJGLException e)
{
e.printStackTrace();
}
i am trying to make a simple reaction test in java.
when the screen turns green i press space witch is supposed to change te boolean "clicked into false and stop the loop that measures time.
in reality the key listner does nothing.
am i adding the keay listener to the right compnent( jpanel panel)?
is there any other problems?
import java.awt.Color;
import java.awt.RenderingHints.Key;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
public class mainCheck {
// //////////////////////////////////////
public static void timeKeeper() {
boolean clicked=false;
long time = 10000;
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
panel.setBackground(Color.GREEN);
while (time > 0 && !clicked) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
time--;
}
panel.setBackground(Color.gray);
long time2= 10000-time;
JLabel x = new JLabel("" +time2+"");
panel.add(x);
}
// //////////////////////////////////////
static boolean clicked;
JFrame frame;
static JPanel panel;
public mainCheck() {
frame = new JFrame();
panel = new JPanel();
clicked = false;
Handler handler = new Handler();
frame.addKeyListener(handler);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,500);
frame.setVisible(true);
}
// //////////////////////////////////////
public static void main(String[] args) {
mainCheck f = new mainCheck();
panel.getActionMap();
f.timeKeeper();
}
// //////////////////////////////////////
public class Handler implements KeyListener {
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
clicked = false;
System.out.println("space pressed");
}
}
}
}
do not use Thread.sleep(5000); block Event Dispatch Thread and during sleep you can lost all events to the already visible Swing GUI
use Swing Timer instead
Thread.sleep(1); could be proper delay for space enviroment, non_human, very short period attacking latency in Native OS (8-14miliseconds, depends of Native OS)
JLabel x = new JLabel("" +time2+""); and panel.add(x); in AWT/Swing isn't any notifiers that some, any, part of JComponents are removed or added, have to notify used LayoutManager (JPanel has FlowLayout in API) by using methods revalidate and repaint, e.g.
.
JLabel x = new JLabel("" +time2+"");
panel.add(x);
panel.revalidate();
panel.repaint();
Swing GUI should be created on Initial Thread
don't to use KeyListener use KeyBindings instead, otherwise you (are focus hunter) would need to set panel.seFocusable(true);
The problem is that you "e.getKeyCode()" always is "0" so
change for "e.getKeyChar()" and "(char)32"
the other problem is in that you put clicked = false and must be
"true"
And the last problem you have is in "timeKeeper()" you have to erase "boolean" because it is already declarated
Bad
public static void timeKeeper() {
boolean clicked=false
....}
Good
public static void timeKeeper() {
clicked=false
....}
This is the correct code:
import java.awt.Color;
import java.awt.event.*;
import javax.swing.*;
public class mainCheck {
// //////////////////////////////////////
public static void timeKeeper() {
clicked=false;
long time = 10000;
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
panel.setBackground(Color.GREEN);
while (time > 0 && !clicked) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
time--;
}
panel.setBackground(Color.gray);
long time2= 10000-time;
JLabel x = new JLabel("" +time2+"");
panel.add(x);
}
// //////////////////////////////////////
static boolean clicked;
JFrame frame;
static JPanel panel;
Handler handler = new Handler();
public mainCheck() {
frame = new JFrame();
panel = new JPanel();
clicked = false;
frame.addKeyListener(handler);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,500);
frame.setVisible(true);
}
// //////////////////////////////////////
public static void main(String[] args) {
mainCheck f = new mainCheck();
panel.getActionMap();
f.timeKeeper();
}
// //////////////////////////////////////
public class Handler implements KeyListener {
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == (char)32) {
clicked = true;
System.out.println("space pressed");
}
}
}
}
It's a really bad idea to use Thread.sleep() to decrement the time value.
Use a Timer object instead:
public void myTimer(){
Timer myTimer = new Timer(delay, new ActionListener(){
public void actionPerformed(ActionEvent e){
//Stuff to do
}
});
}
Where delay is the amount of time you delay the timer. You start the timer with myTimer.start();