Dynamical update a textfield on live events - java

i am at the moment developing a Softphone with javafx. and i kind of a have problem capturing incoming call to a textfield. an example of my code is here.
an incoming call is with Joptionpane successful bt i had like to have the value appear in call textfield just like telephone.
Thank you.
public void telephoneNumbs(String numbers) {
String replace = numbers.replace("sip:", "").trim().replace(".", ""); // Incoming Call Numbers from Sip UA
if (!replace.isEmpty()) {
List<TelephoneObj> telephons;
telTextField.setText(null); //init it with null
costumDao = new CostumersDao(); // costumers DB
telephons = costumDao.getOrCompareTelfone(numbers);
for (TelephoneObj tmp : telephons) {
System.out.println("Test: " + tmp.getTelephoneNums); // am getting exactle what i need here from my Database
//or
JOptionPane.showMessageDialog(null,"incoming:"+ tmp.getTelephoneNums); // it show it during incoming calls
//here is the problem. it wouldnt show the Value on the Textfield
telTextField.setText(tmp.getTelephoneNums); //try to push that Value(Telephone number) to show in JFXTextfield/it cold be any other Textfields
}
}

Sooo much happy today it went well with after 2days of thinking how to solve this miserable life of not taking time to think.
I finally got the answer by using Task to solve the problem.
Task<Void> task = new Task<Void>() {
{
updateMessage("");
}
#Override
public Void call() throws Exception {
while (true) {
updateMessage(callee);
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
break;
}
}
return null;
}
};
//neuLabel.textProperty().bind(task.messageProperty());
kdAddrTel.textProperty().bind(task.messageProperty());
Thread th = new Thread(task);
th.setDaemon(true);
th.start();

Related

How to get every time messages from service to activity using runOnUiThread

I have been stuck with one problem. I need some people which check a part of my code and help me with problem and critize my code (I write code but I haven't people which can say this is wrong or something in this pattern)
Generally.
My service get message from bluetooth (HC-05) and I can see values in Log.d, in service.
A part code of my service which get message.
private class ConnectedThread extends Thread{
private final BluetoothSocket bluetoothSocket;
private final InputStream inputStream;
private final OutputStream outputStream;
public ConnectedThread(BluetoothSocket socket){
Log.d(TAG,"ConnectedThread: Starting");
bluetoothSocket=socket;
InputStream tmpInput = null;
OutputStream tmpOutput = null;
try{
tmpInput = bluetoothSocket.getInputStream();
tmpOutput = bluetoothSocket.getOutputStream();
}catch (IOException e){
e.printStackTrace();
active=false;
}
inputStream=tmpInput;
outputStream=tmpOutput;
}
#Override
public void run() {
byte[] buffer = new byte[1024];
int bytes;
while(active){
try {
bytes = inputStream.read(buffer);
final String comingMsg = new String(buffer,0,bytes);
Log.d(TAG,"InputStream: " + comingMsg);
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Message message = new Message();
message.obj = comingMsg;
message.what = 1; // I need it to prevent NullObjReference
Log.d(TAG,"Handler run(): " + message.obj);
mHandler.sendMessage(message);
}
});
}catch (IOException e){
Log.e(TAG,"Write: Error reading input." + e.getMessage());
active=false;
break;
}
}
}
...some code is hidden because it is diploma thesis
}
The problem is get message every time from this service to another activity where all is happen.
I tried a lot of things (with Threads,Looper,runOnUiThread, handleMessage and callback), checked a lot of posts in stackoverflow and I tried to combine with my project but all time I had nullobjectreference (for that i tried to use msg.what to check) , black screen when tried to move to my home activity (it is main) and update my textView or typical crash app.
Now I want only to get message from service to textview. When everything starts working fine, I want to parse string (for example 3 first chars) and send message to one of six textviews.
A part of codes from onCreate before method runThread() is started:
Log.d(TAG,"Check intent - result");
if(getIntent().getIntExtra("result",0)==RESULT_OK){
mDevice = getIntent().getExtras().getParcelable("bonded device");
startConnection(mDevice,MY_UUID);
Log.d(TAG,"Check is active service ");
checkIfActive();;
}
Log.d(TAG,"Check intent - connect_to_paired");
if(getIntent().getIntExtra("connect_to_paired",0)==RESULT_OK){
mDevice = getIntent().getExtras().getParcelable("bonded_paired_device");
startConnection(mDevice,MY_UUID);
Log.d(TAG,"Check is active service ");
checkIfActive();
}
public void checkIfActive(){
Log.d(TAG,"CheckIfActive: Started");
while(myBluetoothService.active!=true) {
Log.d(TAG,"CheckIfActive() active is "+ myBluetoothService.active);
if (myBluetoothService.active) {
Log.d(TAG, "CheckIfActive: Running method runOnUiThread - myBluetoothService.active is "+myBluetoothService.active);
runThread();
}
}
}
Method runThread() which should work everytime after connected with bluetooth device:
public void runThread(){
//I used there Thread but when connection was fail,
// method created multiply threads when I tried to connect next time
runOnUiThread(new Runnable() {
#Override
public void run() {
handler = new Handler(Looper.getMainLooper()){
#Override
public void handleMessage(Message msg) {
while (true) {
switch (msg.what) {
//when is one, service has messages to send
case 1:
String message = myBluetoothService.mHandler.obtainMessage().toString();
rearLeft.setText(message);
break;
default:
super.handleMessage(msg);
}
}
}
};
}
});
}
UPDATE:
Is it good idea ? Maybe I can put JSON Object to service to send message and in the HomeActivity, I can try get values from JSON. Is it fast ? I send a lot of data, because bluetooth receive data of distance from 4 ultrasound sensors in 4 times in lasts until few milliseconds, everytime.
Here is screen how sees my data in service when I have debug logs.
Next idea, but still nothing:
HomeActivity (my main)
public void runThread(){
runOnUiThread(new Runnable() {
#Override
public void run() {
//Looper.prepare();
new Handler() {
#Override
public void handleMessage(Message msg) {
rearLeft.setText(msg.obj.toString());
}
};
//Looper.loop();
//Log.d(TAG, myBluetoothService.mHandler.getLooper().toString());
//rearLeft.setText(myBluetoothService.mHandler.getLooper().toString());
}
});
}
Service which should send data from bluetooth to UI Thread is the same (Check first code).
Screen from HomeActivity where you can see 6 text views. Now I want put all text to one view which will be refresh by get next message.
Ok this post a bit help me to solve problem:
Sending a simple message from Service to Activity
Maybe this link could help another people.
Thanks for help, now understand why i should use broadcast receiver to do this.

