How to set animated image (gif) in a SWT widget using Tabris Framework - tabris

I need to display an animated gif image in the app. In the following code example, I set the setImage property of a Label widget. This works fine in the browser (rap), but mobile app only displays static image without animation. Is there a way to display animated image using Tabris framework?
private void openDialog() {
this.display = getUI().getDisplay();
this.shell = new Shell( this.display, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL );
this.shell.setLayout( new GridLayout() );
Image image = createImage( this.display, "resources/loading.gif" );
Label label = new Label( this.shell, SWT.NONE );
label.setImage( image );
this.shell.open();
}
private Image createImage( Display display, String resourceName ) {
ClassLoader classLoader = getClass().getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream( resourceName );
if( inputStream == null ) {
throw new IllegalArgumentException( "Resource not found: " + resourceName );
}
try {
return new Image( display, inputStream );
} finally {
try {
inputStream.close();
} catch( IOException exception ) {
// TODO handle exception
}
}
}

Currently it is not possible to display an animated gif. Tabris will improve support for image display so that feature could be added in the future.

Related

Xamarin.Forms Action Bar - Center Aligned Image

Using Xamarin.Forms, how do I get the same effect as the application pictured below, specifically to show a centred image on the Action Bar / page tool bar (the section in a blue box)?
I would like to have a long width image in that section, and the solution must work for Android, iOS, Windows Phone, and Universal Windows (even if it means writing custom renderers or platform specific xamarin code).
I suggest you create your own Xamarin.Forms view and handle the navigation by yourself something similar to this:
public class CustomBackNavigationBar : StackLayout
{
public Image BackIcon;
public Image Icon;
public Label IconTitle;
public StackLayout IconContainer;
public CustomBackNavigationBar(string title, string icon)
{
Padding = new Thickness(15,5);
HeightRequest = 40;
Orientation = StackOrientation.Horizontal;
VerticalOptions = LayoutOptions.Start;
BackgroundColor = StaticData.BlueColor;
Spacing = 15;
BackIcon = new Image
{
Source = StaticData.BackIcon,
HorizontalOptions = LayoutOptions.Start
};
Label Title = new Label
{
Text = title,
TextColor = Color.White,
FontSize = Device.GetNamedSize(NamedSize.Default, typeof(Label)),
FontAttributes = FontAttributes.Bold,
VerticalTextAlignment = TextAlignment.Center
};
Icon = new Image
{
Source = icon
};
IconTitle = new Label
{
Text = StaticData.CallAgent,
TextColor = Color.White,
FontSize = Device.GetNamedSize(NamedSize.Micro, typeof(Label)),
};
IconContainer = new StackLayout
{
HorizontalOptions = LayoutOptions.EndAndExpand,
Spacing = 2,
Children = { Icon, IconTitle }
};
Children.Add(BackIcon);
Children.Add(Title);
Children.Add(IconContainer);
#region Events
BackIcon.GestureRecognizers.Clear();
BackIcon.GestureRecognizers.Add(new TapGestureRecognizer
{
Command = new Command(PopAsync)
});
#endregion
}
async void PopAsync()
{
await App.AppNavigation.PopAsync();
}
}

Layout two controls in one row so that the right one is always fully visible in SWT

