Tools/Guide to Creating an Image Looper in GWT - ajax

I'm setting out to create a weather model display tool (web application), and from what I've seen, I'm really liking the idea of using Google Web Tools, and especially the SmartGWT toolkit. My one biggest sticking point at this point is finding some way to create a sort of image "looper" (displaying all images in a particular "set" one after another, not unlike a slide show). For reference, I need functionality (at least on a basic level) similar to this: http://rapidrefresh.noaa.gov/hrrrconus/jsloop.cgi?dsKeys=hrrr:&runTime=2012053007&plotName=cref_sfc&fcstInc=60&numFcsts=16&model=hrrr&ptitle=HRRR%20Model%20Fields%20-%20Experimental&maxFcstLen=15&fcstStrLen=-1&resizePlot=1&domain=full&wjet=1 (though it certainly need not be exactly like that).
Does anyone know of (ideally) some sort of GWT module that can do image looping? Or if not, does it sound like something an intermediate programmer could figure out without too much trouble (I'm willing to accept a challenge), even if I've never explicitly used GWT before? I'm sure I could whip together something that pulls each image in as it goes through a loop, but prefetching them would be even more ideal.
Please comment if you need clarification on anything!

As far as I'm aware there's not a pre-fab solution to do this, although maybe SmartGWT has something I don't know about. In any case, it won't be too hard to roll your own. Here's some code to get you started:
public class ImageLooper extends Composite {
// List of images that we will loop through
private final String[] imageUrls;
// Index of the image currently being displayed
private int currentImage = 0;
// The image element that will be displayed to the user
private final Image image = new Image();
// The Timer provides a means to execute arbitrary
// code after a delay or at regular intervals
private final Timer imageUpdateTimer = new Timer() {
public void run() {
currentImage = (currentImage + 1) % images.length;
image.setUrl(imageUrls[currentImage]);
}
}
// Constructor. I'll leave it to you how you're going to
// build your list of image urls.
public ImageLooper(String[] imageUrls) {
this.imageUrls = imageUrls;
// Prefetching the list of images.
for (String url : imageUrls)
Image.prefetch(url);
// Start by displaying the first image.
image.setUrl(imageUrls[0]);
// Initialize this Composite on the image. That means
// you can attach this ImageLooper to the page like you
// would any other Widget and it will show up as the
// image.
initWidget(image);
}
// Call this method to start the animation
public void playAnimation() {
// Update the image every two seconds
imageUpdateTimer.scheduleRepeating(2000);
}
// Call this method to stop the animation
public void stopAnimation() {
imageUpdateTimer.cancel();
}
}
One annoying thing with this implementation is that you have no way of knowing when your list of images has finished loading; Image.prefetch doesn't have a callback to help you here.

Related

How can I add "proper" images (not Icons) to my JFrame/JPanel/JComponents (Swing) (Kotlin)

Language: Kotlin,
GUI Library: Swing,
IDE: IntelliJ IDEA
I know that there are similarly phrased questions, but note that I want to add multiple images, not just one, to any type of JComponent that holds other components. For example, I am not concerned with adding an image to a JLabel, I already know how to do that. I want to know how to add an image to a JFrame, JPanel, Container, etc.; all things that hold other Components (and have an add(Component) function). Finally, I don't want that workaround where you add the image to a JLabel with no text and then add that to the container. I would like to just use the Image class or a subset like BufferedImage or URL.
I want to be able to call the add() method from the Container class, jFrame.add(component) for example, where component is some sort of image. I want this to result in an image being displayed on the screen.
The ImageIcon class is not a Component so this can't be input on its own. I think I would have to create some sort of custom Image class that extends from Component or JComponent, but I don't know what I would have to override to get that to display an image on screen when added to another JComponent. There are multiple solutions to this, but to clarify, I don't want some kind of "middle man" where I add a JLabel or JButton or something that only contains an Icon. I don't want to display icons anyway, I want to display full-sized images anywhere on the screen. I will provide a possible example of what I want the final result to look like.
class MyApp() {
fun init() {
var jFrame = JFrame()
jFrame.add(Image("filepath/image.png"))
//Some other JFrame boiler plate
jFrame.isVisible = true
}
}
fun main() {
MyApp().init()
}
The unclear part is the Image class, and whether that's a custom class that inherits JImage, or some already defined class or method I don't know about. I know about ImageIO and BufferedImage and ImageIcon, but none of them directly go into this method, as they don't inherit Component or JComponent.
EDIT:
I tried using Camickr's second solution, but it didn't work. I will post the code to see if a made a simple mistake.
import java.awt.Image as AWTImage
import java.awt.Image.*
//Including these imports as I used name alias so I had to say what it was from.
open class JImage(var point: Point = Point(0, 0), image: AWTImage): JComponent() {
var image: ImageIcon = ImageIcon(image)
override fun paintComponent(g: Graphics?) {
super.paint(g)
g?.drawImage(image.image, point.x.toInt(), point.y.toInt(), null)
}
}
class SplashScreen(image: JImage): Frame() {
init {
//jFrame.isUndecorated = true
jFrame.add(image)
}
}
class MyApp {
fun init() {
var jFrame = SplashScreen(JImage(image = ImageIO.read(Loader().getClassLoader().getResourceAsStream("resources/images/splashscreen/SplashScreen.png"))).getScaledInstance(Size(1000, 1000*3/5)))
jFrame.isVisible = true
}
}
fun main() {
MyApp().init()
}
FINAL EDIT:
Okay, so I did make a simple mistake when trying this solution. I overrode paintComponent() but then inside it, I called super.paint(). Additionally, I realized I didn't have to use the ImageIcon class, which I didn't want to do anyway. This is the Image class I have come up with.
open class JImage(var point: Point = Point(0, 0), var image: AWTImage): JComponent() {
fun getScaledInstance(size: Size, scalingMethods: ScalingMethods = ScalingMethods.DEFAULT): JImage {
val scale: Int = when(scalingMethods) {
ScalingMethods.DEFAULT -> SCALE_DEFAULT
ScalingMethods.FAST -> SCALE_FAST
ScalingMethods.AREA_AVERAGING -> SCALE_AREA_AVERAGING
ScalingMethods.REPLICATE -> SCALE_REPLICATE
ScalingMethods.SMOOTH -> SCALE_SMOOTH
}
return JImage(point, image.getScaledInstance(size.width.toInt(), size.height.toInt(), scale))
}
override fun paintComponent(g: Graphics?) {
super.paintComponent(g)
g?.drawImage(image, point.x.toInt(), point.y.toInt(), null)
}
}
I want to know how to add an image to a JFrame, JPanel, Container, etc.
You don't add an image to a JFrame, JPanel etc. As you said an image is not a component. You add the image to a JLabel and add the label to the panel. This is the easiest and more direct way to display an image at its actual size.
Don't know if Kotlin is any different, but the other option is to do custom painting and paint the image on a JPanel by overriding the paintComponent(…) method and using the Graphics.drawImage(…) method and then add the panel to the frame. Read the Swing tutorial on Custom Painting for painting basics.
You can also check out Background Panel for an example that paints an image as a background of the panel. The image can be:
painted at its real size
scaled to fill the panel
tiled to fill the panel
Just note that the image should NOT be read in the paintComponent() method as painting code should be efficient.

JavaFX Export Scene as PDF/SVG

I have currently developed an ultimately open source application to analyse some data in a table view and visualise the resulting data in some additional plots. A problematic thing with this is, that the generated plots could potentially be useful for end users for e.g. a presentation, further downstream informative discussion and so on. This is why I started working on an export function using ImageWriter
//adding a context menu item to the chart
final MenuItem saveAsPng = new MenuItem("Save as png");
saveAsPng.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
int scale = 6; //6x resolution should be enough, users should downscale if required
final Bounds bounds = bc.getLayoutBounds();
final SnapshotParameters spa = new SnapshotParameters();
spa.setTransform(javafx.scene.transform.Transform.scale(scale, scale));
ImageWriter imageWriter = new ImageWriter();
try {
imageWriter.saveImage(stage, bc.snapshot(spa, null));
} catch (ImageException e) {
e.printStackTrace();
}
}
});
This successfully creates a PNG file with sufficient size, but my ideal solution would be to export in vector-based format, e.g. PDF/SVG. For Swing applications, I knew how to achieve this, but for JFX I couldn't really find a proper solution for that matter. I already investigated several potential ideas, e.g. using a printer dialogue and then exporting as a PDF via virtual printer, but that does result in a bitmap inside the PDF, too.
Any ideas on this?