Waiting until boolean value is changed without blocking main JavaFX thread?

I have been reading for hours about different multi-threading techniques for JavaFX and cannot seem to find what I'm looking for. The application being worked on is the "Messenger" which part of a bigger application to provide a trading marketplace for a game.
A breakdown of the process I am having trouble with:
A window with a 'Contact Seller' button is displayed
The user clicks 'Contact Seller', and the Messenger window should be displayed
Using the seller's name from the main window, the Messenger should check if a chat already exists with that name
If the chat already exists, get the index of that chat in the Messenger's ListView, and select the chat so the Messenger's text area is populated with the corresponding messages
If the chat doesn't exist, create one
The issue:
Chats are stored server-side
Messages between clients are stored in a message 'cache' on the server when being processed from one user to the other (they are sorted to their respective chats, inserted into the chats, and pushed to the database upon client disconnection)
Messages received on the client are stored locally in the respective chat
When the Messenger is opened, it requests a list of chats for the signed-in user
The server sends an ArrayList of chats, and upon receiving the client builds the Messenger's ListView with these objects
Now when I need to open the Messenger in order to 'Contact Seller', I need to make sure the sync with the server is complete. Without doing so, I won't be able to properly check if a chat already exists with that name since I won't have the most up-to-date list.
The 'RequestWorker' thread that handles incoming server messages is NOT on the JavaFX thread.
The RequestWorker 'gets' the Messenger instance if it is currently open, and populates the ListView with the newly received chat list. (This needs to happen on the JavaFX thread, since I am working in the Messenger GUI)
What I am trying to do is set a static AtomicBoolean syncInProgress to true when the Messenger initiates a sync upon being displayed. When the RequestWorker receives the latest list back from the server and finishes populating the Messengers ListView, it sets syncInProgress to false.
The sync takes longer than opening the Messenger and making it check if a chat exists. Doing it this way it has no items populated yet in the ListView and the method is ineffective.
Calling a while loop to wait until the boolean is changed, blocks the JavaFX thread which means the RequestWorker cannot do what it needs to in the JavaFX thread.
How can I continuously check for this variable to be set false, then continue to 'Contact Seller' once the ListView has been properly populated?
Contact Seller method: The while loop in here causes a block on the JavaFX thread, thus not enabling RequestWorker to properly populate the ListView.
public static void contactSeller(Messenger messenger, String destination, String itemName)
{
while (TarkovTrader.syncInProgress.get())
{
; // Wait until sync is complete to check the latest chat list for an existing chat
}
if (messenger.chatExists(destination))
{
// Chat exists, select the chat for the user
for (Chat openChat : messenger.chatListView.getItems())
{
if (openChat.getName(TarkovTrader.username).equals(destination))
{
messenger.chatListView.getSelectionModel().select(openChat);
messenger.unpackChatMessages(openChat.getMessages());
break;
}
}
}
else
{
messenger.buildNewChat(destination);
}
messenger.chatInput.setText("Hey " + destination + ". Interested in your '" + itemName + "'.");
messenger.chatInput.setOnMouseClicked(e -> messenger.chatInput.clear());
}
RequestWorker process chat block:
switch(receivedFromServer)
case "chatlist":
// Client requested a chat list, results were returned from the server, and now we need to populate the messenger list
ChatListForm chatlistform = (ChatListForm)processedRequest;
if (Messenger.isOpen)
{
FutureTask<Void> updateChatList = new FutureTask(() -> {
Messenger tempMessenger = trader.getMessenger();
int currentIndex = tempMessenger.chatListView.getSelectionModel().getSelectedIndex();
tempMessenger.populate(chatlistform.getChatList());
tempMessenger.chatListView.getSelectionModel().select(currentIndex);
}, null);
Platform.runLater(updateChatList); // RequestWorker needs access to the JavaFX application thread
try {
updateChatList.get(); // Wait until the ListView has been populated before setting 'syncInProgress' to false again
}
catch (InterruptedException e) {
Alert.display(null, "Sync interrupted.");
}
catch (ExecutionException e) {
Alert.display(null, "Sync failed.");
}
TarkovTrader.syncInProgress.compareAndSet(true, false); // The value of syncInProgress should be true, change to false. Sync complete
}
else
{
Platform.runLater(() -> Alert.display(null, "New chat received."));
TarkovTrader.syncInProgress.compareAndSet(true, false);
}
break;
Contact Seller button logic: If a messenger is not open, create it and pass to static contactSeller method to use.
contactButton.setOnAction(e -> {
Messenger messenger;
if (Messenger.isOpen)
{
// Get messenger
messenger = trader.getMessenger();
}
else
{
messenger = new Messenger(worker);
messenger.display();
trader.setMessenger(messenger);
}
Messenger.contactSeller(messenger, item.getUsername(), item.getName());
itemdisplay.close();
});
EDIT:
Partially using Slaw's idea (AtomicBoolean is still being used since I'm not sure how to do this without it), this is what I came up with...
public static void contactSeller(Messenger messenger, String destination, String itemName)
{
Task<Void> waitForSync = new Task<Void>() {
#Override
public Void call()
{
while (TarkovTrader.syncInProgress.get())
{
; // Wait until sync is complete
}
return null;
}
};
waitForSync.setOnSucceeded(e -> {
while (TarkovTrader.syncInProgress.get())
{
; // Wait until sync is complete to check the latest chat list for an existing chat
}
if (messenger.chatExists(destination))
{
// Chat exists, select the chat for the user
for (Chat openChat : messenger.chatListView.getItems())
{
if (openChat.getName(TarkovTrader.username).equals(destination))
{
messenger.chatListView.getSelectionModel().select(openChat);
messenger.unpackChatMessages(openChat.getMessages());
break;
}
}
}
else
{
messenger.buildNewChat(destination);
}
messenger.chatInput.setText("Hey " + destination + ". Interested in your '" + itemName + "'.");
messenger.chatInput.setOnMouseClicked(me -> messenger.chatInput.clear());
});
Thread t = new Thread(waitForSync);
t.setDaemon(true);
t.start();
}
Which does work, but this doesn't seem like a great solution. Is it fine to do something like this or is there a preferred method over this? I feel like the while loop and using a triggered boolean is sloppy..but is this common practice?
Don't try to handle the opened chat in the same method that schedules the chat retrieval. Instead create a queue of handlers that is executed as soon as the chat is ready.
Simplified Example
public class ChatManager {
private final Map<String, Chat> openChats = new HashMap<>();
// only call from application thread
public void openChat(String user, Consumer<Chat> chatReadyHandler) {
Chat chat = openChats.computeIfAbsent(user, this::createNewChat);
chat.addReadyHandler(chatReadyHandler);
}
private Chat createNewChat(String user) {
return new Chat(user);
}
public class Chat {
// list keeping track of handlers any used for synchronisation
private final ArrayList<Consumer<Chat>> readyHandlers = new ArrayList<>(1);
private boolean ready = false;
private final String user;
public String getUser() {
return user;
}
private void addReadyHandler(Consumer<Chat> chatReadyHandler) {
synchronized (readyHandlers) {
// if already ready, immediately execute, otherwise enqueue
if (ready) {
chatReadyHandler.accept(this);
} else {
readyHandlers.add(chatReadyHandler);
}
}
}
private void chatReady() {
synchronized (readyHandlers) {
ready = true;
}
// execute all handlers on the application thread
Platform.runLater(() -> {
synchronized (readyHandlers) {
for (Consumer<Chat> readyHandler : readyHandlers) {
readyHandler.accept(this);
}
readyHandlers.clear();
readyHandlers.trimToSize();
}
});
}
private Chat(String user) {
this.user = user;
new Thread(() -> {
try {
Thread.sleep(10000); // simulate time required to acquire chat
} catch (InterruptedException ex) {
}
chatReady();
}).start();
}
}
}
The following code creates a Chat with a user when Enter is pressed after typing the user name in the TextField and prints a message to the TextArea when the chat is ready.
#Override
public void start(Stage primaryStage) throws Exception {
ChatManager worker = new ChatManager();
TextField userName = new TextField();
TextArea textArea = new TextArea();
textArea.setEditable(false);
userName.setOnAction(evt -> {
String user = userName.getText();
userName.clear();
textArea.appendText("opening chat for " + user + "\n");
worker.openChat(user, chat -> textArea.appendText("chat for " + chat.getUser() + " ready\n"));
});
Scene scene = new Scene(new VBox(10, userName, textArea));
primaryStage.setScene(scene);
primaryStage.show();
}

