Java, is there a better way to do key detection? - java

So I'm just learning java, and from my work in C++, key dectection was much easier with SDL. But when I try to do it in Java it never seems to work. Could someone please check my code and make sure all of this is alright? And yes I did import everything....
public class start extends JFrame{
JLabel label = new JLabel();
Screen circle = new Screen();
int x = 0;
int y = 0;
static boolean m = false;
boolean running = true;
public static void main(String args[]){
start gui = new start();
gui.go();
}
public void go(){
JFrame j = new JFrame();
j.setDefaultCloseOperation(EXIT_ON_CLOSE);
j.setSize(400,400);
pannel p = new pannel();
Player player = new Player();
j.add(player);
j.setVisible(true);
player.addKeyListener(new key());
//try{
// for(int i = 0; i < 300; i ++){
// player.update();
// Thread.sleep(50);
// j.repaint();
// }
//}
//catch(Exception e){}
This try block was me testing to make sure that player.update() worked.... which it did! So I know the problem isn't with the update function
while(running){
//Updates
if(m)
player.update();
System.out.println(m);
I have the program printing out the value of m to see if its ever true... which it never is...
//Rendering
player.repaint();
}
}
public class pannel extends JPanel{
public void pannel(){
JPanel p = new JPanel();
Player player = new Player();
p.add(player);
p.setVisible(true);
}
}
public class key implements KeyListener{
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_SPACE:
m = true;
break;
}
}
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_SPACE:
m = false;
break;
}
}
public void keyTyped(KeyEvent e) {
}
}
}
In C++ there was a function that you had to call in order to detect if there has been any sort of key detection. You used this function in the main loop and it was really easy... Is there a function like this for Java? Or do I really need to put a key listener on EVERY object that I want to be effected by that key?

The simplest solution, and generally the more powerful, would be to use the key bindings API
The main problem with KeyListener is that is focus contextual. That is, the component it is registered to must be focusable AND have focus before it will raise key events

Related

Creating and Discarding JFrames that run Threads

I'm writing my Tetris using Java Swing. The Game class revolves around a JFrame (frame), which consists of a TetrisPanel extending JPanel (panel) where the blocks fall, a JLabel (pontok) point counter, a JTextArea (rekord_text) showing high scores, and another JPanel (kovi) showing the next block to fall. My idea is that the game has 3 difficulty levels, where the blocks fall with different speed.
I thought the best way of approaching this problem is to create a new JFrame with the components above, but with the blocks' speed set different. I am able to close the old JFrame. However, when the new JFrame opens up, it is only a blank frame, and it won't respond to closing the window.
I should add that TetrisPanel is running a thread, but I am 90% sure I stop that with a volatile boolean.
Constructor of the Game class:
this.difSet(nehezseg); //this function sets the falling velocity
TetrisPanel.stopped = true; //this static member is the volatile boolean responsible for stopping the thread
new_game = false;
frame = new JFrame("Tetris_alpha");
frame.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
panel = new TetrisPanel();
TetrisPanel.stopped = false;
new Thread(panel).start();
frame.add(panel, c);
pontok = new JLabel ("0");
frame.add(pontok, c);
rekord_text = new JTextArea();
//i set up the area
frame.add(rekord_text, c);
kovi = new NextAktualPanel();
frame.add(kovi, c);
menu = new MyMenu(this);
frame.setJMenuBar(menu);
frame.addWindowListener(new WindowAdapter()
{
#Override
public void windowClosing(WindowEvent e)
{
rekordok.add(panel.getPont());
rekordok.write(f);
e.getWindow().dispose();
System.exit(0);
}
}
);
frame.pack();
frame.setVisible(true);
}
The Game.start() function containing the game loop:
public void start()
{
//game_loop
while (!panel.GameOver() && !new_game)
{
if (panel.aktualLeertDetector())
{
panel.addAktualToBlocks();
panel.addNewAktual(next);
Elem temp = new Elem(0,0,rand.nextInt(7));
while (temp.getTipus() == next.getTipus())
temp = new Elem(0,0,rand.nextInt(7));
next = temp;
kovi.setNextAktual (next);
}
if (!paused)
pontok.setText(Integer.toString(panel.getPont()));
kovi.repaint();
panel.repaint();
}
The function which opens the new frame:
Public void newGame (Game g)
{
Game.new_game = true;
g.frame.dispose();
Game new_game = new Game("easy");
g = new_game;
g.start();
}
And the run() function of TetrisPanel:
public static volatile boolean stopped = false;
#Override
public void run() {
while (!stopped)
{
aktual.zuhan();
this.sorTeleAction();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Any help would be appreciated, including ideas about different a approach.
Do not use volatile boolean as status variable, use AtomicBoolean instead, volatile it's not the correct way to do this kind of things, and it does not either cause "immediate variable updating"... this is not volatile purpose.
It's not a good idea to start a thread on main AWT thread, you still have to use SwingUtilities.invokeLater(Runnable runnableAction). You can use something like this when launching a Gui Thread:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new Thread(threadAction).start();
} catch (Exception e) {
}
}
});
Hope that this will solve you problem!

