I have a list that contains about 20 image URLs and some other things.
I want to display the other things (description) and allow the user to interact with the app while I load the 20 images.
What I noticed is that no matter what I tried, I can't interact with the form until the images finished loading even though I am doing the loading in another thread.
This is my solution I am using now.
private Container createServerItems() throws Exception {
Container list = new Container(new BoxLayout(BoxLayout.Y_AXIS));
final int size = mediaList.size();
final Button buttons[] = new Button[size];
System.out.println("In here: " + size);
for (int i = 0; i < size; i++) {
Container mainContainer = new Container(new BorderLayout());
Media m = new Media();
m.fromJSONString(mediaList.elementAt(i).toString());
buttons[i] = new Button("please wait");
final int whichButton = i;
Display.getInstance().callSerially(new Runnable() {
public void run() {
try {
System.out.println(MStrings.replaceAll(m.getImgURL(), "\"", ""));
final StreamConnection streamConnection = (StreamConnection) Connector.open(MStrings.replaceAll(m.getImgURL(), "\"", ""));
Image image = Image.createImage(streamConnection.openInputStream());
streamConnection.close();
buttons[whichButton].setText("");
buttons[whichButton].setIcon(image.scaled(32, 32));
} catch (Exception e) {
}
}
});
TextArea t = new TextArea(m.getDesc());
t.setEditable(false);
t.setFocusable(false);
t.setGrowByContent(true);
mainContainer.addComponent(BorderLayout.WEST, buttons[i]);
mainContainer.addComponent(BorderLayout.CENTER, t);
list.addComponent(mainContainer);
}
return list;
}
APPROACH I : LWUIT 1.5 has a powerful LWUIT4IO library to address your problem.
An excerpt from Shai's Blog link
A feature in LWUIT4IO to which I didn't give enough spotlight is the
cache map, its effectively a lean hashtable which stores its data
using weak/soft references (depending on the platform) and falls back
to storage when not enough memory is available. Its a great way to
cache data without going overboard. One of the cool things about it is
the fact that we use it seamlessly for our storage abstraction (which
hides RMS or equivalent services) in effect providing faster access to
RMS storage which is often slow on devices.
Another useful link is here
The idea is to delegate the Network IO functionality to a singleton to avoid any UI deadlocks, like the one you are facing.
A very good video demo here by vprise, explains how to bind GUI functionality to your netbeans. In this video at around 7:00 mins it explains the use of ImageDownloadService class which binds the component to its thumbnail url which will seamlessly fetch from the network and populate the Image.
APPROACH II: Difficult one of create custom logic
Create a singleton that will interface with the network to fetch the
data
Use a queue to handle the sequential image download services
Create a new thread for this singleton and wait on the queue.
With each image download service bind a listener with the invoking
component so that it easier to update the right component.
According to the lwuit spec, callSerially() executes on the Event Dispatch Thread, which means that it will block other events until it completes. You need to move your code to load the image outside of that method and keep only the setText and setIcon calls in callSerially().
Related
I'm working with the VLCJ Bindings and have finally been able to get several roadblocks. Now I am here.
I have no need (at this time), nor desire for, a visible Media Player component (the EmbeddedMediaPlayerComponent). All I need (for now) is to play Audio Files.
I have the following method in place to handle that for me:
public static void Play(File AudioFile){
if (!LibVLCLoader.Loaded) LibVLCLoader.loadLibVLC();
EmbeddedMediaPlayerComponent EMPC = new EmbeddedMediaPlayerComponent();
if (EMPC.getMediaPlayer().prepareMedia(AudioFile.getAbsolutePath())){
EMPC.getMediaPlayer().addMediaPlayerEventListener(new MediaPlayerEventAdapter(){
#Override public void subItemFinished(MediaPlayer p, int i){
EMPC.release(true);
}
});
Platform.runLater(() -> EMPC.getMediaPlayer().play());
}
}
But I keep getting this exception:
Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: The video surface component must be displayable
Which I understand. It makes sense. But I don't NEED it visible. I just need the sound. How can I make that happen?
EmbeddedMediaPlayer is only for the case where you want to literally embed a video surface inside your application.
If you just need audio, there's an AudioMediaPlayerComponent for expressly this purpose.
To create such a component, simply:
AudioMediaPlayerComponent audioMediaPlayerComponent =
new AudioMediaPlayerComponent();
You can subclass it, for example to customise behaviour and easily implement event handlers.
Using the so-called "component" media players gives you a slightly nicer/easier API than using the non-"component" media players that are created via the MediaPlayerFactory.
This works just fine if your media is an audio file.
If your media is actually video, but you only want to play the audio track, then even if you use the AudioMediaPlayerComponent by default VLC will open a video window. In this case you still need to actually disable the video output - the simplest way to do this is to tell VLC to use vcodec=dummy.
I really don't agree with tricks like creating a window and moving it off-screen, or sizing it down to 1x1, it's just not necessary.
In the code posted in the original question there is an unrelated problem. The EMPC and EMP variable will go out-of-scope when the Play() method terminates, making the media player eligible for garbage collection. What will happen is that some random time later your application will likely crash because the native hooks that vlcj uses will call back into a Java object that no longer exists. You need to keep your media player references alive via hard references.
Okay so it turns out you can create your own MediaPlayer object outside of the EmbeddedMediaPlayerComponent like so:
public static void Play(File AudioFile){
if (!LibVLCLoader.Loaded) LibVLCLoader.loadLibVLC();
MediaPlayerFactory MPF = new MediaPlayerFactory(
"--video-title=vlcj video output",
"--no-snapshot-preview",
"--quiet",
"--quiet-synchro",
"--sub-filter=logo:marq",
"--intf=dummy"
);
EmbeddedMediaPlayer EMP = MPF.newEmbeddedMediaPlayer();
if (EMP.prepareMedia(AudioFile.getAbsolutePath())){
EMP.addMediaPlayerEventListener(new MediaPlayerEventAdapter(){
#Override public void subItemFinished(MediaPlayer p, int i){
EMP.release();
MPF.release();
}
});
Platform.runLater(() -> EMP.play());
} else{
EMP.release();
MPF.release();
}
}
I'm struggling with this issue since some days ago and I'm not able to find a solution.
I have a listener which receives market data (orders at bid and ask). If market is quiet (pre-market or post-market (low volatility)) everything works fine. But once the market is open the listener receives events too fast. So after a couple of minutes my app freezes.
Right now the listener only assigns the received data to a var.
orderBookBid.getBuyOrders().addListener(new ObservableListModelListener<Order>() {
#Override
public void modelChanged(final Change<? extends Order> change) {
System.out.println("bid event");
bidChange = change.getSource();
}
});
The program only freezes when uses real data. When market is closed and uses test data from a local file works fine.
Is there any way to set the maximum number of events per second? Or any way to ignore events for a short time period?
Any idea on how can I handle this would be very appreciated.
Thanks.
You could put a load balancer in your application, that way it will create a queue and will not freeze the application.
If you want to let go some events, in the logic of your listener, you should have something that check if it's been X time since the last time you managed the event.
private long timeSinceLastEventManaged = 0;
private final static long MINIMUM_TIME = 2000; //2 seconds
In your listener
public void modelChanged(final Change<? extends Order> change) {
long timeSystem = System.currentTimeMillis();
if(timeSystem - timeSinceLastEventManaged > MINIMUM_TIME){
//do your stuff
timeSinceLastEventManaged = timeSystem;
}
}
First of all you should get rid of the println as it is really slow
The rest depends on what you are doing. Right now it seems that you are just getting the value and writing it to a variable. You will only see the latest change that way and if that is what you want the solution #TyMarc suggested will work fine.
If what you showed us is just an example and you really need every change things get a bit more complicated. Your modelChanged method should be changed to add the current value to a queue (e.g a LinkedList or Stack).
public void modelChanged(final Change<? extends Order> change)
{
syncronized(syncObject)
{
//add to your preffered queue
syncObject.notifyAll()
}
}
This frees your listener from the real work and it can keep collecting data.
I added a syncronized as someone has to do the work. For this you can use a Thread that runs something like this:
Order current;
while(keeprunning)
{
syncronized(syncObject)
{
if(queue.hasNext())
{
current = queue.getNext()
}
else
{
Thread.wait()
}
}
//do the real work here
}
Now someone else has the problem. Literally. If the Thread can't handle the inflow of data the queue will grow in size until you run out of memory or hit some other limit. But that's another story.
And yes, nothing of this will compile as I only wanted to show an example
I have some page that should have dynamic count of check boxes, and inputs depends on data received from database
now I do like this:
make rpc call on component load (getting data for inputs)
onSuccess add inputs dynamically on the form
result: form displayed without content(because it makes call async), only after resizing, it displays content properly
(probably I can fire resize event or redraw with my self, don't know how.. )
question: I am new in GWT, What is the best way to do this task? (Now i am using gwt-ext http://gwt-ext.com/, but I think it's no matter )
update: to refresh panel it's possible to call doLayout();
I'm not familiar with gwt-ext but in "vanilla" gwt you have two options:
Refresh your widget (that should show the result) in the onSuccess method
Proceed with the rest of your code not until the result returned.
To get a bit more precise i would need more of your code.
I had a similar challenge, the content of my widget was loading for a few seconds. I display a ""Loading, please wait ..."" label until the widget is loaded:
final VerticalPanel mainPanel = new VerticalPanel();
initWidget(mainPanel);
mainPanel.add(new Label("Loading, please wait ..."));
mainPanel.add(new myCustomWidget()); // this constructor uses RPC to get content
Timer t = new Timer()
{
public void run()
{
if (!mainPanel.getWidget(1).isVisible()) {
// do nothing
} else {
// remove label "Loading, please wait ..."
mainPanel.remove(0);
// stop timer
cancel();
}
}
};
// repeat every 30 miliseconds until myCustomWidget is visible
t.scheduleRepeating(30);
i have coded a database update software which allows me to deploy a jade mobile agent in order to update the database. In order for it to run, i need to launch it using the AMS gui. I wanted to be able to launch it from gui. I have now done a nice swing gui and i only need to know the code which allows me to launch my mobile agent when the "Update" button is clicked. What is the code? Thanks in advance.
To launch an agent or do whatever related to JADE you need to write YOUR code using JADE libraries and API, irrespective of what Front End you have used (Swing in this case)
One suggestion would be, to keep the modularity, is create another file which does one of many such operations you want, and let your Swing GUI interact (say via sockets) to that file, triggering your operation.
That file, which would act as a server, would listen to the front end and do the respective work. But all commands are to be coded using JADE API. One such code is:
ContainerController cc = Runtime.instance().createAgentContainer(newProfileImpl());
Object arguments[] = new Object[1];``arguments[0]=new Object();
AgentController dummy = cc.createNewAgent("mob2","mobiletrial", arguments);
dummy.start();
This is a method I wrote for launching one agent from another.You'll have to edit it for multiple container use.
void launchAgent( final String AgentName, final String AgentType)
{
log(Level.FINER,"attempting to launch angent name: "+AgentName+" type: "+AgentType);
CreateAgent ca = new CreateAgent();
ca.setAgentName(AgentName);
ca.setClassName(AgentType);
ca.setContainer(new ContainerID(AgentContainer.MAIN_CONTAINER_NAME, null));
Action actExpr = new Action(this.getAMS(), ca);
ACLMessage request = new ACLMessage(ACLMessage.REQUEST);
request.addReceiver(this.getAMS());
request.setOntology(JADEManagementOntology.getInstance().getName());
request.setLanguage(FIPANames.ContentLanguage.FIPA_SL);
request.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST);
try {
getContentManager().fillContent(request, actExpr);
addBehaviour(new AchieveREInitiator(this, request) {
protected void handleInform(ACLMessage inform) {
log(Level.INFO,"Agent successfully created name:"+AgentName+" type: "+AgentType);
}
protected void handleFailure(ACLMessage failure) {
log(Level.SEVERE,"Agent launch failed name: "+AgentName+" type: "+AgentType);
}
} );
}
catch (Exception e) {
e.printStackTrace();
}
}
i am trying to simulate a live view using a canon Camera.
I am interacting with the cam using the CanonSDK, i get an image every a short period in order to simulate a video frame by frame. This works fine, i am using java to do the backend and send the images trough BlazeDS to flex.
The problem is not getting the image, the problem is that when i load a new image using something like:
image.source=my_new_image;
the new image is loaded but it produces a short white blink and it ruins the video...
So i would like to know if the is a way to update an image on flex avoiding the blinking problem, or if i could make a video streaming from java and pick it up with flex...
Thanks in advance!!!
The easy way is to use a technique called double buffering, using two Loaders - one for the image which is visible, and one for the image which is being loaded and is invisible. When the image has completed loading it becomes visible, and the other one becomes invisible and the process repeats.
In terms of efficiency, it would be better to at least use a socket connection to the server for transferring the image bytes, preferably in AMF format since it has little overhead. This is all fairly possible in BlazeDS with some scripting.
For better efficiency you may try using a real-time frame or video encoder on the server, however decoding the video on the client will be challenging. For best performance it will be better to use the built-in video decoder and a streaming server such as Flash Media Server.
UPDATE (example script):
This example loads images over HTTP. A more efficient approach would be to use an AMF socket (mentioned above) to transfer the image, then use Loader.loadBytes() to display it.
private var loaderA:Loader;
private var loaderB:Loader;
private var foregroundLoader:Loader;
private var backgroundLoader:Loader;
public function Main()
{
loaderA = new Loader();
loaderB = new Loader();
foregroundLoader = loaderA;
backgroundLoader = loaderB;
loadNext();
}
private function loadNext():void
{
trace("loading");
backgroundLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleteHandler);
backgroundLoader.load(new URLRequest("http://www.phpjunkyard.com/randim/randim.php?type=1"));
}
private function loaderCompleteHandler(event:Event):void
{
trace("loaded");
var loaderInfo:LoaderInfo = event.target as LoaderInfo;
var loader:Loader = loaderInfo.loader;
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loaderCompleteHandler);
if (contains(foregroundLoader))
removeChild(foregroundLoader);
var temp:Loader = foregroundLoader;
foregroundLoader = backgroundLoader;
backgroundLoader = temp;
addChild(foregroundLoader);
loadNext();
}