Parse: Duplicate records for the a single saveInBackground Call

I have a single incident where a complete duplicate of a entry was made into the database (the same user comment appeared twice). They had different object IDs but were otherwise the exact same. It was slower than usual to finish the posting and only happened once out of dozens of comments, so I want to say it was a Parse issue during the saveInBackground call. Even so, I expect a service like Parse to be a little more robust. As my first time working with Android though, I also can't be sure nothing is wrong on my end. Any help? Also just any criticisms? This is the method called when the user hits a comment submission button:
private void submitComment() {
String text = commentText.getText().toString().trim();
Intent intent = getIntent();
String ID = intent.getStringExtra("imageID");
String parentID = intent.getStringExtra("parent");
// Set up a progress dialog
final ProgressDialog loadingDialog = new ProgressDialog(CommentSubmitActivity.this);
loadingDialog.setMessage(getString(R.string.publishing_comment));
loadingDialog.show();
Comment comment = new Comment();
comment.setText(text);
comment.setUser((ParseUser.getCurrentUser()));
if (ID.equals("#child")) {
comment.setParent(parentID);
comment.setImage("#child");
ParseQuery<ParseObject> query = ParseQuery.getQuery("Comment");
query.getInBackground(parentID, new GetCallback<ParseObject>() {
public void done(ParseObject parentComment, ParseException e) {
if (e == null) {
int numChild = parentComment.getInt("numChild");
parentComment.put("numChild", ++numChild);
parentComment.saveInBackground();
} else {
Log.d("numChild: ", "error");
}
}
});
} else {
comment.setImage(ID);
comment.put("numChild", 0);
ParseQuery<ParseObject> query = ParseQuery.getQuery("ImageUpload");
query.getInBackground(ID, new GetCallback<ParseObject>() {
public void done(ParseObject image, ParseException e) {
if (e == null) {
int numComments = image.getInt("numComments");
image.put("numComments", ++numComments);
image.saveInBackground();
} else {
Log.d("numComments: ", "error");
}
}
});
}
comment.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
loadingDialog.dismiss();
finish();
}
}
});
}
I encountered similar problem like yours.
I created an app where user can create account and add photo to it and list of objects (friends in my case).
Once when I was testing it user was created twice.
I went through my code and my my suspicions are connected with async calls.
I see that you use asynchronous parse api in you application so no fragment of code is waiting for response and blocking the rest of operations.
You cannot control when parse server will response.
What I did I just put all synchronous requests in my custom async code (AsyncTask in Android).
Hope that my answer somehow meeets your expectations.