KeyListener in a new thread for game input capture

I am making an old school Snake game in Java with Swing. I've read that in order to capture input in real time I need to run my game loop in a new thread so that It's wait() method won't interfere with the input capture. I've made InputCapture class implementing KeyListener and I've implemented keyPressed() method like that:
public class InputCapture implements KeyListener {
private Direction capturedDirection;
//Methods
#Override
public void keyPressed(KeyEvent e) {
boolean inputConsoleDebug = true;
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
capturedDirection = Direction.left;
if (inputConsoleDebug) System.out.println("LEFT");
} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
capturedDirection = Direction.right;
if (inputConsoleDebug) System.out.println("RIGHT");
} else if (e.getKeyCode() == KeyEvent.VK_UP) {
capturedDirection = Direction.up;
if (inputConsoleDebug) System.out.println("UP");
} else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
capturedDirection = Direction.down;
if (inputConsoleDebug) System.out.println("DOWN");
}
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
public Direction getCapturedDirection() {
return capturedDirection;
}
}
Then I've made Game class extending Thread and I've put game loop code into run() method:
public class Game extends Thread {
private Board board;
private Snake snake;
private JFrame frame;
private long waitTime;
private int difficultyStep;
private Direction inputDirection;
private InputCapture inputManager;
//Constructors
Game(Dimension boardSize) {
//Set difficulty
int applesToWin = boardSize.width * boardSize.height - 1;
final int easiestWaitTime = 1000;
final int hardestWaitTime = 100;
difficultyStep = (easiestWaitTime - hardestWaitTime) / applesToWin;
waitTime = easiestWaitTime;
//Set starting point
final int startingPointX = boardSize.width / 2;
final int startingPointy = boardSize.height / 2;
//Set board and snake
board = new Board(boardSize);
snake = new Snake(board, startingPointX, startingPointy);
//Set window Frame
frame = new JFrame(SnakeApplication.getApplicationName());
frame.setContentPane(board);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setResizable(false);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
interrupt();
}
});
//Set input manager
inputManager = new InputCapture();
frame.addKeyListener(inputManager);
inputDirection = null;
}
//Methods
public void run() {
board.spawnApple();
while (!isWon()) {
try {
sleep(waitTime);
} catch (InterruptedException e) {
return;
}
try {
inputDirection = inputManager.getCapturedDirection();
snake.move(inputDirection);
} catch (LosingMove e) {
showGameOverDialog();
return;
}
board.repaint();
}
showWinDialog();
}
JFrame getFrame() {
return frame;
}
private boolean isWon() {
for (int row = 0; row < board.getFields().length; row++) {
for (int col = 0; col < board.getFields()[0].length; col++) {
if (!(board.getFields()[row][col].getContent() instanceof Snake.SnakeNode)) return false;
}
}
return true;
}
private void showGameOverDialog() {
JFrame gameOverFrame = new JFrame();
JOptionPane.showMessageDialog(gameOverFrame, "Game Over!");
}
private void showWinDialog() {
JFrame gameOverFrame = new JFrame();
JOptionPane.showMessageDialog(gameOverFrame, "You Win!");
}
}
In my MainMenu class I've made startNewGame() method that is called when New Game button is clicked. This method creates Game object and starts a new thread by calling start() method.
public class MainMenu {
//Form components references
private JButton exitButton;
private JFrame frame;
private JPanel mainPanel;
private JButton newGameButton;
private JLabel titleLabel;
//Constructors
MainMenu() {
//Set window Frame
frame = new JFrame(SnakeApplication.getApplicationName());
frame.setContentPane(mainPanel);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setResizable(false);
frame.pack();
newGameButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
startNewGame();
}
});
exitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
exitGame();
}
});
}
JFrame getFrame() {
return frame;
}
private Dimension showBoardSizeDialog() {
Frame boardSizeFrame = new Frame();
int width = Integer.parseInt(JOptionPane.showInputDialog(boardSizeFrame, "Set board's width:"));
int height = Integer.parseInt(JOptionPane.showInputDialog(boardSizeFrame, "Set board's height:"));
return new Dimension(width, height);
}
private void startNewGame() {
Dimension boardSize = showBoardSizeDialog();
frame.setVisible(false);
Game game = new Game(boardSize);
game.getFrame().setVisible(true);
//Starting game loop in a new thread
game.start();
try {
game.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
frame.setVisible(true);
}
}
But when testing the app it gets stuck in the game loop and doesn't capture input at all. Why? I was trying to debug It, but every time the new thread is started it gets stuck in game loop. The Board itself is painted only when main thread ends its execution. Why? Shouldn't It be repainted many times during game loop if execution is stucked there?
Also, I've made thread interrupt when frame's close button is clicked (red X button) so execution could get back to MainMenu and reappear it, but clicking red close button has no effect.
The program freezes because of the call to game.join() in startNewGame. join keeps the thread it was called from from continuing execution until the thread it was called on dies. In your situation, join defeats the purpose of using another thread, so you should just remove that.
There are other issues, though. You probably shouldn't use a thread. You should probably use a Swing Timer. Swing isn't thread-safe, and I can already see a few places where your code isn't thread-safe either. (For example, you need to declare capturedDirection as volatile.) Writing correct multi-threaded code with Swing is a bit complicated and it would be much simpler to just use a timer.
Otherwise, if you don't use a timer, you need to use e.g. synchronization between the game thread (which writes to shared game state) and the Swing thread which does painting (and presumably reads from shared game state). If you don't, you may run in to problems that are hard to diagnose.
Also see The Use of Multiple JFrames: Good or Bad Practice?
You should make your Game class extending Runnable instead of Thread.
Then to have the game in a different thread:
Game theGame = ... // initialization code here
new Thread(theGame).start();

