So there's been a new "feature" in the flash player since version 10.1, which reduces the player's framerate to 2 fps when the application window is out of view. This is good news for performance, but it can break some functionality, such as the Timer class.
I have an application which uses a Timer to display a countdown. Given the nature of the application, it is required for the Timer to complete its countdown even if the user is not there to see it. Imagine that you need to give the user only 10 seconds to perform a task. If the user minimizes the window halfway through the counter, they can take as much time as they want and still have 5 seconds left when they return to the window. This apparently can not be avoided with the newer flash players.
In Air applications there is the backgroundFrameRate property which can be set to prevent this behavior, but this is part of the WindowedApplication class, so it seems that it is not available in a web application. Does anyone know a way to keep a constant frame rate even when the window is not visible? Thanks
Setting the wmode parameter of the embedded swf to opaque will prevent the framerate throttling.
Brian
I've not tried myself, but maybe you can try to force the framerate onDeactivate:
stage.addEventListener(Event.DEACTIVATE, onDeactivate);
function onDeactivate (e:Event):void
{
//eg myFrameRate=24
stage.frameRate = myFrameRate;
}
Let me know if this works.
Testing with:
private var numer:int = 0;
private var prevNumer:int = 0;
private var timer:Timer = new Timer( 1000, 0 )
[...]
var tf:TextField = new TextField ();
addChild (tf);
addEventListener ( Event.ENTER_FRAME, onEnterFrame )
timer.addEventListener (TimerEvent.TIMER, onTimer )
timer.start()
function onTimer ( e:TimerEvent ):void
{ tf.appendText (' ' + (numer - prevNumer)); prevNumer = numer;}
function onEnterFrame ( e:Event ):void { numer++ }
shows clearly, that when You see the flash, tf appends numbers equal to Your FPS. If timer would get changed together with FPS, You wouldn't see a difference when minimizing a window. But, coming back You see 2 2 2 2 2, that is, FPS dropped to 2.
onDeactivate solution by AsTheWormTurns doesn't work. Event is fired, but fps not changed.
wmode=opaque solution by Mr Brian Bishop doesn't work too
something obvious to try: change onEnterFrame function to set FPS:
function onEnterFrame ( e:Event ):void { numer++; stage.frameRate = 30 }
Obviously You can't set FPS when flash is not visible! Well, You can't set FPS unless You set it to 1.
Workaround to Your problem is simple, just make another timer similar to this above but with additional conditional:
function onTimer ( e:TimerEvent ):void {
if ( numer - prevNumer == 2 ) adjustOriginalTimer();
tf.appendText (' ' + (numer - prevNumer)); prevNumer = numer;
}
E: You can read about it here: http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-8000.html
Related
In my Uno test project, it takes about 4 seconds to load 50 images into an ItemsWrapGrid on the UWP platform. The same images take 225 seconds (3 minute 45 seconds) to load into a WrapPanel. Since the only difference in the code is ItemsWrapGrid or WrapPanel, I'm thinking the problem is the WrapPanel, but I can't be sure, it could be in how the platforms implement the <Image ItemsSource=""/.
I don't have any experience with .wasm so I don't know if this is expected (is it?). Is there something I can do to Optimize for wasm?
or any other thoughts? 4- minutes is just not acceptable compared to about 4 seconds.
Thanks
Thanks for asking if I could repro in Uno Playground. I was unaware of the site.
I was NOT ABLE to repro on the playground, which led me to investigate other possibilities.
I have resolved the issue.
My design pattern was to define a single ObservableCollection without a property change notification:
public ObservableCollection<PictureViewModel> Pictures {get;set }
I would bind that to my UserControl and update by Pictures.Clear().
This is my snippet that resulted in the long render time:
List<Picture> PictList = await DataService.GetPicturesByEvent(this.SelectedEvent.EvtKey, clubkey, skipPosition, this.PagingViewModel.PageSize);
List<PictureViewModel> PictVMList = mapper.Map<List<Picture>, List<PictureViewModel>>(PictList);
if (PictVMList != null && this.SelectedEvent != null && !string.IsNullOrEmpty(SelectedEvent.FilePath))
{
this.Pictures.Clear();
foreach (PictureViewModel item in PictVMList)
{
item.Parent = this;
item.SetURL(SelectedEvent);
this.Pictures.Add(item);
}
this.SelectedPicture = PictVMList.Count > 0 ? PictVMList.First() : null;
}
To resolve the long render time. I:
Made my ObservableCollection observable.
Removed all instances of Picture.Clear();
Created a new ObservableCollection whenever it needed updating.
The Resolved code snippet is:
List<Picture> PictList = await DataService.GetPicturesByEvent(this.SelectedEvent.EvtKey, clubkey, skipPosition, this.PagingViewModel.PageSize);
List<PictureViewModel> PictVMList = mapper.Map<List<Picture>, List<PictureViewModel>>(PictList);
if (PictVMList != null && this.SelectedEvent != null && !string.IsNullOrEmpty(SelectedEvent.FilePath))
{
foreach (PictureViewModel item in PictVMList)
{
item.Parent = this;
item.SetURL(SelectedEvent);
}
this.SelectedPicture = PictVMList.Count > 0 ? PictVMList.First() : null;
}
Pictures = new ObservableCollection<PictureViewModel>(PictVMList);
I don't understand why my initial code pattern did not work as expected, but can live with adding an OnPropertyChanged("Pictures") notification.
As of Uno 3.10, ItemWrapGrid is not supported on WebAssembly. Using the WrapPanel control will force the materialization of all the items in the list, making the performance particularly slow.
You're not specifying which control you're using as a panel, but if you're using a ListView control, the virtualization will be enabled, though not with the layout wrapping that you need.
If you want virtualizing grid-like layouts, you can also use the ItemsRepeater control, and its layouts (e.g. FlowLayout, StackLayout, or WCT's WrapLayout).
I have a function that looks like the following
void MainWindow::CreateEnvironment()
{
MdiWindow* sub = createSubWindow();
MyQTWidget* widget = CreateWidget();
..
..
}
I want that during this function a progress bar will be shown at the beggining and will close at the end of this function.
However adding
void MainWindow::CreateEnvironment()
{
**progressBarDialog->show();**
MdiWindow* sub = createSubWindow();
MyQTWidget* widget = CreateWidget();
..
..
**progressBarDialog->hide();**
}
Does not work, maybe because the function needs to exit first or something.
What is the best way to do this?
I assume that you use QProgressDialog?
You need to first setup the dialog with the correct number of steps you expect, how long you want to wait before it actually shows and more importantly: you need to call setValue() to update the progress bar.
Here is an example of how I would solve that (as far as I understand it)
void MainWindow::CreateEnvironment()
{
auto bar = new QProgressBarDialog(this);
bar->setLabelText(tr("Creating Environment..."));
bar->setCancelButton(nullptr); // No cancel button
bar->setRange(0, 10); // Let's say you have 10 steps
bar->setMinimumDuration(100); // If it takes more than 0.1 sec -> show the dialog
bar->setValue(0);
MdiWindow* sub = createSubWindow();
bar->setValue(1);
MyQTWidget* widget = CreateWidget();
..
..
bar->setValue(10);
MyLastWidget* last = CreateLastWidget();
bar->deleteLater(); // Not needed anymore, let's get rid of it
}
And don't worry too much if the dialog never shows. Unless you're doing really heavy computation (such as allocating / initialising huge portion of memory), creating widgets is very fast and would finish before the 100ms times out.
EDIT: Another thing to be aware of: QProgressDialog is meant to work after the main event loop started. (That is after the call to app.exec() in your main())
If you plan to show call this function in the constructor of your MainWindow, the dialog might even never show up because the window itself is not fully created and operational.
If you intended to call this function later, when the main window is already displayed on screen and the user hit a New Document button of some sort: you can ignore this part of the answer.
EDIT 4:
EDIT 3
EDIT 2
string currentWindow = driver.CurrentWindowHandle;
driver.SwitchTo().Window("");
string childTitle = driver.Title;
driver.SwitchTo().Window(currentWindow);
string parentTitle = driver.Title;
the above code gives me the same title for parent window or child window.
EDIT:
<a id="ctl00_ctl00_Features_ctl03_lnkPage" class="title" target="_blank" href="websiteaddress">Stay Around</a>
how to verify the title of a newly window open and once i verified then close the opened new window?
so in my page I have a link and click on the link and it opens a new window and now I am not sure how to verify the title of that window.
here is what i have done so far.
GoToMysiteUrl();
IWebElement addtoList = driver.FindElement(By.XPath(_pageName));
addtoList.Click();
//it opens a new window
now i want to switch focus on the new window and verify the title and close the new window
back to the previous window.
The piece that most people miss when dealing with popup windows in IE is that a click on an element is asynchronous. That is to say, if you check the .WindowHandles property immediately after a click, you may lose the race condition, because you're checking for the existence of a new window before IE has had the chance to create it, and the driver has had a chance to register it exists.
Here's the C# code I would use to perform the same operation:
string foundHandle = null;
string originalWindowHandle = driver.CurrentWindowHandle;
// Get the list of existing window handles.
IList<string> existingHandles = driver.WindowHandles;
IWebElement addtoList = driver.FindElement(By.XPath(_pageName));
addtoList.Click();
// Use a timeout. Alternatively, you could use a WebDriverWait
// for this operation.
DateTime timeout = DateTime.Now.Add(TimeSpan.FromSeconds(5));
while(DateTime.Now < timeout)
{
// This method uses LINQ, so it presupposes you are running on
// .NET 3.5 or above. Alternatively, it's possible to do this
// without LINQ, but the code is more verbose.
IList<string> currentHandles = driver.WindowHandles;
IList<string> differentHandles = currentHandles.Except(existingHandles).ToList();
if (differentHandles.Count > 0)
{
// There will ordinarily only be one handle in this list,
// so it should be safe to return the first one here.
foundHandle = differentHandles[0];
break;
}
// Sleep for a very short period of time to prevent starving the driver thread.
System.Threading.Thread.Sleep(250);
}
if (string.IsNullOrEmpty(foundHandle))
{
throw new Exception("didn't find popup window within timeout");
}
driver.SwitchToWindow(foundHandle);
// Do whatever verification on the popup window you need to, then...
driver.Close();
// And switch back to the original window handle.
driver.SwitchToWindow(originalWindowHandle);
Incidentally, if you're using the .NET bindings, you have access to a PopupWindowFinder class in the WebDriver.Support.dll assembly, which uses a very similar approach to the locating popup windows. You may find that class meets your needs exactly, and can use it without modification.
GoToMysiteUrl();
IWebElement addtoList = driver.FindElement(By.XPath(_pageName));
addtoList.Click();
// Post above operation a new window would open as described in problem
// Get hold of Main window's handle
string currentWindow = Driver.CurrentWindowHandle;
// Switch to the newly opened window
Driver.SwitchTo().Window("Your Window Name");
// Perform required Actions/Assertions here and close the window
// Switch to Main window
Driver.SwitchTo().Window(currentWindow);
In flex component life cycle, after we make some change in a components property, invalidation methods schedules a call to methods like commitProperties, updateDisplayList, etc for some later time. I need to call the updateDisplayList instantaneously. Is there some direct way to do this.
Currently, both the labels are changed simultaneously after completion of the loop. Instead I need it to work like this, to first render the updated 'myButton1' label then enter the loop and then update myButton2's label. I know, it is elastic race track issue, but isn't there some way to achieve this ?
myButton1.label = 'New Label1' ;
// Some logic to forcibly make the screen reflect it
for (var i:int = 0; i < 500 ; i ++){
//a dummy loop
}
myButton2.label = 'New Label2' ;
You can use myButton1.validateNow() but it's use is discouraged, for you may end up having the same component update itself multiple times on the same frame.
Use validateNow() . But, I would use it sparingly. using invalidateDisplayList() will force updateDisplayList() to run on the next renderer event.
A render event happens on each frame. 24 frames happen each second by default for Flex. Are you sure need to change these values quicker?
I would set the label for myButton1, then put the remaining code into a separate method and call that method using callLater:
private function foo():void {
myButton1.label = 'New Label1';
this.callLater(bar);
}
private function bar():void {
for (var i:int = 0; i < 500 ; i ++){ //a dummy loop
}
myButton2.label = 'New Label2';
}
This way myButton1 will update to show the new label before going into your loop since callLater doesn't call bar until after the event queue is cleared, giving myButton1 a chance to update.
invalidateDisplayList() or valdiateNow() will do it for you however excess of using these will end up memory leaks.
I'm trying to read the width and height of a locally loaded image. This seems to work for images that do not exceed the dimensions limited by the Flash Player 10 (http://kb2.adobe.com/cps/496/cpsid_49662.html), but as soon as the images are bigger, the width and height remain 0. The strange thing is that now and then, I can read the dimension of these bigger images, but most of the times not. I understand that this might be because of the player limitation, but then I would at least expect the error to be consistent.
I want to check this since there is no use in loading such a big image as it will not be displayed anyway, but it would be good to provide a detailed error message to the user.
Any ideas on this?
Here's the code that I use to load the image locally and read the dimension:
private function chooseImageButton_clickHandler(event:Event):void {
var allowedTypes:String = "*.jpg;*.png";
m_uploadFileReference = new FileReference();
m_uploadFileReference.addEventListener(Event.SELECT, uploadFileReference_selectHandler);
m_uploadFileReference.addEventListener(Event.COMPLETE, uploadFileReference_completeHandler);
m_uploadFileReference.browse([new FileFilter("Image Files (" + allowedTypes + ")", allowedTypes)]);
}
private function uploadFileReference_selectHandler(event:Event):void {
m_uploadFileReference.load();
}
private function uploadFileReference_completeHandler(event:Event):void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
loader.loadBytes(m_uploadFileReference.data);
}
private function onImageLoaded(e:Event):void {
trace(e.target.content.width);
}
You can skip loading the entire image and just reading the headers with this class.
var je : JPGSizeExtractor = new JPGSizeExtractor( );
je.addEventListener( JPGSizeExtractor.PARSE_COMPLETE, sizeHandler );
je.extractSize( your_jpg_file.jpg );
function sizeHandler( e : Event ) : void {
trace( "Dimensions: " + je.width + " x " + je.height );
}
Should be both faster and more reliable.
I would at least expect the error to be consistent.
Well, at least Adobe are pretty clear on that point: "...if you choose to develop beyond these boundaries we cannot guarantee consistent behavior."
Could you perhaps upload your image to a php pre-processor? (Here's one from Google)