Windows Phone XAML and XNA app with ads

I am trying to display ads from pubcetner in XNA game for WP. I am using DrawableAd class as it is written here:
http://msdn.microsoft.com/en-us/library/advertising-mobile-windows-phone-xna-silverlight-hybrid-walkthrough-ads%28v=msads.20%29.aspx
But I can't see any ads rendering. Is it works? Or is there any other way to display ads? I wanted to try Adrotator, but I can't
get NuGet Package for this
Ok, I had a lot of problems with this in my game.
Without seeing your code, it's hard to actually diagnose, so without posting that from your Game.cs (assuming it's in Game.cs), you will need to make sure to test the following things.
//Global variable area
DrawableAd bannerAd;
string applicationID = "test_client"; //Or insert your actual ID. I recommend you first do with test client
//ie. 1234567-d123-1234-a12b-1a23b4567890
string adUnitID = "Image480_80"; //Or the actual unit ID. ie. 123456
//Initialization
protected override void Initialize(){
AdGameComponent.Initialize(this, applicationId);
AdGameComponent.Current.CountryOrRegion = System.Globalization.RegionInfo.CurrentRegion.TwoLetterISORegionName;
bannerAd = AdGameComponent.Current.CreateAd(adUnitId, new Rectangle(0,400, 480, 80), true);
AdGameComponent.Current.Enabled = true;
AdGameComponent.Current.Visible = true;
base.Initialize();
}
The part that got me by surprise was that I got rid of my base.Update(...) and base.Draw(...) calls and it actually prevented anything from ever being updated or called with the Ad. I also remember through my endeavor that the region was apparently important in some cases. Can't find the source for that. You might be able to get rid of it.
protected override void Update(GameTime gameTime)
{
//Your code here...
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
//Your code here...
base.Draw(gameTime);
}
Hope that helps! Good luck. I know I had a pretty nasty time figuring out why mine didn't work. Make sure your render order is correct to. I'm not sure, but perhaps you might be drawing everything ON the ad. I haven't looked into whether you could actually do that or if the depth field of the ad was always on top. I just leave my base.Draw(gameTime) at the bottom of everything else.