KeyListener Lags Inconsistantly

I am writing a little game in Java and, like most games, I need to listen for user input. I decided to use java.awt.event.KeyListener to handle inputs.
Here is my main method:
public static void main(String[] args){
LevelViewer l = new LevelViewer(LevelFileIO.load());
List<Entity> entities = l.getEntities();
List<GameObject> gameObjects = l.getGameObjects();
Pacman player = null;
for (Entity e : entities){
if (e instanceof Pacman){
player = (Pacman)e;
break;
}
}
JFrame frame = new JFrame();
frame.add(l);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setFocusable(true);
frame.requestFocus();
class Listener implements KeyListener{
Pacman player;
Listener(Pacman player){
this.player = player;
}
#Override
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_W:
player.up();
break;
case KeyEvent.VK_D:
player.right();
break;
case KeyEvent.VK_S:
player.down();
break;
case KeyEvent.VK_A:
player.left();
break;
}
}
#Override
public void keyReleased(KeyEvent e) {}
#Override
public void keyTyped(KeyEvent e) {}
}
frame.addKeyListener(new Listener(player));
Timer timer = new Timer();
timer.schedule(new UpdateTimer(
entities.toArray(new Entity[entities.size()]),
gameObjects.toArray(new GameObject[gameObjects.size()]),
l), 0, 17);
}
That is all pretty straightforward, when I read key events I call methods in the player that simply change his velocity.
An example:
public void right(){
this.setVelocity(new Vector2(speed, 0));
this.setSprite(right);
}
The Timer at the end of the main method just calls this:
public UpdateTimer(Entity[] toUpdate, GameObject[] gameObjects, LevelViewer toRedraw){
this.toUpdate = toUpdate;
this.gameObjects = gameObjects;
this.toRedraw = toRedraw;
}
#Override
public void run() {
toRedraw.repaint();
if (timeAtLastUpdateCall == 0){
timeAtLastUpdateCall = System.currentTimeMillis();
for (Entity e : toUpdate){
e.start();
}
return;
}
long newTime = System.currentTimeMillis();
double deltaT = ((double)(newTime - timeAtLastUpdateCall)/1000.0);
timeAtLastUpdateCall = newTime;
for (Entity e : toUpdate){
for (GameObject g : gameObjects){
if (g.touching(e)){
e.setVelocity(e.getVelocity().multiply(-1));
e.free(g);
}
}
e.update(deltaT);
e.getSprite().nextFrame();
}
}
All this run function does is some collision checking and then calls the update method in each entity. In the case of the player it just calculates how much it should move since the last update call:
public void update(double deltaT){
this.setPosition(this.getPosition().add(velocity.multiply(deltaT)));
}
Now the problem is that when I press a key that changes the players velocity the change will usually occur instantaneously, but sometimes there can be noticeable lag (around a quarter of a second, much more than 17 ms).
Is this a problem with Java's KeyListener, or with my implementation?
I would like to fix this to have smooth user input.
I don't think this is an issue with KeyListener. I am not a game developer but some things to consider:
Have you timed how long it takes to do the TimerTask? If it's ever over 17ms then it could be a problem especially when you compare schedule to scheduleAtFixedRate
You may want to use a proper game loop particularly if you plan on this game being played on systems out side of your control.

