TextInputDialog error - javafx

i have a problem with showing my TextInputDialog in JavaFX application. In code:
TextInputDialog tid = new TextInputDialog("Your name");
tid.setTitle("Table");
tid.setHeaderText("You have won!");
tid.setContentText("Enter your name: ");
tid.showAndWait();
And i got an error like this:
Exception in thread "Timer-2" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-2
And yes, i use timers, three or four in my application.
GitHub - https://github.com/verygoodat/FlappyBox
/src/Application/GameController/ - function setState(int), switch(2), i should create a message at the and of the game, but i can't.
So, what may cause this problem?
This Platform.runLater(() -> tid.showAndWait()) didn't work
case 2://pause
TextInputDialog tid = new TextInputDialog("Ваше имя");
tid.setTitle("Таблица рекордов");
tid.setHeaderText("Вы побили чей-то рекорд!");
tid.setContentText("Введите ваше имя: ");
Platform.runLater(() -> tid.showAndWait());
Timers.stopTimers();
pr.setFill(Color.rgb(0,0,0,0.5));
pr.clearRect(0,0,pre.getWidth(), pre.getHeight()-50);
pr.fillRect(0,0,pre.getWidth(), pre.getHeight());
pr.setFill(Color.WHITE);
stat = "КОНЕЦ ИГРЫ!";
pr.fillText(stat, WIDTH/2-150, HEIGHT/2);
pr.fillText( "\nPOINTS: "+gamecontroller.score, WIDTH/2-170, HEIGHT/2);
gameover = true;
break;
It works like this:
Platform.runLater(() ->
{
TextInputDialog tid = new TextInputDialog();
tid.setTitle("Таблица рекордов");
tid.setHeaderText("Вы побили чей-то рекорд!");
tid.setContentText("Введите ваше имя: ");
tid.showAndWait();
});

In JavaFX, anything that updates the UI needs to run on the FX application thread. You can do whatever else you want in your own threads, with timers, etc. but you should show the TextInputDialog on the Application thread.
You can do it like this:
Platform.runLater(()->tid.showAndWait());

Related

How to properly connect a QProgressBar with a QFutureWatcher?