A UI with a label on the left and a button-like Link widget on the right, both in one row, should be layouted so that the Link is never cropped.
If there is enough space, the controls should be left-aligned:
If not enough space, the label should be decreased in width (thereby cropping its content) so that the link is still fully visible:
The snippet below does what it should. However, it uses a RowLayout and a resize listener to adjust the RowData to assign abolute width to the particular control. This contradicts the whole idea of using a layout manger.
public static void main( String[] args ) {
Display display = new Display();
Shell shell = new Shell( display );
shell.setLayout( new FillLayout() );
Composite container = new Composite( shell, SWT.NONE );
Label label = new Label( container, SWT.NONE );
label.setText( "kdsajf alkdsjf sadkf dsakfjalksd fadskjf sadlk sfdk dsflkjg" );
Link link = new Link( container, SWT.NONE );
link.setText( "<a>Do Something...</a>" );
RowLayout layout = new RowLayout();
layout.marginWidth = 0;
layout.wrap = false;
container.setLayout( layout );
label.setLayoutData( new RowData() );
link.setLayoutData( new RowData( 90, SWT.DEFAULT ) );
container.addListener( SWT.Resize, new Listener() {
#Override
public void handleEvent( Event event ) {
int linkWidth = link.computeSize( SWT.DEFAULT, SWT.DEFAULT ).x;
RowData rowData = ( RowData )link.getLayoutData();
rowData.width = linkWidth;
rowData = ( RowData )label.getLayoutData();
rowData.width = container.getClientArea().width - linkWidth - ( layout.spacing * 2 );
if( label.computeSize( SWT.DEFAULT, SWT.DEFAULT ).x < rowData.width ) {
rowData.width = SWT.DEFAULT;
}
}
} );
shell.pack();
shell.open();
while( !shell.isDisposed() ) {
if( !display.readAndDispatch() )
display.sleep();
}
display.dispose();
}
My hope is that there is a simpler solution, possibly using a regular SWT layout.

How can I change the font size of a Gtk.Label in vala?

I'm a Vala/Gtk newbie and I'm trying to change the font size of a Gtk.Label, but I can't find a good way to do it.
I find out that I can use the markup like this :
var welcome_message = new Gtk.Label ("<span size='17000'>Hello</span>");
welcome_message.set_use_markup (true);
But it seems a little hackish.
What is the right way to do it ?
Thanks lethalman and nemequ.
I think it might help someone so here is a little example of how to use css with Vala.
using Gtk;
public class StyleApp1 : Gtk.Window
{
public StyleApp1()
{
this.title = "Style app example";
this.set_border_width (10);
this.set_position (Gtk.WindowPosition.CENTER);
this.set_default_size (350, 200);
this.destroy.connect (Gtk.main_quit);
var screen = this.get_screen ();
var css_provider = new Gtk.CssProvider();
string path = "styleapp1.css";
// test if the css file exist
if (FileUtils.test (path, FileTest.EXISTS))
{
try {
css_provider.load_from_path(path);
Gtk.StyleContext.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER);
} catch (Error e) {
error ("Cannot load CSS stylesheet: %s", e.message);
}
}
var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 10);
this.add (box);
var label = new Gtk.Label ("Thank you");
box.add (label);
var label2 = new Gtk.Label ("Stackoverflow");
label2.get_style_context().add_class("my_class");
box.add (label2);
}
}
static int main(string[] args) {
Gtk.init(ref args);
StyleApp1 win = new StyleApp1();
win.show_all();
Gtk.main();
return 0;
}
and the styleapp1.css file :
GtkWindow {
font-size: 17px;
}
.my_class {
color: pink;
}
NB : if you use add_provider instead of add_provider_for_screen. You have to use add_provider for every widget that you want to customize.
You could try with css, I think lately this is the preferred way. Give your label a class, then load a css. If you are going to change the font size of a label, I bet you are also going to customize other things so the css may be useful for you.

IP Camera 401 unauthorized Error