Setting ChoiceBox item too slow in javafx

i have a problem with setting item in ChoiceBox, so basicly i must load data from a database i do it in another thread :
final Service<ObservableList<Country>> countryService = new Service<ObservableList<Country>>() {
#Override
protected Task<ObservableList<Country>> createTask() {
return new Task<ObservableList<Country>>() {
#Override
protected ObservableList<Country> call() throws Exception {
Dao<Country, Integer> countriesDao = null;
List<Country> result = null;
try {
countriesDao = DaoManager.createDao(Connection.getNewInstance(), Country.class);
System.out.println("getting data");
result = countriesDao.queryForAll();
System.out.println("got data");
} catch (SQLException ex) {
Logger.getLogger(ListClientsController.class.getName()).log(Level.SEVERE, null, ex);
}
return FXCollections.observableArrayList(result);
}
};
}
};
countryService.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
// taking a lot of time here like 4-5 second and freeze
// the gui(normal because it executed in Javafx Application Thread
// but why its take so much time??
cbSearchCountry.setItems(countryService.getValue());
}
});
countryService.start();
Normally database access should take a time longer that setting a list to a ChoiceBox, but no here fetching 150 record from my database is instantaneous but settings observable list to my ChoiceBox take about 5 seconds why?
because i have too much Node in my current Scene??
Use ChoiceBox only if you have < 10 items, else use ComboBox

