I am loading images in PictureScrollField from the server and want that until images are loaded from server, the PictureScrollField shows a blank image and when the image loads in image array, it repaints (redraw) the PictureScrollField like a ListField.
I read from BlackBerry documentation that every field can be invalidated (that is, we can repaint it) but when I use the PictureScrollField.invalidate() method in my program, I get an error :
The method invalidate from the type Field is not visible
The program I use is listed below
public final class GetMoreImage extends MainScreen {
public static PictureScrollField psf;
int size;
int length;
String text=null;
EncodedImage[] encodedImage;
VerticalFieldManager vmanger;
private LoadImages loadImages;
public GetMoreImage(int index) {
super(NO_VERTICAL_SCROLL | NO_VERTICAL_SCROLLBAR);
this.size=index;
try {
length=ListHome.object[size].getJSONArray("UrlArray").length();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ScrollEntry[] entries = new ScrollEntry[length];
for (int i = 0; i < length; i++) {
if(encodedImage != null && encodedImage.length > i && encodedImage[i] != null) {
EncodedImage encodedImg =ListHome.sizeImage(JPEGEncodedImage.encode(Bitmap.getBitmapResource("icon.png"),80),640,380);
Bitmap bmp=encodedImg.getBitmap();
entries[i] = new ScrollEntry(bmp, "hello", "");
}
else {
try {
text=ListHome.object[size].getJSONArray("UrlArray").getString(i).toString();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
EncodedImage encodedImg =ListHome.sizeImage(JPEGEncodedImage.encode(connectServerForImage(text),80),640,380);
Bitmap bmp=encodedImg.getBitmap();
entries[i] = new ScrollEntry(bmp, "hello", "");
}
}
psf = new PictureScrollField();
psf.setData(entries, 0);
psf.setHighlightStyle(HighlightStyle.ILLUMINATE_WITH_SHRINK_LENS);
add(psf);
loadImages = new LoadImages(80, 80);
loadImages.start();
}
private class LoadImages extends Thread {
int widthL;
int heightL;
LoadImages(int width, int height) {
this.widthL = width;
this.heightL = height;
}
public void run() {
encodedImage=new EncodedImage[length];
if (ListHome.object[size] != null) {
for (int i = 0; i < length; i++) {
try {
String text=ListHome.object[size].getJSONArray("UrlArray").getString(i).toString();
EncodedImage encodedImg = JPEGEncodedImage.encode(connectServerForImage(text), 80);//Get Image from Server
encodedImage[i] = ListHome.sizeImage(encodedImg, Display.getWidth(), Display.getHeight()-100);
psf.invalidate();//This Line generate error
} catch (Exception e)
{
e.printStackTrace();
}
}
} else {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert("No Data Found");
}
});
}
}
}
}
Any help will be appreciated.
Thanks
The reason you get a compile error on this line:
psf.invalidate();//This Line generate error
is because the PictureScrollField#invalidate() method is protected, not public. So, code not in PictureScrollField or a class that extends PictureScrollField cannot use it directly.
However, you don't need to use invalidate(). invalidate() is a low-level method that instructs a field to repaint. However, PictureScrollField has a higher-level method that is designed to allow you to change images, and have the field (re)draw them: PictureScrollField#setData().
Because that method is changing the user interface (UI), it should be run on the UI/main thread. This will not automatically happen if you make the call inside the run() method you are using to download the images. So, you'll need something like this inside your LoadImages class:
public void run() {
encodedImage=new EncodedImage[length];
if (ListHome.object[size] != null) {
for (int i = 0; i < length; i++) {
try {
String text=ListHome.object[size].getJSONArray("UrlArray").getString(i).toString();
EncodedImage encodedImg = JPEGEncodedImage.encode(connectServerForImage(text), 80);//Get Image from Server
encodedImage[i] = ListHome.sizeImage(encodedImg, Display.getWidth(), Display.getHeight()-100);
//psf.invalidate();//This Line generate error
entries[i] = new ScrollEntry(encodedImage[i].getBitmap(), "label", "callout");
// we must update the scroll entries on the UI/main thread:
UiApplication.getUiApplication().invokeLater(new Runnable() {
// setting the field to index 'i' will scroll to the image
// that was just downloaded
psf.setData(entries, i);
});
} catch (Exception e)
{
e.printStackTrace();
}
}
}
In order to make this work, you must change the local entries variable to a member variable in your GetMoreImage class:
public final class GetMoreImage extends MainScreen {
public static PictureScrollField psf;
private ScrollEntry[] entries;
but, you can still instantiate it (entries = new ScrollEntry[length];) in your screen's constructor, or whenever you know the correct length.
Related
Consider:
namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//int[] val = { 0, 0};
int val;
if (textBox1.Text == "")
{
MessageBox.Show("Input any no");
}
else
{
val = Convert.ToInt32(textBox1.Text);
Thread ot1 = new Thread(new ParameterizedThreadStart(SumData));
ot1.Start(val);
}
}
private static void ReadData(object state)
{
System.Windows.Forms.Application.Run();
}
void setTextboxText(int result)
{
if (this.InvokeRequired)
{
this.Invoke(new IntDelegate(SetTextboxTextSafe), new object[] { result });
}
else
{
SetTextboxTextSafe(result);
}
}
void SetTextboxTextSafe(int result)
{
label1.Text = result.ToString();
}
private static void SumData(object state)
{
int result;
//int[] icount = (int[])state;
int icount = (int)state;
for (int i = icount; i > 0; i--)
{
result += i;
System.Threading.Thread.Sleep(1000);
}
setTextboxText(result);
}
delegate void IntDelegate(int result);
private void button2_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
Why is this error occurring?
An object reference is required for the nonstatic field, method, or property 'WindowsApplication1.Form1.setTextboxText(int)
It looks like you are calling a non static member (a property or method, specifically setTextboxText) from a static method (specifically SumData). You will need to either:
Make the called member static also:
static void setTextboxText(int result)
{
// Write static logic for setTextboxText.
// This may require a static singleton instance of Form1.
}
Create an instance of Form1 within the calling method:
private static void SumData(object state)
{
int result = 0;
//int[] icount = (int[])state;
int icount = (int)state;
for (int i = icount; i > 0; i--)
{
result += i;
System.Threading.Thread.Sleep(1000);
}
Form1 frm1 = new Form1();
frm1.setTextboxText(result);
}
Passing in an instance of Form1 would be an option also.
Make the calling method a non-static instance method (of Form1):
private void SumData(object state)
{
int result = 0;
//int[] icount = (int[])state;
int icount = (int)state;
for (int i = icount; i > 0; i--)
{
result += i;
System.Threading.Thread.Sleep(1000);
}
setTextboxText(result);
}
More info about this error can be found on MSDN.
For this case, where you want to get a Control of a Form and are receiving this error, then I have a little bypass for you.
Go to your Program.cs and change
Application.Run(new Form1());
to
public static Form1 form1 = new Form1(); // Place this var out of the constructor
Application.Run(form1);
Now you can access a control with
Program.form1.<Your control>
Also: Don't forget to set your Control-Access-Level to Public.
And yes I know, this answer does not fit to the question caller, but it fits to googlers who have this specific issue with controls.
You start a thread which runs the static method SumData. However, SumData calls SetTextboxText which isn't static. Thus you need an instance of your form to call SetTextboxText.
Your method must be static
static void setTextboxText(int result)
{
if (this.InvokeRequired)
{
this.Invoke(new IntDelegate(SetTextboxTextSafe), new object[] { result });
}
else
{
SetTextboxTextSafe(result);
}
}
Credit to #COOLGAMETUBE for tipping me off to what ended up working for me. His idea was good but I had a problem when Application.SetCompatibleTextRenderingDefault was called after the form was already created. So with a little change, this is working for me:
static class Program
{
public static Form1 form1; // = new Form1(); // Place this var out of the constructor
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(form1 = new Form1());
}
}
I actually got this error because I was checking InnerHtml for some content that was generated dynamically - i.e. a control that is runat=server.
To solve this I had to remove the "static" keyword on my method, and it ran fine.
From my looking you give a null value to a textbox and return in a ToString() as it is a static method. You can replace it with Convert.ToString() that can enable null value.
Make the function static. This must solve your problem.
The essence, and solution, to your problem is this:
using System;
namespace myNameSpace
{
class Program
{
private void method()
{
Console.WriteLine("Hello World!");
}
static void Main(string[] args)
{
method();//<-- Compile Time error because an instantiation of the Program class doesnt exist
Program p = new Program();
p.method();//Now it works. (You could also make method() static to get it to work)
}
}
}
i'm creating one application in which i get gift images with id's from web server through JSON. When i click on any gift image, it goes on next page where it shows all information of that image (get image information with its id from web server through JSON).
Problem is: When i click on any gift image on page to see its relevant information, it gets the last gift image id every time, i want when i click on any image, it gets the specific image id which i click. How it is possible??
Screenshot of the page is : http://ugo.offroadstudios.com/gifts.png
Here is sample code:
public class Gifts extends MainScreen {
String giftsid;
BitmapField giftimg;
public Gifts(){
setTitle("Gift Store");
creategifts();
}
public void creategifts()
{
//Link URL
String strURL = "http://ugo.offroadstudios.com/api/frndgift/?loginusername=adil;deviceside=true";
webConnection wb = new webConnection();
String res = wb.getJson(strURL);
try {
JSONObject object = new JSONObject(res);
if(object.getString("status") == "error")
{
Dialog.alert("Invalid "+object.getString("status"));
}
else
{
int totalgifts;
totalgifts = object.getInt("totalgifts");
Bitmap listThumb;
JSONArray imagearr;
JSONArray giftsidarr;
String imgname;
Bitmap bmpResized;
for(int i=0; i < totalgifts; i++){
imagearr = object.getJSONArray("gifts_image");
imgname = imagearr.getString(i);
giftsidarr = object.getJSONArray("gifts_id");
giftsid = giftsidarr.getString(i);
listThumb = getImage.getImageFromUrl("http://ugo.offroadstudios.com/wp-content/plugins/bp-gifts-rebirth/includes/images/"+imgname+";deviceside=true");
bmpResized = GPATools.ResizeTransparentBitmap(listThumb, 80, 80,
Bitmap.FILTER_LANCZOS, Bitmap.SCALE_TO_FIT);
giftimg =new BitmapField(bmpResized,FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
Dialog.alert("giftsid "+giftsid);
UiApplication.getUiApplication().pushScreen(new SendGift(giftsid));
return true;
}
};
add(giftimg);
}
}
}
catch (JSONException e) {
System.out.println("EX is "+e);
e.printStackTrace();
}
}
}
You are always getting the gift id of the last gift in the list because you have created your buttons with this code:
giftimg =new BitmapField(bmpResized,FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
Dialog.alert("giftsid "+giftsid);
UiApplication.getUiApplication().pushScreen(new SendGift(giftsid));
return true;
}
};
Your navigationClick() method used the giftsid variable, which is a persistent member variable of your class. You assign this variable in your for loop, so the final value it keeps is the last value assigned in the loop (giftsidarr.getString(totalgifts)).
Although you declare the navigationClick() method in a loop where the giftsid is many different values, the navigationClick() method uses the value of giftsid when it is run. The last value.
There's many ways to fix it. You can use a separate constant value in your loop:
final String nextGiftsId = giftsid;
giftimg =new BitmapField(bmpResized,FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
Dialog.alert("nextGiftsId= "+nextGiftsId);
UiApplication.getUiApplication().pushScreen(new SendGift(nextGiftsId));
return true;
}
};
Or, as Signare suggested, attach a cookie to each button that identifies its corresponding gift:
giftimg =new BitmapField(bmpResized,FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
String giftId = (String)getCookie(); // read gift id from the cookie
Dialog.alert("giftId= "+giftId);
UiApplication.getUiApplication().pushScreen(new SendGift(giftId));
return true;
}
};
giftimg.setCookie(giftsid); // set the cookie after creating the field
Inside your for loop, add the following code -
giftimg[i].setChangeListener(this);
Then -
public void fieldChanged(Field field, int context) {
for(int i=0;i<totalgifts;i++) {
if(field == giftimg[i]) {
// you can trigger your event
}
}
EDIT :-
giftimg[i].setChangeListener(listener);
listener = new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
if ( field instanceof BitmapField ) {
for(int i=0;i<totalgifts;i++) {
if ( field == giftimg[i] ) {
// you can trigger your event
}
}
}
}
};
I am new to BlackBerry development. But good about android.
I want to load Images coming from the server in ListField.
I have implement like below code but not getting success:
package mypackage;
public class TempScreen extends MainScreen implements ListFieldCallback{
Bitmap[] images=null;
private ListField mylist;
private static Bitmap _bitmap;
private ImageDownloader downloader;
int size = 0;
String[] urls={
"http://www.kentnews.co.uk/polopoly_fs/damian_lewis_at_port_lympne_wild_animal_park_c_taf_1_1738362!image/2626063106.jpg_gen/derivatives/landscape_225/2626063106.jpg",
"http://www.kentnews.co.uk/polopoly_fs/damian_lewis_at_port_lympne_wild_animal_park_c_taf_1_1738362!image/2626063106.jpg_gen/derivatives/landscape_225/2626063106.jpg",
"http://www.kentnews.co.uk/polopoly_fs/damian_lewis_at_port_lympne_wild_animal_park_c_taf_1_1738362!image/2626063106.jpg_gen/derivatives/landscape_225/2626063106.jpg",
"http://www.kentnews.co.uk/polopoly_fs/damian_lewis_at_port_lympne_wild_animal_park_c_taf_1_1738362!image/2626063106.jpg_gen/derivatives/landscape_225/2626063106.jpg"};
public TempScreen()
{
images=new Bitmap[urls.length];
size = urls.length;
mylist = new ListField();
mylist.setCallback(this);
mylist.setSize(4);
mylist.setRowHeight(getFont().getHeight() * 3);
add(mylist);
Thread downloader=new Thread(new ImageDownloader());
downloader.start();
}
public void drawListRow(ListField listField, Graphics graphics, int index,
int y, int width) {
if(images[index]==null)
{
//Load placeholder image
_bitmap = Bitmap.getBitmapResource("close_btn.png");// load some bitmap
// of your choice
// here
}
else
//Load Bitmap
_bitmap = images[index];
graphics.drawText("row details", 100, y + 30);
//graphics.drawBitmap(0, y, _bitmap.getWidth(), _bitmap.getHeight(),_bitmap, 0, 0);
mylist.invalidate(index);
}
public class ImageDownloader implements Runnable
{
public void run()
{
for(int i=0; i<size;i++)
{
if(images[i]==null)
{
images[i]=connectServerForImage(urls[i].toString());//replace downloadImage method to whatever method you have to download the bitmap from url
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run()
{
mylist.invalidate();
}
});
}
}
}
}
public Object get(ListField listField, int index) {
// TODO Auto-generated method stub
return null;
}
public int getPreferredWidth(ListField listField) {
// TODO Auto-generated method stub
return 0;
}
public int indexOfList(ListField listField, String prefix, int start) {
// TODO Auto-generated method stub
return 0;
}
public static Bitmap connectServerForImage(String url) {
HttpConnection httpConnection = null;
DataOutputStream httpDataOutput = null;
InputStream httpInput = null;
int rc;
Bitmap bitmp = null;
try {
// httpConnection = (HttpConnection)
// Connector.open(url+";interface=wifi");
httpConnection = (HttpConnection) Connector.open(url);
rc = httpConnection.getResponseCode();
// System.out.println("===============================");
Dialog.alert("beore if condition");
if (rc == HttpConnection.HTTP_OK) {
System.out.println(" ============= IN FUNCTION. . . . .");
httpInput = httpConnection.openInputStream();
InputStream inp = httpInput;
byte[] b = IOUtilities.streamToBytes(inp);
EncodedImage hai = EncodedImage.createEncodedImage(b, 0,
b.length);
bitmp = hai.getBitmap();
} else {
throw new IOException("HTTP response code: " + rc);
}
} catch (Exception ex) {
System.out.println("URL Bitmap Error........" + ex.getMessage());
} finally {
try {
if (httpInput != null)
httpInput.close();
if (httpDataOutput != null)
httpDataOutput.close();
if (httpConnection != null)
httpConnection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return bitmp;
}
}
Dont know where i am wrong. Please can any budy help me for the same.
Several problems with your code:
The BitmapLazyLoader class looks like a consumer. It holds a Thread reference. This alone is very confusing, since Runnables are intended to be passed to a Thread constructor, but Runnables should not know about the thread for the sake of encapsulation. Letting this apart, this class attempts to spawn a thread only once, but as you are creating an instance of Runnable each time a row is drawn, you'll end up spawning a considerable number of threads. This will probably end in a TooManyThreadsException being thrown as in BlackBerry the max number of threads is limited to 16 per app. Even if you don reach the limit, performance will degrade as BlackBerries, which sport a single core CPU, you shouldn't have more than 2-3 threads running at the same time. EVEN if you could spawn infinite threads, in BlackBerry you can only have X connections opened at the same time (I think X is 5 for the whole OS, not sure about this). So first of all modify the code to ensure only a single worker thread is downloading images. (and if possible, extract the thread instantiation and launch out of the Runnable class).
When the bitmap is downloaded, you are not doing anything with it. Look at the ImageDownloadCompleted method, it is empty. (BTW, the convention for methods is to start with lowercase) So you should store the bitmap somewhere and call invalidate on your list, which in turn will paint the stored bitmaps.
Hope it helps.
You can try using this link :
http://www.coderholic.com/blackberry-webbitmapfield/
You have to create a separate class named as WebBitmapField as suggested in above link.
How to use that class in your list field image objects:
For every image url create WebBitmapField object
photoList_vector is the vector through which populate elements in
list field
WebBitmapField web = new WebBitmapField("http://www.image1.png");
photoList_vector.addElement(web);
web = new WebBitmapField("http://www.image2.png");
photoList_vector.addElement(web);
Now use this vector to work on your list field......
In the above lines we try to ensure that when we simultaneously send multiple requests to get the images then each image corresponds to a particular WebBitmapField Object.
Each object is then added to vector so that it can be added to the list field.
Each url send is tied to an object of WebBitmapField.
So though request is send in a separate thread it gets tied to its associated object only
Hope it helps
:)
I have worked on this problem, earlier, and I am posting my technique here, though its not ideal solution, as it was coupled very much with Screen class, but still might be helpful.
First in your screen class have one array for bitmaps having size equal to list field items.
public class TempScreen extends MainScreen{
Bitmap[] images=null;
String[] urls={"image1_url", "image2_url".....};
public TempScreen()
{
images=new Bitmap[urls.length];
}
now in drawListRow method of ListFieldCallBack, check for the following:
public void drawListRow(ListField list, Graphics g, int index, int y, int width){
if(bitmap[index]==null)
{
//Load placeholder image
}
else
//Load Bitmap
}
Now create a thread class to download the images:
public class ImageDownloader implements Runnable
{
public void run()
{
for(int i=0; i<size;i++)
{
if(images[i]==null)
{
images[i]=downloadImage(url[i]);//replace downloadImage method to whatever method you have to download the bitmap from url
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run()
{
list.invalidate()
}
});
}
}
}
}
Now in constructor of the screen class, after setting callback to listfield, start thread:
Thread downloader=new Thread(new ImageDownloader());
downloader.start();
Edit: Change TempScreen constructor to following:
public TempScreen()
{
images=new Bitmap[urls.length];
size = urls.length;
mylist = new ListField();
mylist.setCallback(this);
mylist.setSize(4);
mylist.setRowHeight(getFont().getHeight() * 3);
add(mylist);
Thread downloader=new Thread(new ImageDownloader());
downloader.start();
}
I am trying to download xml files from server when my application starts. So i want to show splash screen until am done with downloading and then show next screen. below is my code:
Here, i want to show My splash screen when getTopNotDoc() method is under execution. and after completion of that method show next screen.
//get _topics and notification document<br>
_getDoc = new ServerConnectivity(this);
public class ServerConnectivity {
private Document _questionDoc;
private Document _topics;
private Document _notifications;
public ServerConnectivity(ApplicationSession appSession){
//getTopNotDoc();
_this = this;
_appSession = appSession;
new Thread(new Runnable(){
public void run(){
getTopNotDoc();
}
}).start();
}
}
private void getTopNotDoc(){
InputStream inputStream = null ;
try{
// Build a document based on the XML file.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
inputStream = getClass().getResourceAsStream("topics.xml");
_topics = builder.parse( inputStream );
inputStream = getClass().getResourceAsStream("notification.xml");
_notifications = builder.parse( inputStream );
if(_topics == null || _notifications == null){
Dialog.alert("Unable to connect to internet");
}
}
catch ( Exception e ){
System.out.println( e.toString() );
}
finally{
if(inputStream != null){
try {
inputStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
Usually when I do this, I create a loading screen, then I just extend the Thread class.
So I would create a loading screen like this:
public class LoadingScreen extends MainScreen {
public LoadingScreen() {
super();
this.setTitle("loading...");
// add a spinning animated gif or whatever here
final Screen me = this;
new Thread(new Runnable(){
public void run(){
// do something that takes a long time
try { Thread.sleep(1000);} catch (Exception e) {}
}
}){
public void run() {
super.run();
synchronized (UiApplication.getEventLock()) {
UiApplication.getUiApplication().popScreen(me);
}
}
}.start();
}
}
Then I push this screen, it will perform the long task, and then pop itself when its done.
(you may or may not want to disable the back button and menus on this screen)
I made the Runnable as an anonymous inner class just to compact the code, but you probably have this code already in a class somewhere else, so you would pass it in instead.
To add some flexibility and keep your classes loosely coupled together, you could make some modifications to your ServerConnectivity class so your calls could go something like the following:
// push your splash screen on to the stack
//
final SplashScreen splashScreen = new SplashScreen();
UiApplication.getUiApplication().pushScreen(splashScreen);
_getDoc = new ServerConnectivity(this, new ServerConnectivityListener() {
public void onCompleted(ServerConnectivity sender) {
// display next screen
//
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
splashScreen.close();
UiApplication.getUiApplication().pushScreen(new NextScreen());
}
});
}
public void onError(ServerConnectivity sender) {
splashScreen.close();
// display error message, retry, etc...
}
});
For this to work, you need an interface with the following definition:
public interface ServerConnectivityListener {
void onCompleted(ServerConnectivity sender);
void onError(ServerConnectivity sender);
}
So, your ServerConnectivity class maintains a reference to some object that implements the interface called ServerConnectivityListener This allows you to maintain loose coupling between the subject class and any observers that need to listen for events.
Within ServerConnectivity, you would make calls to the listener's methods something like this:
// begin excerpt from above...
//
if(_topics == null || _notifications == null) {
_listener.onError(this);
} else {
_listener.onCompleted(this);
}
catch ( Exception e ){
System.out.println( e.toString() );
_listener.onError(this);
//
// end excerpt from above...
Here is code for splash screen in java........after and call that view.........
http://www.randelshofer.ch/oop/javasplash/javasplash.html
import java.awt.*;
import java.awt.event.*;
public class SplashTest extends Frame implements ActionListener {
static void renderSplashFrame(Graphics2D g, int frame) {
final String[] comps = {"foo", "bar", "baz"};
g.setComposite(AlphaComposite.Clear);
g.fillRect(130,250,280,40);
g.setPaintMode();
g.setColor(Color.BLACK);
g.drawString("Loading "+comps[(frame/5)%3]+"...", 130, 260);
g.fillRect(130,270,(frame*10)%280,20);
}
public SplashTest() {
super("SplashScreen demo");
setSize(500, 300);
setLayout(new BorderLayout());
Menu m1 = new Menu("File");
MenuItem mi1 = new MenuItem("Exit");
m1.add(mi1);
mi1.addActionListener(this);
MenuBar mb = new MenuBar();
setMenuBar(mb);
mb.add(m1);
final SplashScreen splash = SplashScreen.getSplashScreen();
if (splash == null) {
System.out.println("SplashScreen.getSplashScreen() returned null");
return;
}
Graphics2D g = (Graphics2D)splash.createGraphics();
if (g == null) {
System.out.println("g is null");
return;
}
for(int i=0; i<100; i++) {
renderSplashFrame(g, i);
splash.update();
try {
Thread.sleep(200);
}
catch(InterruptedException e) {
}
}
splash.close();
setVisible(true);
toFront();
}
public void actionPerformed(ActionEvent ae) {
System.exit(0);
}
public static void main (String args[]) {
SplashTest test = new SplashTest();
}
}
Since,it is a thread based one,We cannot do it the normal way.So Check the following link
http://supportforums.blackberry.com/t5/Java-Development/What-is-the-Event-Thread/ta-p/446865
and Check whether parsing is done,Until that have the same screen,Check the condition of whehter it is downloaded or not ,and then push the screen
Suppose this is my NeteorkingMainScreen class which will display the text retrived from web.
public NetworkingMainScreen() {
setTitle("Networking");
urlField = new EditField("URL:", "");
textOutputField = new RichTextField();
add(urlField);
add(textOutputField);
}
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(new MenuItem("Get", 10, 10) {
public void run() {
getURL();
}
});
private void getURL() {
HttpRequestDispatcher dispatcher = new HttpRequestDispatcher(urlField.getText(),"GET", this);
dispatcher.start();
}
//*********************************************************************************
//HttpRequestDispatcher class performs the downloading of contents of webpage.
public class HttpRequestDispatcher extends Thread {
private String url;
private String method; // GET or POST
private NetworkingMainScreen screen;
public HttpRequestDispatcher(String url, String method, NetworkingMainScreen screen){
this.url = url;
this.method = method;
this.screen = screen;
}
public void run() {
try{
HttpConnection connection = (HttpConnection)Connector.open(url);
connection.setRequestMethod(method);
int responseCode = connection.getResponseCode();
if (responseCode != HttpConnection.HTTP_OK){
screen.requestFailed("Unexpected response code: " + responseCode);
connection.close();
return;
}
String contentType = connection.getHeaderField("Content-type");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream responseData = connection.openInputStream();
byte[] buffer = new byte[10000];
int bytesRead = responseData.read(buffer);
while(bytesRead > 0) {
baos.write(buffer, 0, bytesRead);
bytesRead = responseData.read(buffer);
}
baos.close();
connection.close();
screen.requestSucceeded(baos.toByteArray(), contentType);
}
catch (IOException ex) {
screen.requestFailed(ex.toString());
}
}
}
//***************************************************************************
//WaitScreen displays animation till the downloading is completed.
class WaitScreen extends FullScreen
{
}
Now I m getting confused...
When to start the WaitScreen class. Suppose i start by creating an object of WaitScreen and pushing the screen object.
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(new MenuItem("Get", 10, 10) {
public void run()
UiApplication.getUiApplication.pushScreen(new WaitScreen());
getURL();
}
});
How would my code know that it should displaying the animated Screen and display the contents of the webpages ie i mean how my code will knows downloading data has been completed. ie when i will call popScreen()?
I interface is to be used how can use the interface and what help we will get by using the interface.? Plz help
This is rather simple.
Your HttpRequestDispatcher should have a handle to the WaitScreen instance to be able to show it on start and close it upon completion.
So inside of the HttpRequestDispatcher you could (1) create the WaitScreen. (2) Push it. (3) Do the stuff the HttpRequestDispatcher should do. (4) Pop the the WaitScreen. Smth like that:
final WaitScreen waitScreen = new WaitScreen();
// just to reduce code duplication
final UiApplication app = UiApplication.getUiApplication();
// we are on the non-UI thread, so need
// to use UiApplication.invokeLater(Runnable action),
// it safely runs the passed action on the UI thread
app.invokeLater(new Runnable() {
public void run() {
app.pushScreen(waitScreen);
}
});
try {
// main networking actions go here
} catch (..) {
// error handling goes here
} finally {
// make sure we close the waitScreen
app.invokeLater(new Runnable() {
public void run() {
app.popScreen(waitScreen);
}
});
}
Here, Try this. All you have to do is put your code into the "run" function.
If you want help with the HttpRequest stuff or have trouble with the classes there, let me know. I have a web library with thread classes set up to use the classes within that post.