Java: turn-based battle system (with gui)

EDIT (4/3/2017): Sorry, I was a noob back then.
I'm trying to make a turn-based battle system where the player clicks buttons on his turn. But I can't seem to find out how to code it. Below is the code on what I did.
What should happen here is that when I click the attack button(for example) the next turn will be the monster's turn but the playerTurn variable doesn't change when I click the button. playerTurn is always true. Can you help me correct this? It is a turn-based battle system.
public class BattleFrame extends JFrame implements ActionListener, Runnable {
private JButton atkButton = new JButton("Attack");
private JButton runButton = new JButton("Run");
private JButton itemButton = new JButton("Item");
private JButton magicButton = new JButton("Magic");
private JPanel panelButtons = new JPanel();
private Random rand = new Random();
private Boolean playerTurn;
private Thread t;
public BattleFrame() {
setSize(480, 390);
setLayout(null);
// I have not included the code with the setting of the JButtons
initPanel(); // initialize the panel with buttons
setResizable(false);
setVisible(true);
playerTurn = true;
t = new Thread(this);
t.start();
}
// I'm not so familiar with 'synchronized' but I tried it here but it doesn't change anything
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
if(src.equals(atkButton) && playerTurn) {
System.out.println("Attack!");
playerTurn = false;
}
else if(src.equals(runButton) && playerTurn) {
System.out.println("Run!");
playerTurn = false;
}
else if(src.equals(itemButton) && playerTurn) {
System.out.println("Item");
playerTurn = false;
}
else if(src.equals(magicButton) && playerTurn) {
System.out.println("Magic");
playerTurn = false;
}
}
public void run() {
while(true) {
if(playerTurn == false) {
System.out.println("Monster's turn!"); // just printing whose turn it is
playerTurn = true;
}
else System.out.println("player's turn!");
}
}
public static void main(String[] args) {
new BattleFrame();
}
}
A Boolean is an object, so gets compared by identity, not value.
assert new Boolean (true) == new Boolean(true);
The above will fail, as the two different Boolean objects are not the same object.
For general use, use the primitive type boolean, not the standard library class Boolean. Cases where you should use Boolean are pretty rare: it's one of those things that exists more for symmetry than any real practical reason. If you do use it, you need to use a.equals(b) not a == b.
For more details, see:
http://www.java-samples.com/showtutorial.php?tutorialid=221

Make a main method wait on a smaller method (java)

