My program is fullscreen application. On start I use some checks and if something is wrong, error dialog is shown. I need two windows (main fullscreen, and dialog) were here and all graphics were ok.
When I use this code:
primaryStage.show();
/*..some checks*/
dialogStage.show();
.. there is no fullscreen. It's somehow overlapped by other windows.
This one works better:
stage.setOnShown( new EventHandler<WindowEvent>() {
public void handle(WindowEvent windowEvent) {
/*..some checks*/
dialogStage.show();
}
});
primaryStage.show();
But... I can see task panel from Windows. It becomes hidden when dialog is closed.
And also I can see default java icon there. Although I've set custom icon before.
Looks like setOnShown() is called before all graphical updates are done.
Is there any event or something to know it?
I also tried Timeline from animation to call a small delay. But without success.
The same with calling dialog from additional thread (with Platform.runLater() of course :) ). This way fullscreen hides at all.
Maybe on JavaFX8 things are better?
Related
I am having issues with my app returning to the foreground every time the user presses the back button. I believe this may be because there is a sound playing module that restarts the activity although this is just my hypothesis. However whenever I press the home (middle) button the app is sent to the background and everything works accordingly. I would like to emulate this functionality by capturing the back press event and handle it in a similar manner to the home button. While navigating the source, i've found the following handler in
android/reactnativenavigation/layouts/SingleScreenLayout.java
#Override
public boolean onBackPressed() {
if (handleBackInJs()) {
return true;
}
if (stack.canPop()) {
stack.pop(true, System.currentTimeMillis());
EventBus.instance.post(new ScreenChangedEvent(stack.peek().getScreenParams()));
return true;
} else {
return false;
}
}
I can understand at a glance what is being done however I am not very familiar with Java and don't want to introduce any bugs involving the native side of the app, could anyone kindly point out what I would need to modify?
So, you need to capture "the hardware back button" press not the home button right?
check here for the react-native way of doing it
I have a requirement to generate a bitmap out of an EditText and then perform some manipulations on it.
My main concern is not to call View.buildDrawingCache() method on the UI thread and possibly block it, especially when talking about large screens (i.e. Nexus 10) since the EditText will occupy about 80% of the available screen size.
I execute Runnables inside a ThreadPoolExecutor, those will inflate dummy views on a worker thread and set all the required attributes to them, then simply call buildDrawingCache() & getDrawingCache() to generate a bitmap.
This works perfect on some devices yet recently I have encountered a few devices that crash with the following message:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
I understand why this happens, as some phones must have modified implementation for EditText that creates a Handler and thus requires Looper.prepare() to be called first.
From what I've read online there is no issue with calling Looper.prepare() inside a worker thread though some stated it is highly unrecommended yet I could not find a reason for that.
Other than that, most posts related to this issue state you are not supposed to inflate views inside a background thread, probably due to the following from Android's official documentation (Processes and Threads):
"Do not access the Android UI toolkit from outside the UI thread"
What is the recommended approach to dealing with this problem?
Is there any harm in calling build/get drawingcache from the main thread? (performance-wise)
Will calling Looper.prepare() inside my worker thread solve this problem?
EDIT
Just to elaborate on my specific requirement, I have a user-interface consisting of an ImageView and a custom EditText on top of it, the EditText can change it's font and color according to the user selection, it can be zoomed in/out using "pinch to zoom" gesture and can also be dragged around to allow the user to reposition it on top of the image.
Eventually what I do is create a dummy view inside my worker thread using the exact same values (width, height, position) it currently has on the UI and then generate it's drawingcache, the original image's bitmap is decoded again from a local file.
Once the two bitmaps are ready I merge them into a single bitmap for future use.
So to put it simple, is there anything wrong with executing the following code (from within a background thread):
Call Looper.prepare()
Create a new view with application context, call measure() & layout() manually and then build+get drawingcache from it, i.e.:
Looper.prepare();
EditText view = new EditText(appContext);
view.setText("some text");
view.setLayoutParams(layoutParams);
view.measure(
View.MeasureSpec.makeMeasureSpec(targetWidth, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(targetHeight, View.MeasureSpec.EXACTLY));
view.layout(0, 0, targetWidth, targetHeight);
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
How does this apply to the restriction with not accessing the Android UI toolkit from outside the UI thread, what could possibly go wrong?
In your case, you can do it of course, but be carefull only reading values from UI data, to avoid synchronizations bug.
Also you should not recreate the EditText from the background thread, it will be more efficient to directly access the already existant one instead:
Looper.prepare();
myEditText.setDrawingCacheEnabled(true);
Bitmap bitmap = myEditText.getDrawingCache();
If your question is : why it is not recommanded by android guidelines, here is a good SO answer to your question.
Calling View.buildDrawingCache() calls Bitmap.nativeCreate which can be a large allocation, so yes, it can be potentially harmful to run on main thread. I don't see a problem with calling Looper.prepare() in your background thread. However, it's unclear what you are trying to achieve and there may be a better solution to your problem.
The reason you are not supposed to the UI toolkit from other threads is that it is not written to be thread safe it is written under the assumption that only one thread runs it. This means it's really hard to tell what can go wrong, the bad effects, if any, will mostly happen in an un-repeatable due to specific timing of threads.
Your description of what you are trying to do it not too clear. In your case, I would just allocate a large bitmap, and draw text into it. Why are you using the EditText in the first place ? It seems like a kind of a hack, and hacks tend to break eventually.
Why View.buildDrawingCache()? What about using View.draw(Canvas canvas) to manually render to a Canvas backed by a Bitmap? Method seems simple enough to not cause problems on background threads.
EditText edit = (EditText)findViewById(R.id.edit);
edit.buildDrawingCache();
ImageView img = (ImageView)findViewById(R.id.test);
img.setImageBitmap(edit.getDrawingCache());
Lalit when you try to build the cache in the onCreate method, the drawing hasn't happened yet so the drawingCache should have nothing. Either put the buildDrawingChache method in the onClick method. Or use the following code in onCreate.
ViewTreeObserver vto = editText.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
editText.buildDrawingCache();
}
});
I also encountered this error a few times already:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
my solution:
new Thread(new Runnable(){
#Override
public void run(){
//add implementations that DOES NOT AFFECT the UI here
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run(){
//manage your edittext and Other UIs here
}
});
}
}).start();
just create a handler inside your worker thread to apply data changes to your UI
I have a Notes-like app: UITableViewController showing up individual notes by pushing them onto navigation stack.
The problem arises when I have UITextView with the FirstResponder status (keyboard is shown) and I touch Back button. The current view controller is dismissed with the animation as expected, BUT the navigation bar is broken now! If I press any of the bar buttons, it will cause EXC_BAD_ACCESS.
I would say that it was not transitioned properly. The table VC is broken somehow as well, as it may appear empty on further manipulations... Very strange behaviour!
By the way, it did not cause any problems with iOS5 and iOS6, but there I used a custom chevron Back button.
I've checked the standard Notes app and it works like a charm.
What is the trick?
Thanks a lot for your advice!
EXC_BAD_ACCESS means you are trying to access an object that has been deallocated. Best thing you can do to trace this is enabling NSZombie, it will tell you what released object is being sent a message (aka EXC_BAD_ACCESS).
You can get how to enable it from here.
I got it and will try to explain to help somebody else to save their day...
EXC_BAD_ACCESS was raised because UITableViewController was not properly transitioned to during Back pop-animation (its viewWillAppear: and viewDidAppear: method were not triggered at all).
In its turn, the animation was not properly performed, as popViewControllerAnimated: was called twice or even more times: 1) as part of the system Back-button callback; 2) inside textViewDidEndEditing: in case no text was entered.
The solution is to check whether the back button has been pressed before calling popViewControllerAnimated:. The trick is to check if the detail-view controller is still in the navigation stack.
Here is the helper method:
-(void) returnToTheListOfRecords {
self.textView.delegate = nil; // this is to avoid the second call of `textViewDidEndEditing:`
if ([self.navigationController.viewControllers indexOfObject:self.delegate]==NSNotFound) {
// Back button has been pressed.
} else {
[self.navigationController popViewControllerAnimated:YES];
}
}
The problem happens on iOS7 only due to its brand-new animation.
According to the documentation, Display.setCurrent doesn't work if the current displayable is an alert. This is a problem as I would like to pop up another alert when the user selects a command. Does anyone know how to work around this so that we can go from one alert to another? I am using CLDC 1.0 and MIDP 2.0.
Additional Information
The spec does allow us to edit an alert while it is on screen, but some Nokia phones don't handle it well at all. So I am now trying to go from the alert to a blank canvas, then back to the alert. Of course I don't want the user to interact with the previous canvas, so it seems that I am forced to create a new blank canvas. As a sidenote, this has the slight disadvantage of looking worse on phones which still have the previous screen when an alert is shown.
The bigger problem is how to transition from the blank canvas back to an alert once the canvas is loaded. Testing on the Motorola emulator revealed that showNotify is not called after returning from an alert to the previous screen. I guess I could create the next alert in the paint method, but this seems like a ugly hack.
OK, so your problem is that you can't set it up to do:
Display.setCurrent(alert1, alert2);
and
Display.setCurrent(alert2);
is also not possible if the current Displayable is already alert1.
So how about put an intermediate Displayable item that is blank and that immediately changes to the next alert? Assuming the current Displayable is alert1, like this in your alert1's command block:
Display.setCurrent(blankForm);
Display.setCurrent(alert2);
That should work assuming you are not using the default 'Dismiss' command. So basically it goes from alert1->(blankForm->alert2).
I couldn't find a way around this, so I just used the paint hack.
public class AlertPage extends Canvas{
MIDlet midlet;
Alert alert;
private AlertPage(MIDlet midlet){
this.midlet=midlet;
}
protected void paint(Graphics arg0){
//Yep, this is a hack, but showNotify doesn't seem to work well for Motorola
if(alert!=null){
Display d=Display.getDisplay(midlet);
d.setCurrent(alert);
alert=null;
}
}
public static void showAlert(MIDlet m, Alert a){
AlertPage page=new AlertPage(m);
Display d=Display.getDisplay(m);
page.alert=a;
d.setCurrent(page);
}
}
I have a C++/CLI System::Windows::Forms::UserControl derived control which should only redraw (a small portion of) itself as new data is fed into it. For some reason though, the OnPaint mechanism is being called even when there's nothing to cause it external to the app.
Here's a snippet:
void Spectrogram::OnPaint(System::Windows::Forms::PaintEventArgs ^e)
{
// Overidden to stop the background being painted(?)
}
void Spectrogram::AddNewFFTData( float* data, int fataWidth )
{
Graphics^ gfx = CreateGraphics();
//now do some drawing
gfx->Dispose();
}
So I call the add data method to add some new data which should in theory write over the previous entry (which clears some highlighting) and write the new entry.
Back in the day I used to develop MFC/OpenGL apps and one of the first things I'd do would be to override the OnEraseBackground method. As far as I can see though, there's no obvious way of stopping it being erased. What have I missed?
You may be looking for Control.OnPaintBackground(). I've had to override that to do nothing for a custom control I wrote to bring a legacy MFC control into a Winforms project. Otherwise it would paint the background on top of the MFC control's paint job.
Essentially, in the .cpp:
void MyControl::OnPaintBackground(System::Windows::Forms::PaintEventArgs ^pevent)
{
// Do nothing, we don't want to paint over the native control.
// You may want to do something a little fancier for DesignMode
// if you use the winforms designer, though.
}
On the prototype:
protected:
void virtual OnPaintBackground(System::Windows::Forms::PaintEventArgs ^pevent) override;
What rectangle is being passed in to you via the event args? Is the entire control being invalidated, or just a portion of it?
Maybe it's a statement like this in the Form's constructor:
//do own background painting
this.SetStyle(ControlStyles.Opaque, true);
I think that prevents OnPaintBackground being invoked at all: so you don't need to override OnPaintBackground, and instead you can erase the background (or not) yourself in your OnPaint.
I did some stuff with the OnPaint lately (C#, if that matters), and I noticed it literally is drawn when a area of the control is revealed.
A better solution is to draw on a cached Bitmap, and draw it to the control every time dotNet asks for it.