I make and display an clock count down with this code
LabelField time;
long mille=0;
Timer timer=null;TimerTask task=null;
public Timerscreen() {
mille=1000*60*1;
time=new LabelField();
add(time);
timer=new Timer();
task=new TimerTask() {
public void run() {
synchronized (UiApplication.getEventLock()) {
if(mille!=0){
SimpleDateFormat date=new SimpleDateFormat("mm:ss") ;
System.out.println("================="+date.formatLocal(mille)+"====================="+Thread.activeCount());
time.setText(date.formatLocal(mille));
mille=mille-1000;
}else{
time.setText("00:00");
mille=1000*60*1;
timer.cancel();
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.inform("Time expaired");
}
});
}
}
}
};
timer.schedule(task,0, 1000);
And when I push a new screen , I want to this clock still display and count down.
How can I do that ?
It is not possible to add a single ui field or manager into two managers or screens.. every ui field or manager must have at most one parent (screen or manager).
So if you need a LabelField which will hold and show time on different screens, then you only need to implement some sort of listener which will listen for the time changes.. and for every changes you have to update the screen and the LabelField with the new value. You have already implemented a TimerTask which will provide you updated data.
[Edited - added later]
you can check the following codes, not tested but something like this will solve your problem...
class MyTimerUtil {
TimerListener listener = null;
public MyTimerUtil() {
}
public void setTimerListener(TimerListener listener) {
this.listener = listener;
}
public void startTimer() {
final int interval = 1000;
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
// add your codes..
// notify others
if (listener != null) {
listener.timeChanged();
}
}
};
timer.schedule(task, 0, interval);
}
}
interface TimerListener {
public void timeChanged();
}
class ScreeA extends MainScreen implements TimerListener {
public void timeChanged() {
// add Codes here on time changed event
}
}
in the above snippet, you can implement TimerListener interface in any screen instance and can get update on every time changed event by the MyTimerUtil class. For that, you have to set an instance of ScreeA (which implements TimerListener) via setTimerListener() of the MyTimerUtil class.
Also need to start the timer by calling startTimer() method.
Related
I have the following problem:
My method opens a JDialog with a bunch of buttons (only one in example code). I want to click a button and thereby choose an ImageIcon for my method to return. But the Method does not wait for me to click a button. It opens the window and then returns an empty ImageIcon.
public class Kartenauswahl {
ImageIcon bandit;
public ImageIcon auswahlfenster() {
int bwidth = new Integer(150);
int bheight = new Integer(225);
bandit = new ImageIcon("cover/Bandit.jpe");
bandit.setImage(bandit.getImage().getScaledInstance(bwidth,bheight,Image.SCALE_DEFAULT));
final JDialog kartenwahl = new JDialog();
kartenwahl.setTitle("Kartenwahl");
kartenwahl.setSize(1500,1000);
kartenwahl.setVisible(true);
kartenwahl.setLayout(new FlowLayout());
ImageIcon returnicon= new ImageIcon();
final JButton b1 = new JButton(); //just to get the Icon out of the void loop
JButton B1 = new JButton(bandit); //this is going to be the button I want to click to choose the ImageIcon which is returned
B1.setContentAreaFilled(false);
B1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
b1.setIcon(bandit);
kartenwahl.dispose();
}
});
kartenwahl.add(B1);
returnicon = (ImageIcon) b1.getIcon();
return returnicon;
}
}
Question: can I bind the return statement to a condition? Like "only return after I clicked that Button B1"?
Hi sorry for the long wait. I have written an custom JDialog that should work for you.
public class CustomDialog extends JDialog {
JButton[] buttons;
ImageIcon selectedImageIcon;
public CustomDialog() {
setSize(500, 500);
setLayout(new GridLayout(4, 6));
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
selectedImageIcon = ((ImageIcon) ((JButton) e.getSource()).getIcon());
dispose();
}
};
buttons = new JButton[24];
for(int i = 0; i < 24; i++) {
buttons[i] = new JButton(new ImageIcon("path_to_your_image_file"));
buttons[i].addActionListener(actionListener);
add(buttons[i]);
}
setVisible(true);
}
public ImageIcon getSelectedImageIcon() {
return selectedImageIcon;
}
}
The initial size is not that important the GridLayout is. you mentioned that you would need 24 buttons so I created an grid with 4 rows and 6 columns.
Then I create the buttons in a loop and adding the same Listener to set the selection icon with the icon of the pressed button. Afterwards I dispose the screen triggering an windowClosed event.
You could simply create this Dialog from your main class and wait for the response like so:
public class main {
public static void main(String[] args) {
CustomDialog customDialog = new CustomDialog();
customDialog.addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent e) {
ImageIcon icon = customDialog.getSelectedImageIcon();
//do something with your icon
}
});
}
}
Don't forget to mark this answer as correct if it fixes your problem.
Have a good one!
I am building a download manager in javafx
I have added function to download button which initialises new task.More than one download is also being executed properly.
But I need to add pause and resume function. Please tell how to implement it using executor. Through execute function of Executors, task is being started but how do i pause & then resume it??
Below I am showing relevant portions of my code. Please tell if you need more details. thanks.
Main class
public class Controller implements Initializable {
public Button addDownloadButton;
public Button pauseResumeButton;
public TextField urlTextBox;
public TableView<DownloadEntry> downloadsTable;
ExecutorService executor;
#Override
public void initialize(URL location, ResourceBundle resources) {
// here tableview and table columns are initialised and cellValueFactory is set
executor = Executors.newFixedThreadPool(4);
}
public void addDownloadButtonClicked() {
DownloadEntry task = new DownloadEntry(new URL(urlTextBox.getText()));
downloadsTable.getItems().add(task);
executor.execute(task);
}
public void pauseResumeButtonClicked() {
//CODE FOR PAUSE AND RESUME
}
}
DownloadEntry.java
public class DownloadEntry extends Task<Void> {
public URL url;
public int downloaded;
final int MAX_BUFFER_SIZE=50*1024;
private String status;
//Constructor
public DownloadEntry(URL ur) throws Exception{
url = ur;
//other variables are initialised here
this.updateMessage("Downloading");
}
#Override
protected Void call() {
file = new RandomAccessFile(filename, "rw");
file.seek(downloaded);
stream = con.getInputStream();
while (status.equals("Downloading")) {
byte buffer=new byte[MAX_BUFFER_SIZE];
int c=stream.read(buffer);
if (c==-1){
break;
}
file.write(buffer,0,c);
downloaded += c;
status = "Downloading";
}
if (status.equals("Downloading")) {
status = "Complete";
updateMessage("Complete");
}
return null;
}
}
You may be interested in Concurrency in JavaFX.
I guess you should also have a look at pattern Observer.
By the way I think you should not use constant string as a status ("Downloading", etc), creating an enum would be a better approach.
In your loop, around the read/write part, there should be a synchronization mechanism, controlled by your pause/resume buttons (see the two links).
I have a screen. I want alert vibrate with 10th seconds, 20th seconds, 30th seconds....
How can I do that ?
Thanks for reading
Here's a simple static method that uses a Timer to accomplish this. You pass in the amount of times to vibrate and the period between vibrations. The phone will vibrate for 100ms every repeatPeriodSeconds for repeatCount times.
public static void repeatVibrate(final int repeatCount, int repeatPeriodSeconds)
{
TimerTask task = new TimerTask()
{
private int repeats = 0;
#Override
public void run()
{
++repeats;
Alert.startVibrate(100);
if(repeats >= repeatCount)
{
cancel();
}
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(task, 0, repeatPeriodSeconds * 1000L);
}
Here's the documentation of the relevant classes: Alert, Timer, TimerTask
This helps you:
public class LoadingScreen extends MainScreen
{
Timer timer;
TimerTask timerTask;
public LoadingScreen()
{
setTitle("Loading Screen");
callTheTimer();
}
public void callTheTimer()
{
timer=new Timer();
timerTask=new TimerTask()
{
public void run()
{
Alert.startVibrate(500);
}
};
timer.scheduleAtFixedRate(timerTask, 0, 3000);//For 10 secs give 10000; I am testing this for every 3 secs;
}
}
Before push new screen or closing the current screen give timertask.cancel();
I've add timer to display images in my app.
is there any way to check the timer is running or not.?
after checking , the timer should be cancel using timer.cancel() method.
Pls hlp me.
Blackberry's Timer is very cheesy - it's just like a Runnable with Thread.sleep() inside. Very commonly for Blackberry, it contains lot of crap you don't actually need and doesn't contain things you do need.
I would dump the Timer and make a class specially for my needs:
abstract public class MyTimer extends Thread {
private final Object waitobj = new Object();
private volatile boolean running;
private volatile boolean canceled;
private final long due;
public MyTimer setDelay(long delay) {
long cur = System.currentTimeMillis();
due = cur + delay;
return this;
}
public MyTimer setAlarmTime(long dueTimeMillis) {
due = dueTimeMillis;
return this;
}
synchronized void setIsRunning(boolean running) {
this.running = running;
}
synchronized public boolean isRunning() {
return running;
}
synchronized public void cancel() {
synchronized (waitobj) {
canceled = true;
waitobj.notify();
}
}
public void run() {
setIsRunning(true);
long cur = System.currentTimeMillis();
long sleep = due - cur;
while (sleep > 0) {
synchronized (waitobj) {
waitobj.wait(sleep);
}
if (isCanceled()) return;
cur = System.currentTimeMillis();
sleep = due - cur;
}
alarm();
setIsRunning(false);
}
private boolean isCanceled() {
return canceled;
}
abstract void alarm();
}
Then I would invoke it like this:
timer = new MyTimer() {
void alarm() {
// do cool things
}
};
timer.setDelay(10000).start();
If I need to cancel it I would do it like this:
if (timer.isRunning()) {
timer.cancel();
}
or simply
timer.cancel();
PS: Note volatile and synchronized things in MyTimer class.
You can manage this yourself by recording the timers unique integer and use it later to cancel. I find a useful place to set/cancel this is in the onVisibilityChanged(boolean) override. I'm assuming here your timed images are for animation.
// start
if (renderLoop==-1) renderLoop = UiApplication.getUiApplication().invokeLater( this, 50, true );
// stop
if (renderLoop!=-1)
{
UiApplication.getUiApplication().cancelInvokeLater( renderLoop );
renderLoop = -1;
}
//assumes your screen implements Runnable
public void run() {
// do something cool
}
Assuming that you're programming in Java with Swing, you have a method called isRunning() within the Timer Class.
http://download.oracle.com/javase/7/docs/api/javax/swing/Timer.html#isRunning%28%29
Regards
I have a BlackBerry application that needs to take pictures from the camera and send them to a server. In order to do this i invoke the native camera application and listen to the filesystem. Once an image is captured and saved as a new jpeg file i get notified, resume foreground control and go about my business. The problem starts occurring after the first time this cycle is completed because now when i decide to call the camera application again it is already opened, and now the user is seeing a thumbnail of the last picture that was taken and several buttons allowing him to manipulate/manage it. naturally what i want the user to see is a preview of what the camera is "seeing" before he snaps another photo as he did before.
I have thought of various ways to solve this including killing the camera app each time (I understand this cannot be done programatically?), sending CameraArguments when invoking the app (which appears to be useless), and now i was thinking a solution could be as simple generating a "Back" key event before switching back to my app which would theoretically dismiss the annoying edit screen. Could this really be done? and if not is there any other possible solution you may think of?
A kind of hack...
start Camera App
in TimerTask check if Camera App started and if it need to be closed (some flag)
if yes, invoke it(so it will became active) and push ESC keypress event injection to close it
Take a look at this:
class Scr extends MainScreen {
boolean killCameraApp = false;
final String mCameraModuleName = "net_rim_bb_camera";
final CameraArguments args = new CameraArguments();
public Scr() {
super();
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
if (isCameraRunning() && killCameraApp) {
getApplication().invokeAndWait(callCamera);
getApplication().invokeAndWait(killCamera);
}
}
}, 0, 100);
}
Runnable callCamera = new Runnable() {
public void run() {
callCamera();
}
};
Runnable killCamera = new Runnable() {
public void run() {
injectKey(Characters.ESCAPE);
killCameraApp = false;
}
};
private boolean isCameraRunning() {
boolean result = false;
ApplicationManager appMan =
ApplicationManager.getApplicationManager();
ApplicationDescriptor[] appDes = appMan.getVisibleApplications();
for (int i = 0; i < appDes.length; i++) {
result = mCameraModuleName.equalsIgnoreCase(appDes[i]
.getModuleName());
if (result)
break;
}
return result;
}
private void callCamera() {
Invoke.invokeApplication(Invoke.APP_TYPE_CAMERA,
new CameraArguments());
}
private void injectKey(char key) {
KeyEvent inject = new KeyEvent(KeyEvent.KEY_DOWN, key, 0);
inject.post();
}
protected void makeMenu(Menu menu, int instance) {
menu.add(new MenuItem("start camera", 0, 0) {
public void run() {
callCamera();
killCameraApp = false;
}
});
menu.add(new MenuItem("kill app", 0, 0) {
public void run() {
killCameraApp = true;
}
});
super.makeMenu(menu, instance);
}
}
EDIT: Don't forget to set permissions for device release:
Options => Advanced Options => Applications => [Your Application] =>Edit Default permissions =>Interactions =>key stroke Injection