I want the timer to continue when the app is pushed to the Background.
It seems the Timer pauses and resumes when the app is brought back to the forground.
_timer = new System.Timers.Timer();
_timer.Interval = 30000;
_timer.Elapsed += OnTimedEvent;
_timer.Enabled = true;
private void OnTimedEvent(object sender, System.Timers.ElapsedEventArgs e)
{
AutoSaveMethod();
}
Goal is to measure the reaction time of the user. 3-10 seconds after clicking the start button it should start the stopwatch and make the stop button visible. After the user clicks the stop button, it should stop the watch and display the milliseconds the user took to respond.
I am having trouble coming up with a solution as to how to implement a loop that would check if the button has been pressed and to stop the watch without blocking the user from clicking the button.
public partial class Main : ContentPage
{
public Main()
{
InitializeComponent();
}
public void OnStartClicked(object sender,EventArgs args)
{
Stopwatch stopWatch = new Stopwatch();
startButton.IsVisible = false;
BG.BackgroundColor = Color.Red;
status_text.Text = "Get Ready";
Random R = new Random();
Device.StartTimer(TimeSpan.FromSeconds(R.Next(3, 10)), () =>
{
stopWatch.Start();
stopButton.IsVisible = true;
BG.BackgroundColor = Color.Green;
long elapsed = stopWatch.ElapsedMilliseconds;
stopWatch.Stop();
status_text.Text = elapsed.ToString();
return false;
});
}
}}
Use the StopWatch as a member Variable and stop the watch in an OnStopClicked-Event. Read the elapsed time after stopping. Instead of button.IsVisible you could also use button.IsEnabled.
public partial class MainPage : ContentPage
{
Stopwatch mStopWatch = new Stopwatch();
public MainPage()
{
InitializeComponent();
}
private void StartButton_Clicked(object sender, EventArgs e)
{
startButton.IsVisible = false;
BG.BackgroundColor = Color.Red;
status_text.Text = "Get Ready";
Random R = new Random();
Device.StartTimer(TimeSpan.FromSeconds(R.Next(3, 10)), () =>
{
mStopWatch.Start();
stopButton.IsVisible = true;
BG.BackgroundColor = Color.Green;
return false;
});
}
private void StopButton_Clicked(object sender, EventArgs e)
{
mStopWatch.Stop();
long elapsed = mStopWatch.ElapsedMilliseconds;
status_text.Text = elapsed.ToString();
mStopWatch.Reset();
stopButton.IsVisible = false;
startButton.IsVisible = true;
}
}
I've been playing with the new Remote Wiring libraries on Windows Remote Arduino and I have been unable to control a servo - there is a "PinMode.Servo" option in the library - but the motor does not move reliably, sometimes not at all.
The code is below
namespace UniversalBlink
{
public sealed partial class MainPage : Page
{
private bool useBluetooth = true;
BluetoothSerial bluetooth;
UsbSerial usb;
RemoteDevice arduino;
public MainPage()
{
this.InitializeComponent();
if (useBluetooth)
{
bluetooth = new BluetoothSerial("HC-06");
arduino = new RemoteDevice(bluetooth);
bluetooth.ConnectionEstablished += OnConnectionEstablished;
//these parameters don't matter for bluetooth
bluetooth.begin(0, 0);
}
else
{
usb = new UsbSerial("VID_2341", "PID_0043"); //I've written in my device D directly
var test = UsbSerial.listAvailableDevicesAsync();
arduino = new RemoteDevice(usb);
usb.ConnectionEstablished += OnConnectionEstablished;
usb.begin(57600, SerialConfig.SERIAL_8N1);
}
}
private void OnConnectionEstablished()
{
//enable the buttons on the UI thread!
var action = Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, new Windows.UI.Core.DispatchedHandler(() => {
OnButton.IsEnabled = true;
OffButton.IsEnabled = true;
arduino.pinMode(9, PinMode.SERVO);
}));
}
private async void OnButton_Click(object sender, RoutedEventArgs e)
{
arduino.analogWrite(9, 0);
}
private async void OffButton_Click(object sender, RoutedEventArgs e)
{
arduino.analogWrite(9, 140);
}
}
}
I'm at a loss as to where to go from here.
The Code use Bluetooth or Serial (via USB) to control an Arduino.
I need to grow the size of my Application.Current.MainWindow (when running OOB, of course).
Is there any way to do it in a Storyboard?
I can do it programatically:
private long timerCntr = 0;
private void OpenBtn_OnClick(object sender, RoutedEventArgs e)
{
timerCntr = 0;
DispatcherTimer t = new DispatcherTimer();
t.Interval = new TimeSpan(0, 0, 0, 0, 10);
t.Tick += (o, args) =>
{
if (timerCntr < 100)
{
Application.Current.MainWindow.Height += 1;
userControl.Height += 1;
LayoutRoot.Height += 1;
++timerCntr;
}
else
{
t.Stop();
}
};
t.Start();
OpenStory.Begin(); // Controls opacity of object becoming visible
}
Thanks for any insights...
The link in comments provided the answer.
Basically, add a hidden slider control; change the slider's value in a storyboard; in the slider's value_changed handler change the window size.
Works great.
Is there a way to show "Loading" screen with animation in blackberry?
Options:
PME animation content
multithreading + set of images + timer/counter
standard rim api
some other way
Any of this?
Thanks!
Fermin, Anthony +1. Thanks to all, you gave me the part of answer.
My final solution:
1.Create or generate (free Ajax loading gif generator) animation and add it to project.
2.Create ResponseCallback interface (see Coderholic - Blackberry WebBitmapField) to receive thread execution result:
public interface ResponseCallback {
public void callback(String data);
}
3.Create a class to handle your background thread job. In my case it was http request:
public class HttpConnector
{
static public void HttpGetStream(final String fileToGet,
final ResponseCallback msgs) {
Thread t = new Thread(new Runnable() {
public void run() {
HttpConnection hc = null;
DataInputStream din = null;
try {
hc = (HttpConnection) Connector.open("http://" + fileToGet);
hc.setRequestMethod(HttpsConnection.GET);
din = hc.openDataInputStream();
ByteVector bv = new ByteVector();
int i = din.read();
while (-1 != i) {
bv.addElement((byte) i);
i = din.read();
}
final String response = new String(bv.toArray(), "UTF-8");
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
msgs.callback(response);
}
});
}
catch (final Exception e) {
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
msgs.callback("Exception (" + e.getClass() + "): "
+ e.getMessage());
}
});
}
finally {
try {
din.close();
din = null;
hc.close();
hc = null;
}
catch (Exception e) {
}
}
}
});
t.start();
}
}
4.Create WaitScreen (a hybrid of FullScreen and AnimatedGIFField with ResponseCallback interface):
public class WaitScreen extends FullScreen implements ResponseCallback
{
StartScreen startScreen;
private GIFEncodedImage _image;
private int _currentFrame;
private int _width, _height, _xPos, _yPos;
private AnimatorThread _animatorThread;
public WaitScreen(StartScreen startScreen) {
super(new VerticalFieldManager(), Field.NON_FOCUSABLE);
setBackground(
BackgroundFactory.createSolidTransparentBackground(
Color.WHITE, 100));
this.startScreen = startScreen;
EncodedImage encImg =
GIFEncodedImage.getEncodedImageResource("ajax-loader.gif");
GIFEncodedImage img = (GIFEncodedImage) encImg;
// Store the image and it's dimensions.
_image = img;
_width = img.getWidth();
_height = img.getHeight();
_xPos = (Display.getWidth() - _width) >> 1;
_yPos = (Display.getHeight() - _height) >> 1;
// Start the animation thread.
_animatorThread = new AnimatorThread(this);
_animatorThread.start();
UiApplication.getUiApplication().pushScreen(this);
}
protected void paint(Graphics graphics) {
super.paint(graphics);
// Draw the animation frame.
graphics
.drawImage(_xPos, _yPos, _image
.getFrameWidth(_currentFrame), _image
.getFrameHeight(_currentFrame), _image,
_currentFrame, 0, 0);
}
protected void onUndisplay() {
_animatorThread.stop();
}
private class AnimatorThread extends Thread {
private WaitScreen _theField;
private boolean _keepGoing = true;
private int _totalFrames, _loopCount, _totalLoops;
public AnimatorThread(WaitScreen _theScreen) {
_theField = _theScreen;
_totalFrames = _image.getFrameCount();
_totalLoops = _image.getIterations();
}
public synchronized void stop() {
_keepGoing = false;
}
public void run() {
while (_keepGoing) {
// Invalidate the field so that it is redrawn.
UiApplication.getUiApplication().invokeAndWait(
new Runnable() {
public void run() {
_theField.invalidate();
}
});
try {
// Sleep for the current frame delay before
// the next frame is drawn.
sleep(_image.getFrameDelay(_currentFrame) * 10);
} catch (InterruptedException iex) {
} // Couldn't sleep.
// Increment the frame.
++_currentFrame;
if (_currentFrame == _totalFrames) {
// Reset back to frame 0
// if we have reached the end.
_currentFrame = 0;
++_loopCount;
// Check if the animation should continue.
if (_loopCount == _totalLoops) {
_keepGoing = false;
}
}
}
}
}
public void callback(String data) {
startScreen.updateScreen(data);
UiApplication.getUiApplication().popScreen(this);
}
}
5.In the end, create Start screen to call HttpConnector.HttpGetStream and to show WaitScreen:
public class StartScreen extends MainScreen
{
public RichTextField text;
WaitScreen msgs;
public StartScreen() {
text = new RichTextField();
this.add(text);
}
protected void makeMenu(Menu menu, int instance) {
menu.add(runWait);
super.makeMenu(menu, instance);
}
MenuItem runWait = new MenuItem("wait", 1, 1) {
public void run() {
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
getFile();
}
});
}
};
public void getFile() {
msgs = new WaitScreen(this);
HttpConnector.HttpGetStream(
"stackoverflow.com/faq", msgs);
}
//you should implement this method to use callback data on the screen.
public void updateScreen(String data)
{
text.setText(data);
}
}
UPDATE: another solution naviina.eu: A Web2.0/Ajax-style loading popup in a native BlackBerry application
The basic pattern for this kind of thing is:
Have a thread running a loop that updates a variable (such as the frame index of the animated image) and then calls invalidate on a Field which draws the image (and then sleeps for a period of time). The invalidate will queue a repaint of the field.
In the field's paint method, read the variable and draw the appropriate frame of the image.
Pseudo code (not totally complete, but to give you the idea):
public class AnimatedImageField extends Field implements Runnable {
private int currentFrame;
private Bitmap[] animationFrames;
public void run() {
while(true) {
currentFrame = (currentFrame + 1) % animationFrames.length;
invalidate();
Thread.sleep(100);
}
}
protected void paint(Graphics g) {
g.drawBitmap(0, 0, imageWidth, imageHeight, animationFrames[currentFrame], 0, 0);
}
}
Note also here I used an array of Bitmaps, but EncodedImage lets you treat an animated gif as one object, and includes methods to get specific frames.
EDIT: For completeness: Add this to a PopupScreen (as in Fermin's answer) or create your own dialog by overriding Screen directly. The separate thread is necessary because the RIM API is not thread-safe: you need to do everything UI related on the event thread (or while holding the event lock, see BlackBerry UI Threading - The Very Basics
This is simple code for loading screen ....
HorizontalFieldManager popHF = new HorizontalFieldManager();
popHF.add(new CustomLabelField("Pls wait..."));
final PopupScreen waitScreen = new PopupScreen(popHF);
new Thread()
{
public void run()
{
synchronized (UiApplication.getEventLock())
{
UiApplication.getUiApplication().pushScreen(waitScreen);
}
//Here Some Network Call
synchronized (UiApplication.getEventLock())
{
UiApplication.getUiApplication().popScreen(waitScreen);
}
}
}.start();
If it's just an animation could you show an animated gif on a popup and close it when loading operation is complete?
Easiest way is probably to use the standard GaugeField, setting style GaugeField.PERCENT. This will give you a progress bar. Add this to a PopupScreen and it will sit on top of your content. Something like..
private GaugeField _gaugeField;
private PopupScreen _popup;
public ProgressBar() {
DialogFieldManager manager = new DialogFieldManager();
_popup = new PopupScreen(manager);
_gaugeField = new GaugeField(null, 0, 100, 0, GaugeField.PERCENT);
manager.addCustomField(_gaugeField);
}
Then have an update method which will use _gaugeField.setValue(newValue); to update the progress bar.
I normally have this called from whichever thread is doing the work (loading in your case, everytime an operation is complete the progress bar is updated.
I would suggest to take a look at this simple implementation. I liked this but never used it. May be helpful to you.
link text
ActivityIndicator is a good option if you are working with at least BB OS 6.0.
http://www.brighthub.com/mobile/blackberry-platform/articles/94258.aspx
http://docs.blackberry.com/en/developers/deliverables/17966/Screen_APIs_1245069_11.jsp