JSVGCavas BridgeUserAgent displayError() override

I've met a problem and I've been struggling last 2 days. I have a compiled program that runs some simulations and visualizes the results in an SVG file. The file is replaced every 2 seconds with a new one, until the simulation is done.
Wanting to visualize the results, I made a java swing program which uses batik and JSVGCanvas to display the svg file and update it every 2 seconds.
The code I use is:
// In the main part of my code
svgCanvas = new JSVGCanvas();
oneLineInnerPanel.add("Center", svgCanvas);
(new Thread() {
#Override
public void run() {
try {
Thread.sleep(2000);
File f = new File("file_that_shows_simulation_still_running");
while (f.exists()) {
svgReloadButtonActionPerformed(null);
Thread.sleep(2000);
}
} catch (InterruptedException ex) {
Logger.getLogger(testUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}).start();
// -----------------------------------------------
private void svgReloadButtonActionPerformed(java.awt.event.ActionEvent evt) {
try {
svgCanvas.loadSVGDocument(SVGFile.toURL().toString());
} catch (MalformedURLException ex) {
Logger.getLogger(testUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
It works fine with the exception that every 30-40 updates, it happens that the loadSVGDocument tries to read the document while it's being written by the simulator and thus I get a jdialog error:
XML document structures must start and end within the same entity.
org.apache.batik.dom.util.SAXIOException: XML document structures must start and end within the same entity.
at org.apache.batik.dom.util.SAXDocumentFactory.createDocument(SAXDocumentFactory.java:437)
at org.apache.batik.dom.util.SAXDocumentFactory.createDocument(SAXDocumentFactory.java:349)
at org.apache.batik.dom.svg.SAXSVGDocumentFactory.createDocument(SAXSVGDocumentFactory.java:200)
at org.apache.batik.dom.svg.SAXSVGDocumentFactory.createSVGDocument(SAXSVGDocumentFactory.java:124)
at org.apache.batik.bridge.DocumentLoader.loadDocument(DocumentLoader.java:106)
at org.apache.batik.swing.svg.SVGDocumentLoader.run(SVGDocumentLoader.java:84)
Caused by: org.xml.sax.SAXParseException; systemId: file:/tmp/tempDir9189341730639722289/svgOut.svg; lineNumber: 272; columnNumber: 2; XML document structures must start and end within the same entity.
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.batik.dom.util.SAXDocumentFactory.createDocument(SAXDocumentFactory.java:431)
... 5 more
This doesn't affect the whole procedure, but it's ugly. I get 2-3 of these jdialogs throughout the simulation. I cannot lock the file I/O, because I don't have access to the simulator code. If I lock from java only, the simulator crashes saying it cannot access the file.
What I want is that if there is an error while loading the svg file to somehow catch it internally and not have a jdialog. I can accept missing an update every 30-40 times (60-80 secs).
Now, JSVGCanvas gives you the option to provide a useragent and overwrite the displayError() method to do as you like. I tried that but the dialogs still occur. The problem is that the dialogs are not produced by the svgUserAgent I provide but by an internal BridgeUserAgent:
public JSVGComponent(SVGUserAgent ua, boolean eventsEnabled,
boolean selectableText) {
super(eventsEnabled, selectableText);
svgUserAgent = ua;
userAgent = new BridgeUserAgentWrapper(createUserAgent());
addSVGDocumentLoaderListener((SVGListener)listener);
addGVTTreeBuilderListener((SVGListener)listener);
addSVGLoadEventDispatcherListener((SVGListener)listener);
if (updateOverlay != null)
getOverlays().add(updateOverlay);
}
public void loadSVGDocument(String url) {
String oldURI = null;
if (svgDocument != null) {
oldURI = svgDocument.getURL();
}
final ParsedURL newURI = new ParsedURL(oldURI, url);
stopThenRun(new Runnable() {
public void run() {
String url = newURI.toString();
fragmentIdentifier = newURI.getRef();
loader = new DocumentLoader(userAgent);
nextDocumentLoader = new SVGDocumentLoader(url, loader);
nextDocumentLoader.setPriority(Thread.MIN_PRIORITY);
Iterator it = svgDocumentLoaderListeners.iterator();
while (it.hasNext()) {
nextDocumentLoader.addSVGDocumentLoaderListener
((SVGDocumentLoaderListener)it.next());
}
startDocumentLoader();
}
});
}
Can anyone help me get out of this mess, please?
Thanks in advance!
Finally solved the issue. Extended JSVGCanvas, override the createUserAgent() method to provide a bridgeuseragent of my own. This useragent extends the JSVGCanvas user agent but overrides the displayError methods. Here's the code:
import org.apache.batik.bridge.UserAgent;
import org.apache.batik.swing.JSVGCanvas;
import org.apache.batik.util.XMLConstants;
/**
*
* #author
*/
public class myJSVGCanvas extends JSVGCanvas{
#Override
protected UserAgent createUserAgent() {
return new myCanvasUserAgent();
}
protected class myCanvasUserAgent extends CanvasUserAgent
implements XMLConstants {
/**
* Displays an error message in the User Agent interface.
*/
#Override
public void displayError(String message) {
if (svgUserAgent != null) {
super.displayError(message);
} else {
System.out.println(message);
// JOptionPane pane =
// new JOptionPane(message, JOptionPane.ERROR_MESSAGE);
// JDialog dialog =
// pane.createDialog(myJSVGCanvas.this, "ERROR");
// dialog.setModal(false);
// dialog.setVisible(true); // Safe to be called from any thread
}
}
/**
* Displays an error resulting from the specified Exception.
*/
#Override
public void displayError(Exception ex) {
if (svgUserAgent != null) {
super.displayError(ex);
} else {
ex.printStackTrace();
// JErrorPane pane =
// new JErrorPane(ex, JOptionPane.ERROR_MESSAGE);
// JDialog dialog = pane.createDialog(myJSVGCanvas.this, "ERROR");
// dialog.setModal(false);
// dialog.setVisible(true); // Safe to be called from any thread
}
}
}
}
Hope it helps somebody. If anyone has a better idea for dealing with the problem, than just hiding it, I'd be glad to hear it!

Categories

Resources