Asynchronous image loading in AS3

I understand that images are to be loaded asynchronously in AS3, and that that synchronisation should be handled using events and event listeners.
So, in a simple case, it would look like this:
var loader : Loader = new Loader();
var im_file: URLRequest = new URLRequest ("imfile.png");
loader.load(im_file);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loading_complete);
function loading_complete (e : Event) : void
{ // ... do smt with your loaded data // }
What I want to do is have a PreLoader class that will load all the images I need beforehand.
In that case, how do I let all the other classes know when the loading is done?
Do I dispatch events? What is the best practise in this case?
Thanks in advance,
Praskaton
Most likely you want to create a queue and add your image paths to the queue. Then after each image is done loading, you proceed to the next item in the queue. When all images are loaded, you dispatch a COMPLETE event or something similar to let your app know it's all done.
Check QueueLoader or Casalib for how they implement single or bulk image loading.
Adding to the answer that #Boon provided, this is how you could go about the actual setting up of the image queue.
Firstly, you need a list that will store all of the images that still need to be loaded. This makes it easy for you to define as many images as you want. It can be the 'queue':
var queue:Array = [
"http://interfacelift.com/wallpaper/previews/03177_orionnebulaintheinfrared#2x.jpg",
"http://interfacelift.com/wallpaper/previews/03175_purpleclouds#2x.jpg",
"http://interfacelift.com/wallpaper/previews/03173_goodmorning2013#2x.jpg"
];
The next thing to do is set up what I would call the 'core' method of what we're doing. It will handle loading the next image as well as notifying us when the queue is empty. It looks something like this:
function loadNext():void
{
if(queue.length > 0)
{
// Notice here that we use .pop() on the queue, which will select and
// remove the last item from queue.
var req:URLRequest = new URLRequest( queue.pop() );
var photo:Loader = new Loader();
photo.load(req);
photo.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
}
else
{
// The queue is finished - dispatch an event or whatever you fancy to
// let the rest of the application know we're done here.
trace("Queue finished.");
}
}
And then of course our listener function to deal with the completion of loaded images. Notice here that we call loadNext() - this is the key to beginning the load of the next image in the queue only once the currently loading image has finished.
function loadComplete(e:Event):void
{
addChild(e.target.content as Bitmap);
// Begin loading next image in the queue.
loadNext();
}
And to start the process we of course just use this, which will either immediately notify us that the queue is finished if it's empty, or start loading the images in sequence.
// Start loading the queue.
loadNext();
Additional / tidy up:
If you want to be able to recycle this code or just tidy up, you can easily make this into a class. The class could be called ImageQueue and its structure will contain the above queue array, loadNext() method and loadComplete() method. It can also have an add() method for adding images to the queue initially in a cleaner manner.
Here is the foundation of that class, which you can finish up if you're interested:
public class ImageQueue
{
private var _queue:Array = [];
public function add(image:String):void{ }
public function loadNext():void{ }
private function _loadComplete(e:Event):void{ }
}

ViewModels and IsolatedStorageSettings

Im working on a MVVM Windows phone app that displays weather info.
When the app loads up it opens MainPage.xaml. It makes a call the the service to get weather info and binds that data to the UI. Both Fahrenheit and Celcius info are returned but only one is displayed.
On the setting page, the user can select to view the temp in either Fahrenheit or Celcius.
The user can change this setting at any time and its stored in IsolatedStorageSettings.
The issue Im having is this:
when the user navigates to the Settings page and changes their preference for either Fahrenheit or Celcius, this change is not reflected on the main page.
This issue started me thinking about this in a broader context. I can see this being an issue in ANY MVVM app where the display depends on some setting in IsolatedStorage. Any time any setting in the IsoStore is updated, how does the ViewModels know this? When I navigate back in the NavigationStack from the settings page back to MainPage how can I force a rebind of the page?
The data in my model hasnt changed, only the data that I want to display has changed.
Am I missing something simple here?
Thanks in advance.
Alex
Probably you have code like this:
public double DisplayTemperature
{
get { return (IsCelsium) ? Celsium : Fahrenheit; }
}
And IsCelsium is:
public double IsCelsium
{
get { return (bool)settings["IsCelsium"]; }
set { settings["IsCelsium"] = value; }
}
So you need to add NotifyPropertyChanged event to notify UI to get new values from DisplayTemperature property:
public double IsCelsium
{
get { return (bool)settings["IsCelsium"]; }
set
{
settings["IsCelsium"] = value;
NotifyPropertyChanged("DisplayTemperature");
}
}
Take a look at Caliburn Micro. You could implement something similar or use CM itself. When using CM I don't even think about this stuff, CM makes it so simple.
When your ViewModel inherits from Screen there are life-cycle events that fire that you can override. For example, OnInitialize fires the very first time the ViewModel is Activated and OnActivate fires every time the VM is activated. There's also OnViewAttached and OnViewLoaded.
These methods are the perfect place to put logic to populate or re-populate data.
CM also has some special built in features for allowing one to easily tombstone a single property or an entire object graph into Iso or phone state.
ok, so Ive come up with a solution. Before I get to it, let me provide some background. The app that Im working on uses both MVVM Light and WP7Contrib. That being the case, I am using Funq for DI and the MVVMLight Toolkit. After I posted my initial question, I gave the question a bit more thought. I remembered a video that I watched a while back from MIX2011 called Deep Dive MVVM with Laurent Bugnion
http://channel9.msdn.com/Events/MIX/MIX11/OPN03
In it, he talks about just this problem (view models not living at the same time) on Windows Phone. The part in question starts around the 19 minute mark.
Anyway, after I remembered that and realized that the ViewModel locator is exposed in App.xaml, this became a trivial problem to solve. When the user changes the Fahrenheit/Celcius option on the setting page, I simply get a reference to the MainViewModel via the ViewModelLocator and reset the collection that is bound to the UI thus causing the bindings to update.
public bool AddOrUpdateValue(string Key, Object value)
{
bool valueChanged = false;
// If the key exists
if (settings.Contains(Key))
{
// If the value has changed
if (settings[Key] != value)
{
// Store the new value
settings[Key] = value;
valueChanged = true;
}
}
// Otherwise create the key.
else
{
settings.Add(Key, value);
valueChanged = true;
}
return valueChanged;
}
public bool ImperialSetting
{
get
{
return GetValueOrDefault<bool>(ImperialSettingKeyName, ImperialSettingDefault);
}
set
{
if (AddOrUpdateValue(ImperialSettingKeyName, value))
{
Save();
RaisePropertyChanged("ImperialSettingText");
var vml = new ViewModelLocator();
vml.MainViewModel.Cities = (App.Current as App).Cities;
}
}
}
It was a mistake on my part not to realize that I could get access to the viewModel via the ViewModelLocator. Hopefully this post saves someone else the time I burned on this issue.

Resources