I want the progress of the function to be displayed on progressBar. Following the guides, I wrote the code below. But during the execution of the function, the program freezes, then progress bar's value becomes equal to one.
The program itself will not produce errors. The result of the function is correct.
I think my problem is that I don’t know how to connect the value of the progress of a function with the value of a progress bar.
(Form.h)
public:
MyObject object;
QFutureWatcher<QBitArray> FutureWatcher;
QFuture<QBitArray> future;
(Form.cpp) Form constructor body:
ui->setupUi(this);
ui->progressBar->setMinimum(0);
ui->progressBar->setMaximum(100);
connect(&this->FutureWatcher, SIGNAL(progressValueChanged(int)), ui->progressBar, SLOT(setValue(int)));
(Form.cpp) Function on_button_clicked():
void Form::on_button_clicked()
{
QString message = ui->textEdit->toPlainText();
future = QtConcurrent::run(&this->object, &MyObject::longFunction, message);
this->FutureWatcher.setFuture(future);
QBitArray bitresult = future.result();
}
The problem is that you're immediately calling future.result(). The problem with this is that result() will wait until the QFuture has finished.
The Qt documentation says (https://doc.qt.io/qt-5/qfuture.html#result):
If the result is not immediately available, this function will block and wait for the result to become available.
The solution is to connect a slot to QFutureWatcher::finished():
auto *watcher = new QFutureWatcher<QBitArray>(this);
connect(watcher, &QFutureWatcher::finished, this, [=]() {
auto result = watcher->result();
// do something with the result
// important: delete watcher again
watcher->deleteLater();
});
// now start the task
QString message = ui->textEdit->toPlainText();
watcher->setFuture(QtConcurrent::run(myObject, &MyObject::longFunction, message));

how to make the processindecator show before certain action in javafx

I have an multi-window javafx mailbox project.Which is realized by turning the visibility and availability true and false of the window(anchorpane).
now I hava two windows (paneA and B),When i switch from A to B,because there is a process where i need to load some information into the pane B and which would take some time, I wanted to make an progressindicator to show that panel B is actually loading information.
but the problem is,even if i set the progress-indicator's visibility and availability true before i called the loading function and switching pane function,the progress-indicator only show after the loading was finished.
i tried to set the progress-indicator's visibility and availability in another thread and it also wont work properly(show after the loading)
"loading" in the code is the fxml id of the progressindicator
here is the code:(the code is part of the controller.java)
//open inboxpage
public void OpenBox() {
this.loading.setVisible(true);//loading is the id of the progress indicator
this.loading.setDisable(false);
SendPane.setDisable(true);
SendPane.setVisible(false);
SettingPane.setDisable(true);
SettingPane.setVisible(false);
BoxPane.setDisable(false);
BoxPane.setVisible(true);
if(account.length()+pwd.length()<2) {
//this.loading.setVisible(false);
//this.loading.setDisable(true);
this.MailDisplay.setText("Please fill in your infos");
}else {
this.MailDisplay.clear();
LoadMails(account,pwd);
//this.loading.setVisible(false);
//this.loading.setDisable(true);
}
}
the truth is ,if i use the code below,the progress indicator won't show at all(the indicator show after loading,but it was set to unvisible soon after showing)
//open inboxpage
public void OpenBox() {
this.loading.setVisible(true);//loading is the id of the progress indicator
this.loading.setDisable(false);
SendPane.setDisable(true);
SendPane.setVisible(false);
SettingPane.setDisable(true);
SettingPane.setVisible(false);
BoxPane.setDisable(false);
BoxPane.setVisible(true);
if(account.length()+pwd.length()<2) {
this.loading.setVisible(false);
this.loading.setDisable(true);
this.MailDisplay.setText("Please fill in your infos");
}else {
this.MailDisplay.clear();
LoadMails(account,pwd);
this.loading.setVisible(false);
this.loading.setDisable(true);
}
}
Thanks to all who commented above,the problem was solved.
I used another thread to load the information into the pane.
before the execute of such thread ,invoke the indicator
setDisable(f);
setVisible(t);
at end of the run method of this class,invoke indicator.setdisable(t),visible(f)
```
ExecutorService executor = Executors.newCachedThreadPool();
System.out.println("call thread");
call(executor,account,pwd);
private synchronized void call (ExecutorService executor,String acc,String pwd) {
loadBox loader= new loadBox();
loader.loading=this.loading;
loader.account = acc;
loader.pwd= pwd ;
loader.ChooseMail = ChooseMail ;
loader.MailDisplay= this.MailDisplay;
System.out.println("exe thread");
executor.execute(loader);
}
```

Failure to get the stage of a dialog

http://code.makery.ch/blog/javafx-dialogs-official/ shows how to get the stage of a JavaFX-8 dialog:
// Get the Stage.
Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
Alas, this does not work for me: the dialog pane (although displayed) gives null on .getScene().
Is there any other easy way to get the stage or at least the scene of an open dialog window?
The background of the question is that, under certain circumstances, need to display an Alert to the user while keeping the underlying dialog window open. Currently, that does not work due to an invalid combination of Modality values, but that's a different topic.
Hard to say for sure if you post no context code but I think the problem is the timing. You need to get the stage before you showAndWait (or at least before the dialog is closed). Try this:
public static boolean showConfirmationDialog(String contentText, String headerText) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, contentText, ButtonType.YES, ButtonType.NO);
alert.setTitle("Test");
alert.setHeaderText(headerText);
Window alertWindow = alert.getDialogPane().getScene().getWindow();
System.out.println("alertWindow.getOpacity(): " + alertWindow.getOpacity());
Optional<ButtonType> result = alert.showAndWait();
//This would cause a NullPointerException at this point:
//alertWindow = alert.getDialogPane().getScene().getWindow();
//System.out.println("alertWindow.getOpacity(): " + alertWindow.getOpacity());
return (result.get() == ButtonType.YES);
}

Activity Indicator is not visible on xaml page in xamarin.forms?