While connecting IP camera with C# app, i found the simple player in Aforge/Samples/Player. It just needed modifying the ip string so i added mine admin:admin#192.168.1.239:81/videostream.cgi?rate=11 to get MJPEG video stream. On compiling i get error as
The Remote server returned an Error (401) Unauthorized.
Andre Kirillow mentioned in MJPEGstream.cs file
Some cameras produce HTTP header, which does not conform strictly to standard, what leads to .NET exception. To avoid this exception the useUnsafeHeaderParsing configuration option of httpWebRequest should be set, what may be done using application configuration file.
<configuration>
<system.net>
<settings>
<httpWebRequest useUnsafeHeaderParsing="true" />
</settings>
</system.net>
</configuration>
well there are two ways to do this as suggested by Dinis Cruz. I added the .config file wth the above code and also did it programmaticaly but same error persists. The Player program coding is
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using AForge.Video;
using AForge.Video.DirectShow;
using System.Reflection;
using System.Net.Configuration;
using System.Net;
namespace Player
{
public partial class MainForm : Form
{
private Stopwatch stopWatch = null;
// Class constructor
public MainForm( )
{
InitializeComponent( );
}
private void MainForm_FormClosing( object sender, FormClosingEventArgs e )
{
CloseCurrentVideoSource( );
}
// "Exit" menu item clicked
private void exitToolStripMenuItem_Click( object sender, EventArgs e )
{
this.Close( );
}
// Open local video capture device
private void localVideoCaptureDeviceToolStripMenuItem_Click( object sender, EventArgs e )
{
VideoCaptureDeviceForm form = new VideoCaptureDeviceForm( );
if ( form.ShowDialog( this ) == DialogResult.OK )
{
// create video source
VideoCaptureDevice videoSource = form.VideoDevice;
// open it
OpenVideoSource( videoSource );
}
}
// Open video file using DirectShow
private void openVideofileusingDirectShowToolStripMenuItem_Click( object sender, EventArgs e )
{
if ( openFileDialog.ShowDialog( ) == DialogResult.OK )
{
// create video source
FileVideoSource fileSource = new FileVideoSource( openFileDialog.FileName );
// open it
OpenVideoSource( fileSource );
}
}
// Open JPEG URL
private void openJPEGURLToolStripMenuItem_Click( object sender, EventArgs e )
{
URLForm form = new URLForm( );
form.Description = "Enter URL of an updating JPEG from a web camera:";
form.URLs = new string[]
{
"http://195.243.185.195/axis-cgi/jpg/image.cgi?camera=1",
};
if ( form.ShowDialog( this ) == DialogResult.OK )
{
// create video source
JPEGStream jpegSource = new JPEGStream( form.URL );
// open it
OpenVideoSource( jpegSource );
}
}
// Open MJPEG URL
private void openMJPEGURLToolStripMenuItem_Click( object sender, EventArgs e )
{
URLForm form = new URLForm( );
form.Description = "Enter URL of an MJPEG video stream:";
form.URLs = new string[]
{
"http://admin#192.168.1.239:81/videostream.cgi?rate=11",
"mjpegSource by mobby"
};
if ( form.ShowDialog( this ) == DialogResult.OK )
{
// create video source
MJPEGStream mjpegSource = new MJPEGStream( form.URL );
// open it
OpenVideoSource( mjpegSource );
}
}
// Open video source
private void OpenVideoSource( IVideoSource source )
{
// set busy cursor
this.Cursor = Cursors.WaitCursor;
// stop current video source
//CloseCurrentVideoSource( );
// start new video source
videoSourcePlayer.VideoSource = source;
videoSourcePlayer.Start( );
// reset stop watch
stopWatch = null;
// start timer
timer.Start( );
this.Cursor = Cursors.Default;
}
// Close video source if it is running
private void CloseCurrentVideoSource( )
{
if ( videoSourcePlayer.VideoSource != null )
{
videoSourcePlayer.SignalToStop( );
// wait ~ 3 seconds
for ( int i = 0; i < 30; i++ )
{
if ( !videoSourcePlayer.IsRunning )
break;
System.Threading.Thread.Sleep( 100 );
}
if ( videoSourcePlayer.IsRunning )
{
videoSourcePlayer.Stop( );
}
videoSourcePlayer.VideoSource = null;
}
}
// New frame received by the player
private void videoSourcePlayer_NewFrame( object sender, ref Bitmap image )
{
DateTime now = DateTime.Now;
Graphics g = Graphics.FromImage( image );
// paint current time
SolidBrush brush = new SolidBrush( Color.Red );
g.DrawString( now.ToString( ), this.Font, brush, new PointF( 5, 5 ) );
brush.Dispose( );
g.Dispose( );
}
// On timer event - gather statistics
private void timer_Tick( object sender, EventArgs e )
{
IVideoSource videoSource = videoSourcePlayer.VideoSource;
if ( videoSource != null )
{
// get number of frames since the last timer tick
int framesReceived = videoSource.FramesReceived;
if ( stopWatch == null )
{
stopWatch = new Stopwatch( );
stopWatch.Start( );
}
else
{
stopWatch.Stop( );
float fps = 1000.0f * framesReceived / stopWatch.ElapsedMilliseconds;
fpsLabel.Text = fps.ToString( "F2" ) + " fps";
stopWatch.Reset( );
stopWatch.Start( );
}
}
}
public static bool SetAllowUnsafeHeaderParsing20()
{
//Get the assembly that contains the internal class
Assembly aNetAssembly = Assembly.GetAssembly(typeof(System.Net.Configuration.SettingsSection));
if (aNetAssembly != null)
{
//Use the assembly in order to get the internal type for the internal class
Type aSettingsType = aNetAssembly.GetType("System.Net.Configuration.SettingsSectionInternal");
if (aSettingsType != null)
{
//Use the internal static property to get an instance of the internal settings class.
//If the static instance isn't created allready the property will create it for us.
object anInstance = aSettingsType.InvokeMember("Section",
BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.NonPublic, null, null, new object[] { });
if (anInstance != null)
{
//Locate the private bool field that tells the framework is unsafe header parsing should be allowed or not
FieldInfo aUseUnsafeHeaderParsing = aSettingsType.GetField("useUnsafeHeaderParsing", BindingFlags.NonPublic | BindingFlags.Instance);
if (aUseUnsafeHeaderParsing != null)
{
aUseUnsafeHeaderParsing.SetValue(anInstance, true);
return true;
}
}
}
}
return false;
}
}
}
From google i added some open ip cameras and there video stream was captured and worked fine but my camera returns Error 401. Then I used ISPY software recently made by Sean Tearney that was built using the same Aforge library and it captures my camera's video stream:p. Now i do not know what's wrong with the simple player's coding.Kindly if some one can help me get the video stream from camera. Thankyou
most likely because the camera is protected by password. to enable you to view the stream, please provide username and password to the camera you try to access.
for jpeg stream:
jpegSource.Login = "your username";
jpegSource.Password = "your password";
for mjpeg stream:
mjpegSource.Login = "your username";
mjpegSource.Password = "your password";