i really need to find better ways to word my questions.
Basically I've created a program that takes information from a webpage and displays it nicely across the screen.
When the user closes the program, they actually hide it.
I also have another method which constantly loops checking for information to see if tis been updated.
unfortunately the problem im having is that it loops to fast, i only want it to check for information every 40 seconds or so.
What i tried was inserting a wait(1000,1000) in the method itself and in the main of the program. but both of these cause IllegalMonitorStateException.
Is this the correct way to make the thread wait properly? or is there a better way?
note: the only thread i have is the main.
MAIN
class Marquee
{
public static void main(String[] args) throws InterruptedException
{
MyFrame frame = new MyFrame();
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
frame.setVisible(true);
frame.setAlwaysOnTop(true);
frame.setBackground(Color.BLACK);
frame.setResizable(true);
while(true)
{
// this doesnt work
frame.wait(1000,1000);
frame.notifyAll();
frame.checkForNewUpdate();
System.out.println(" ____________________________next line _______________________________");
}
}
}
CHECK FOR UPDATES
public String[] checkForNewUpdate()
{
//setVisible(true);
String tempUpdate = getEngineersUpdate();
if (latestUpdate[0] != tempUpdate)
{
// do nothign
setVisible(false);
}
else if(latestUpdate[0]==tempUpdate)
{
latestUpdate[0] = tempUpdate;
//show the page again
setVisible(true);
}
else if(latestUpdate[0]!= "NULL")
{
// do nothing
//latestUpdate[0] = tempUpdate;
}
else
{
latestUpdate[0] = tempUpdate;
}
return latestUpdate;
}
1: WHat am i doing wrong to get this exception
2: Is there any other way to make a gap of time in a method
3: Am i going to have to put all these methods into another thread? Please say no
// my constructor which I failed to mention has a timer in it. only i dont know hwo to use it
class MyFrame extends JFrame implements ActionListener
{
private ActionListener listener;
private Timer t1;
private String [] latestUpdate = new String[1];
public MyFrame()
{
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();// gets the maximum size of the screen
setSize(d.width,(d.height/100)*10);//sets it to max. need to change this
// this shit find the max size of screen and puts it bottom left
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice defaultScreen = ge.getDefaultScreenDevice();
Rectangle rect = defaultScreen.getDefaultConfiguration().getBounds();
int x = (int)rect.getMinX();
int y = (int)rect.getMaxY()-getHeight();
setLocation(x,y-30);
setTitle("ALERT::OUTAGE");
MyPanel panel = new MyPanel();
add(panel);
listener = this;
t1 = new Timer(50,listener);
t1.start();
}
by request, here is getEngineersUpdate()
public String getEngineersUpdate() //gets data from page and sets it to string.
{
String update = "blank";
final WebClient webClient = new WebClient();
webClient.setJavaScriptEnabled(false);// javascript causes some serious problems.
webClient.setCssEnabled(false);
String forChecking;
HtmlPage page;
try
{
URL outageURL = new URL("file:\\C:\\Users\\0vertone\\Desktop\\version control\\OUTAGE\\Outages.html"); //local drive at home
page = webClient.getPage(outageURL);
//All this crap can be gone if we just give the table an id
Object[] dates = page.getByXPath("//span[#id='date']/text()").toArray();
Object[] sites = page.getByXPath("//span[#id='site']/text()").toArray();
Object[] issues = page.getByXPath("//span[#id='issue']/text()").toArray();
System.out.println("" + dates[0].toString());
System.out.println("" + sites[0].toString());
System.out.println("" + issues[0].toString());
update = (dates[0].toString() + " " + sites[0].toString() + " " +issues[0].toString());
forChecking = dates[0].toString();
/**some examples of the getCellAt() method*/
//update = table.getCellAt(0,0).asText(); // This returns DATE/Time
//update = table.getCellAt(1,0).asText(); // This return the actual date
//update = table.getCellAt(0,1).asText(); // This returns, SITE/Sector
//update = table.getCellAt(1,1).asText(); // This returns the actual site issue
}
catch (FailingHttpStatusCodeException a)
{
System.out.println("Failing HTTP Status Execution");
a.printStackTrace();
}
catch (MalformedURLException b)
{
System.out.println("Malformed URL");
b.printStackTrace();
}
catch (IOException c)
{
System.out.println("IO PROBLEMS!");
c.printStackTrace();
}
webClient.closeAllWindows();
return update;
}
I've changed your code so it should work as you intended. I'm not clear on what getEngineersUpdate() does, so I can't say for sure if it will work, but I've given you a start. I've included 2 options for how to handle it, with explanation in the comments. You can see how to use a Timer properly in the constructor, also. Finally, I don't have your full code, so I had to rig something together to simulate it.
class Marquee {
public static void main(String[] args) throws InterruptedException {
MyFrame frame = new MyFrame();
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
frame.setVisible(true);
frame.setAlwaysOnTop(true);
frame.setBackground(Color.BLACK);
frame.setResizable(true);
}
}
class MyFrame extends JFrame {
private String [] latestUpdate = new String[1];
private static final int DISPLAY_TIME = 3000;
private Timer displayTimer;
/*
* Option #1:
* Ideally, you'd have the thread that generates the "Engineers Update" messages call this
* method. If you can't make this event based, then you should use option #2
*/
public void newUpdate(String message) {
setVisible(true);
// change this to whatever you need to.
text.setText(message);
displayTimer.restart();
}
// I used this to test it
private JTextField text;
public MyFrame() {
// gets the maximum size of the screen
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
//sets it to max. need to change this
setSize(d.width, (d.height / 100) * 10);
// this shit find the max size of screen and puts it bottom left
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice defaultScreen = ge.getDefaultScreenDevice();
Rectangle rect = defaultScreen.getDefaultConfiguration().getBounds();
int x = (int) rect.getMinX();
int y = (int) rect.getMaxY() - getHeight();
setLocation(x, y - 30);
setTitle("ALERT::OUTAGE");
//MyPanel panel = new MyPanel();
//add(panel);
text = new JTextField("Initial Text");
add(text);
// this creates a timer that when it goes off, will hide the frame
displayTimer = new Timer(DISPLAY_TIME, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
});
// sets the timer not to repeat
displayTimer.setRepeats(false);
//This code is for option #2:
updateTimer = new Timer(UPDATE_INTERVAL, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
checkForNewUpdate();
}
});
updateTimer.start();
}
// This is for option #2
private static final int UPDATE_INTERVAL = 1000;
private Timer updateTimer;
/*
* Option #2:
* Not ideal, but this should work.
*/
public String[] checkForNewUpdate() {
// I don't know how getEngineersUpdate() works
// which would have made it much easier to help you.
String tempUpdate = getEngineersUpdate();
// String comparison doesn't work like this in java.
// you also had a sleeping NullPointerException here
if (!tempUpdate.equals(latestUpdate[0])) {
// this is when you have a new update, correct?
newUpdate(tempUpdate);
latestUpdate[0] = tempUpdate;
} else if (tempUpdate.equals(latestUpdate[0])) {
// it's the same update as last time, so do nothing
} else if (tempUpdate.equals("NULL")) {
// You need to handle this according to what getEngineersUpdate() does
}
return latestUpdate;
}
// This code is rigged to show how it would work
private static int i = 0;
private String getEngineersUpdate() {
// 1 in 6 chance of returning "NULL"
if (Math.random() * 6 - 1 < 0)
return "NULL";
// probability of 1 in 4 of generating a new update
if(Math.random() * 4 - 1 < 0)
return "UPDATE #"+i++;
else
return "UPDATE #"+i;
}
}
I think you can't call wait() on an JFrame, but I am not sure.
You have to call wait() within a snychronized-block. (Example below)
Thread.sleep(1000l) can be used, if it runs in a Thread, but look for the class Timer
It would be much better design, if you create a thread, which checks for updates. You can notify the GUI (JFrame) with some kind of event-listener about the new date to display.
Take a look at the Timer and Callable.
You should create another thread, you should call checkforNewUpdate method from this thread. And also do not forget use SwingUtilities.invokeLater method to update your UI inside checkforNewUpdate method. here is the some part of the code;
public class Marque {
private JFrame frame;
class CheckForUpdate implements Runnable {
public void run() {
while(true) {
checkForNewUpdate();
try {
Thread.sleep(40000);
} catch (InterruptedException e1) {
e1.printStackTrace();
throw new RuntimeException(e1);
} }
}
public String[] checkForNewUpdate() {
//your code
// user interface interaction code
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.setVisible(true);
}
});
}
}
public Marque() {
frame = new JFrame();
//....frame related code
new Thread(new CheckForUpdate()).start();
}
public static void main(String[] arg) {
Marque marque = new Marque();
}

Categories

Resources