I have an activity indicator on xaml page. Initially its IsVisible property is false. I have a button on page. When user click on button it calls a web service to get data. I change the value of IsVisible property to true before calling the service so that activity indicator starts to display on page and after successful calling of service I change its value to again false so that it doesn't show any more on page.
But it is not working. I know the actual problem. When we call the web service the UI thread gets block and it doesn't show the activity indicator.
How I can enable the UI thread when web service gets called so that activity indicator can show on page until we get the data?
Try making your webservice call into an async and await it.
Depending on how you've structured things you may have to use a TaskCompletionSource as the following example demonstrates.
In this example when the button is clicked, the button is made invisible, and the ActivityIndicator is set to IsRunning=True to show it.
It then executes your long running task / webservice in the function ExecuteSomeLongTask using a TaskCompletionSource.
The reason for this is that in our button click code, we have the final lines:-
objActivityIndicator1.IsRunning = false;
objButton1.IsVisible = true;
That stop the ActivityIndicator from running and showing, and also set the button back to a visible state.
If we did not use a TaskCompletionSource these lines would execute immediately after calling the ExecuteSomeLongTask if it was a normal async method / function, and would result in the ActivityIndicator not running and the button still being visible.
Example:-
Grid objGrid = new Grid()
{
};
ActivityIndicator objActivityIndicator1 = new ActivityIndicator();
objGrid.Children.Add(objActivityIndicator1);
Button objButton1 = new Button();
objButton1.Text = "Execute webservice call.";
objButton1.Clicked += (async (o2, e2) =>
{
objButton1.IsVisible = false;
objActivityIndicator1.IsRunning = true;
//
bool blnResult = await ExecuteSomeLongTask();
//
objActivityIndicator1.IsRunning = false;
objButton1.IsVisible = true;
});
objGrid.Children.Add(objButton1);
return objGrid;
Supporting function:-
private Task<bool> ExecuteSomeLongTask()
{
TaskCompletionSource<bool> objTaskCompletionSource1 = new TaskCompletionSource<bool>();
//
Xamarin.Forms.Device.StartTimer(new TimeSpan(0, 0, 5), new Func<bool>(() =>
{
objTaskCompletionSource1.SetResult(true);
//
return false;
}));
//
return objTaskCompletionSource1.Task;
}
You need to do your work in an asynchronous way. Or in other words: Use Asnyc & Await to ensure, that you UI works well during the call.
You can find more informations in the Xamarin Docs.
async and await are new C# language features that work in conjunction
with the Task Parallel Library to make it easy to write threaded code
to perform long-running tasks without blocking the main thread of your
application.
If you need further asistance, please update your question and post your code or what you have tried so far.

How to switch to a different window using selenium webdriver java?

I am trying to switch to a New window which gets displayed when I click on the Debt Pricing Template. But I am unable to do that as a result of which I am not able to proceed with further scripting... The problem is I am not able to know what should I pass in the switchTo.window() because Pricing Approval Gateway window displays and following is the HTML for the new window:
<*h1 class="pageType noSecondHeader">Pricing Approval Gateway<*/h1>
Following is the code:
LoginPage2.driver.findElement(By.linkText("TEST ORG")).click();
System.out.println("3.Select Dept pricing template button from the organization detail page.");
if(LoginPage2.driver.findElement(By.name("debt_pricing_template")).isDisplayed())
System.out.println("User should able to navigate to Dept pricing template and template display few question, user have answer these question for further navigation.");
LoginPage2.driver.findElement(By.name("debt_pricing_template")).click();
LoginPage2.driver.manage().timeouts().implicitlyWait(100, TimeUnit.SECONDS);
LoginPage2.driver.switchTo().window("bPageTitle");
Please advise what needs to be added?
I never used it because in my tests I am not using any new windows, but this should help:
Set<string> handlers = driver.getWindowHandles();
if (driver.getWindowHandles().size()>= 1){
for(String handler : handlers){
driver.switchTo().window(handler);
if (driver.getElement(By.tagName("h1")).contains("Pricing")){
System.out.println("Get focus on Popup window");
break;
}
}
}
else System.out.println("No windows founded!");
I am not quite sure with the h1 approach. So if it does not help, try before opening new window storing current window to String:
String mainWindow = driver.getWindowHandle();
Then click the link (or do something else as you are doing now) to open new window. Then to switch to the new window:
Set<string> handlers = driver.getWindowHandles();
for (String handler : handlers){
if (!handler.equals(mainWindow)){
driver.switchTo(handler);
break;
}
}
And then to switch back to original window just do:
driver.switchTo(mainWindow);
Ofcourse the driver variable is expected live instance of
WebDriver
driver.findElement(By.linkText("Go to Billing Summary")).click();
driver.findElement(By.linkText("01 Mar 2016")).click();
Thread.sleep(5000);
driver.findElement(By.linkText("AMS TAX")).click();
driver.findElement(By.linkText("00842")).click();
Set<String> instancewindow= driver.getWindowHandles();
Iterator<String> it = instancewindow.iterator();
String parent =it.next();
String child = it.next();
driver.switchTo().window(child);
driver.switchTo().frame("modalSubWindow");
driver.findElement(By.linkText("View More Vehicle Details>>")).click();
driver.switchTo().window(parent);

Resources