Big image with many icon or one image one icon?

I have to display around 100 icons (each 50x50) in Button. I am downloading big png Image which contains all 100 icons, then I create each icon using Image.subImage() method.
But my application getting OutOfMemoryError.
I am thinking about 2 solution for this:
download 100 icons as tar(combined into single) file. So i can
create icon one by one. Big Image need not to be in memory till I
create last icon.
Download big Image but don't create small icon.Then override Button
class to paint image (icon) from big Image.
Which is the best solution? or do you have any other solution for this problem.
LWUIT is designed for small devices, and so should you design your code. So a big image is not a good idea.
You should really use seperate images. and only keep those in memory that you can see. Or you will keep running into outofmemory errors.
I would handle it like this.
Get a cachemap.
if you want an image, check if it isn't already in the cachemap.
if it is, use the image from the cachemap
if it isn't download it and put the image in the cachemap.
when you're out of memory, remove the last image from the cachemap and download the new.
if (imageCache.get(url) != null) {
//#debug
System.out.println("Get cached image from: " + url);
asyncImage.setImage((Image) imageCache.get(url));
asyncImage.setQueued(false);
} else {
//#debug
System.out.println("Start download image from:" + url);
map.put(url, asyncImage);
ImageDownloadService d = new ImageDownloadService(url, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
NetworkEvent n = (NetworkEvent) evt;
Image image = (Image) n.getMetaData();
String url = n.getConnectionRequest().getUrl();
AsyncImage asyncImage = (AsyncImage) ImageManager.this.map.get(url);
map.put(url, asyncImage);
asyncImage.setImage(image);
map.remove(url);
imageCache.put(url, asyncImage.getImage());
asyncImage.setQueued(false);
if (Display.getInstance().getCurrent() instanceof AsyncLoadable) {
((AsyncLoadable) Display.getInstance().getCurrent()).asyncLoaded();
} else {
Display.getInstance().getCurrent().repaint();
}
//#debug
System.out.println("Retrieved image from:" + url);
}
});
d.addResponseCodeListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
NetworkEvent n = (NetworkEvent) evt;
String url = n.getConnectionRequest().getUrl();
AsyncImage asyncImage = (AsyncImage) ImageManager.this.map.get(url);
asyncImage.setQueued(false);
map.remove(n.getConnectionRequest().getUrl());
//#debug
System.out.println("Failed image from:" + url);
}
});
NetworkManager.getInstance().addToQueue(d);

Resources