I have custom field with volume slider (just color line),
I want to update slider on trackpad movement, is there some other way
then invoking invalidate? Because this is realy slow for me,
a tried also invalidating only region but whit same result. So is there
some way how to repaint part of field without invalidate?
protected boolean navigationMovement(int dx, int dy, int status, int time) {
if (dx >0) {
if (value < maxValue) {
value++;
invalidate(xPosSlider + value*sliderStep, getHeight()/2 - SLIDER_HEIGHT/2, sliderStep, SLIDER_HEIGHT);
return true;
}
} else if (dx < 0) {
if (value > 0) {
value--;
invalidate();
return true;
}
}
return super.navigationMovement(dx, dy, status, time);
}
The first place to look is at your own code. Are you doing something time-consuming on the even thread that is preventing the paint operations from occurring in a timely manner? That's the likely problem.
Otherwise, you can try calling the paint method directly as shown here. But the best solution is to ensure that your event thread is not tied up doing work that should be done on a separate thread.
Related
been fighting with this problem for a good 3 hours now, and i figured it was finally time to ask some professionals.
My problem is that i want to make a scrollbar, and I've figured out that i want to make it by using two integers and then give every item in the list an ID, and then say that all the items that has an ID thats in between the two integers are going to be shown, and then afterwards make 2 buttons that will + or - the integers so you can "scroll" though the items.
So to realize this i decided to make dummy code, to see how i could work it out.
And for most part its working, however i have the problem now, that it seems that my draw function is refreshing the screen constantly (Even though I've put in a bool to make sure it woulden), and by doing that it keeps erasing the numbers I'm listing on the screen.
Heres the code:
List<int> test = new List<int>() {1,2,3,4,5,6,7 };
int low = 0;
int high = 3;
int count;
bool isDone = false;
public override void Draw(GameTime gameTime)
{
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null);
if (!isDone)
{
int posX = 20;
foreach (int nr in test)
{
if (count == high)
{
isDone = true;
break;
}
else
{
count++;
}
if (count >= low && count <= high)
{
posX += 20;
spriteBatch.DrawString(gameFont, nr.ToString(), new Vector2(posX, 20), Color.White);
}
}
}
spriteBatch.End();
}
Hopefully some of you clever folks can eye the mistake I've been missing.
Thanks in advance
~Etarnalazure.
You never reset your counter. Therefore, the numbers will be only visible in the first frame. Add
count = 0;
before the for-loop.
Furthermore, you might want to revise your structure. If you use a List<>, then every item already has its index. And you don't have to iterate over each and every item, if you use a for loop:
for(int i = low; i <= high; ++i)
{
var currentItem = list[i];
}
I am building a news ticker that needs to be implemented on Blackberry 5. When transitioning from one element to the next, I am looking at a fade out/fade in transition. Mostly because I am having trouble finding resources on creating animations in the Blackberry 5 reference.
the basic flow I am looking at is:
public void updateUI() {
//fade out
//set values
//fade in
}
So far I have all the UI elements contained inside a HorizontalFieldManager. I have tried digging through the Field and Graphics documents, but did not find what I was looking for.
Keep in mind, supporting Blackberry 5 is the client's requirement, not mine.
You need to handle animations explicitly, using a timer for transitions.
My typical solution is something like this (inside the paint() method):
final long time = System.currentTimeMillis();
final int alpha;
if (startFadeIn != 0) {
alpha = (int) Math.min((time - startFadeIn) / SPEED, 255);
if (alpha < 255) {
invalidate();
}
} else if (startFadeOut != 0) {
alpha = (int) Math.max(255 + (startFadeOut - time) / SPEED, 0);
if (alpha > 0) {
invalidate();
}
} else {
alpha = 255;
}
graphics.setGlobalAlpha(alpha);
It burns some CPU cycles (for a short time), but it works.
I am working on an eBook app where I need to transition the screens from left to right and right to left. I tried many samples that I've found, but I am not successful. How do I change the screen frequently when user clicks on the screen from left to right and right to left. What is the basic idea for transition of pages. I went through the Developer Support Forum thread "page-flip effect" looking for a solution, but I can't see it.
The following code is not logical. In which position do I have to implement flip effect for flipping pages in the screen and how to implement it?
public class TransitionScreen extends FullScreen implements Runnable{
private int angle = 0;
Bitmap fromBmp,toBmp;
public TransitionScreen(){
}
public TransitionScreen(AnimatableScreen from,AnimatableScreen to) {
fromBmp = new Bitmap(Display.getWidth(), Display.getHeight());
toBmp = new Bitmap(Display.getWidth(), Display.getHeight());
Graphics fromGraphics = Graphics.create(fromBmp);
Graphics toGraphics = Graphics.create(toBmp);
Object eventLock = getApplication().getEventLock();
synchronized(eventLock) {
from.drawAnimationBitmap(fromGraphics);
to.drawAnimationBitmap(toGraphics);
// Interpolate myOffset to target
// Set animating = false if myOffset = target
invalidate();
}
try {
synchronized (Application.getEventLock()) {
Ui.getUiEngine().suspendPainting(true);
}
} catch (final Exception ex) {
}
}
protected void paint(Graphics g){
//control x,y positions of the bitmaps in the timer task and the paint will just paint where they go
g.drawBitmap(0,0, 360,
480, toBmp, 0, 0);
g.drawBitmap(0, 0, 360,
480, fromBmp, 0, 0);
// invalidate();
}
protected boolean touchEvent(TouchEvent event) {
if (!this.isFocus())
return true;
if (event.getEvent() == TouchEvent.CLICK) {
// invalidate();
}
return super.touchEvent(event);
}
}
Assuming you're working with version 5.0 or later of the OS, this page has a simple example:
http://docs.blackberry.com/en/developers/deliverables/11958/Screen_transitions_detailed_overview_806391_11.jsp
From where did you get the code sample posted in your question? That code does not appear to be close to working.
Update: you can actually animate transitions like this yourself fairly simply. Assuming you know how to use the Timer class, you basically have a class-level variable that stores the current x-position of your first Bitmap (the variable would have a value of 0 initially). In each timer tick, you subtract some amount from the x-position (however many pixels you want it to move each tick) and then call invalidate();.
In each call to the paint method, then, you just draw the first bitmap using the x-position variable for the call's x parameter, and draw the second bitmap using the x-position variable plus the width of the first bitmap. The resulting effect is to see the first bitmap slide off to the left while the second slides in from the right.
A caveat : Because this is java (which means the timer events are not real-time - they're not guaranteed to occur when you want them to), this animation will be kind of erratic and unsmooth. The best way to get smooth animation like this is to pre-render your animation cells (where each is a progressive combination of the two bitmaps you're transitioning between), so that in the paint method you're just drawing a single pre-rendered bitmap.
I'm working on a windows phone 7 project, with silverlight, and i'm trying to show 4 images in sequence to give the user the feeling of a short movie.
I have 4 urls pointing to 4 different jpeg images, and I'm using an Image control to show these jpeg in sequence.
The way I'm trying to achieve this is by doing:
private void RetrieveImages()
{
image1.ImageOpened += new EventHandler<RoutedEventArgs>(image1_ImageOpened);
frameNumber = 0;
gotoNextImage();
}
void image1_ImageOpened(object sender, RoutedEventArgs e)
{
System.Threading.Thread.Sleep(400);
gotoNextImage();
}
private void gotoNextImage()
{
if (frameNumber < 4)
{
webBrowser1.Dispatcher.BeginInvoke(()=> {
image1.Source = new System.Windows.Media.Imaging.BitmapImage(new Uri(cam.framesUrl[frameNumber]));
frameNumber++;
});
}
else
{
image1.ImageOpened -= image1_ImageOpened;
}
}
But this just don't work as expected. I'm sure I'm missing something about how to interact with the UI.
Can anyone point me in the right direction?
Which is the best way to achieve this?
Edited:
I'll explain better what's wrong with my code... probably it's unclear what happens.
I don't get any error with my code, but I don't see the "movie effect" too. It just show 1 single image, without iterating between the image collection.
I think it's a threading problem... kind of I'm not doing the right thing in the right thread to see the UI updating as expected...
This seams to work best.
xaml
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="YourNamspace.YourClass"
d:DesignWidth="24"
d:DesignHeight="24">
<Grid x:Name="LayoutRoot">
<Image Name="YourImageName" Stretch="Fill" Source="YourPath" ImageOpened="onImageOpened"/>
</Grid>
</UserControl>
C#
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
namespace YourNameSpace
{
public partial class YourClass : UserControl
{
public int FirstImageIndex = 1;
public int LastImageIndex = 1000;
public int CurrentImageIndex = 1;
public YourClass()
{
InitializeComponent();
}
private void onImageOpened(object sender, System.Windows.RoutedEventArgs e)
{
Thread.Sleep(1000);
CurrentImageIndex = ( CurrentImageIndex == LastImageIndex ) ? FirstImageIndex : CurrentImageIndex++;
YourImageName.Source = new BitmapImage(new Uri("Your/path/to/image"+CurrentImageIndex+".jpg"), UriKind.RelativeOrAbsolute);
}
}
}
Hope that helps. I am pretty new to Silverlight.
So far the best way is to define the image as a resource. Via converter setting the image source.
But, your code should work fine as well. Try setting UriKind.RelativeOrAbsolute may be that should help. Because, this is the most common area while setting image source causes issue
HTH
Ok, I figured it out, and I think I also find a nice solution :) IMHO
I basically bound the Image.source to a proprerty of my class (that now extends INotifyPropertyChanged). But this gave me some issue about the transiction between images: since they were downloaded from internet there was a black images occurring between one images an the next one... but only the first time (i'm looping on a set of 4 images, looks like the video repeat), 'cause after that the images are cached.
So, what I've done is to cache the images the first time, without displaying the right Image control, but displaying instead another Image control (or whatever else) which says to the user "I'm loading".
For handle this scenario I've created a custom event:
public delegate void FramesPrefetchedEventHanlder();
public event FramesPrefetchedEventHanlder FramesPrefetched;
Now let's take a look at the RetrieveImages method:
private void RetrieveImages()
{
frameNumber = 0;
currentCycle = 0;
// set e very short interval, used for prefetching frames images
timer.Interval = new TimeSpan(0, 0, 0, 0, 10);
timer.Tick += (sender, e) => gotoNextImage();
// defines what is going to happen when the prefetching is done
this.FramesPrefetched += () =>
{
// hide the "wait" image and show the "movie" one
imageLoading.Opacity = 0;
image1.Opacity = 1;
// set the timer with a proper interval to render like a short movie
timer.Interval = new TimeSpan(0, 0, 0, 0, 400);
};
// when a frame is loaded in the main Image control, the timer restart
image1.ImageOpened += (s, e) =>
{
if (currentCycle <= cycles) timer.Start();
};
// start the loading (and showing) frames images process
gotoNextImage();
}
Ok, now what we need to handle is the step by step loading of the image and communicate when we finished the prefetching phase:
private void gotoNextImage()
{
timer.Stop();
if (frameNumber < 4)
{
CurrentFrame = new System.Windows.Media.Imaging.BitmapImage(new Uri(cam.framesUrl[frameNumber]));
frameNumber++;
}
else
{
// repeat the frame's sequence for maxCycles times
if (currentCycle < maxCycles)
{
frameNumber = 0;
currentCycle++;
// after the first cycle through the frames, raise the FramesPrefetched event
if (currentCycle == 1)
{
FramesPrefetchedEventHanlder handler = FramesPrefetched;
if (handler != null) handler();
}
// step over to next frame
gotoNextImage();
}
}
}
This works pretty fine to me... but since I'm new to Silverlight and Windows Phone 7 developement, any suggestion for improvement is welcome.
I have a custom object list field with implemented scrolling routine.
public int moveFocus(int amount, int status, int time) {
invalidate(getSelectedIndex());
int unused = super.moveFocus(amount, status, time);
return Math.abs(unused) + 1;
}
public boolean navigationMovement(int dx, int dy, int status, int time) {
if (dy > 0) {
if (selectedIndex < getSize() - 1) {
setSelectedIndex(selectedIndex + 1);
}
} else if (dy < 0) {
if (selectedIndex > 0) {
setSelectedIndex(selectedIndex - 1);
}
}
return true;
}
Scrolling works fine when I scroll with trackwheel, but gets broken when app is launched on a device with trackball. I figured out that problem lays in framework method moveFocus which is not called at all when I scroll with trackball.
Issue has been resolved by changing return true; to return false; in navigationMovement method.
This makes a good example of a buggy api design. When you see some gui event handling method like this returning boolean your first and only suggestion is that the return value means the event has been consumed. But in case of navigationMovement method you're wrong. Here's an extract from JDE 4.2.1 javadoc
Parameters:
dx - Magnitude of navigational motion: negative for a move left and
postive for a move right.
dy - Magnitude of navigational motion: negative for an upwards move,
and positive for a downwards move.
status - Bitfield of values defined by KeypadListener.
time - Number of milliseconds since the device was turned on.
Returns:
False (classes that extend Field must override this method to provide
specific handling).
Bravo RIM!