Diskuze: JavaFX
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.
Člen
Zobrazeno 10 zpráv z 10.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.
Jakou verzi Netbeans a jakou verzi Javy používáš? Protože mně Netbeans 8.0.2 s Javou 8 updatem 71 to vygeneruje lehce odlišnou verzi. Když do ní doplním ten tvůj kód, opravím chybné porovnávání stringů pomocí ==, tak to funguje a reaguje jak by se dalo čekat - volání sc.nextLine() blokne celou aplikaci dokud nenapíšu Ahoj a nestisknu enter.
Mimochodem je nějaký důvod v okenní aplikaci brát vstup od uživatele z konzole? Vždyť přece když to spustíš bez IDE tak tu konzoli k dispozici nemáš, leda bys to teda pouštěl z příkazové řádky...
Verzi Netbeans mám stejnou, a Javu aktuální, teď jsem to kontroloval.
Teď jsem si všiml že narozdíl od mého původního programu se v tomto
programu okno nenačte ani na chvíli.
Opravdu nevím čím by to mohlo být.
Přikládám všechny zdrojové soubory projektu.
Main:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package javafxapplication9;
import java.util.Scanner;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* @author me
*/
public class JavaFXApplication9 extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
Scanner SC = new Scanner(System.in);
System.out.print(get(SC));
}
String get(Scanner sc)
{
String s = sc.nextLine();
if(s.equals("ahoj")) return s;
return get(sc);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Controller:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package javafxapplication9;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
/**
*
* @author me
*/
public class FXMLDocumentController implements Initializable {
@FXML
private Label label;
@FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
Fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication9.FXMLDocumentController">
<children>
<Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
<Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
</children>
</AnchorPane>
A důvodu si prosím nevšímej má aplikace je v testovací fázi, ale
zkoušel jsem si tam dát TextField a Button a stejně to nefungovalo.
PS: díky za snahu o pomoc.
Je to opravdu divné ale už jsem přišel na řešení, okno se načte a
začne zase odpovídat jakmile se dokončí všechny příkazy v Mainu.
Bohužel se toto řešení nevztahuje k mému hlavnímu programu kde jsem v
kontrolleru vytvořil po stisknutí tlačítka vlákno kde se logika mého
programu provozovala. okno stejně přestalo odpovídat.
Máme to teďka úplně stejně, ale mně se otevře okno, i když nejprve samozřejmě na nic nereaguje, jenom čeká až doběhne metoda get. Takže dokud nezadám ahoj, mám tam akorát prázdné okýnko, které na nic nereaguje. V okamžiku kdy v netbeans do output napíšu ahoj a odentruju, tak se to normálně rozjede, objeví se tlačítko Click me a správně zareaguje, když na něj kliknu, vypsáním Hello world.
Myslím, že tu paseku ti tam dělá právě to načítání z konzole - ze své podstaty to prostě zablokuje celou aplikaci. Zkus místo toho ještě jednou ten TextField, nevím proč by to nemělo fungovat. Prostě dáš TextField, vedle toho Button a Buttonu přiřadíš akci ať přečte co je v TextField a s tím už můžeš dále pracovat.
Ano, je to tak. JavaFX využívá hlavní vlákno, na kterém poslouchá eventy (např. zmáčknutí tlačítka) a provádí podle nich různé responze (např. nastavení labelu). Představ si to, jako zdroják, co se píše za běhu programu. Když máš "aktivní" metodu na vstup z konzole, tak to zablokuje celé vlákno, než něco napíšeš. A kdyby se něco mělo dít s oknem (třeba nějaká změna v okně nebo "aktualizace" Listenerů), tak se to zařadí až za tento řádek, který program blokuje. Řešení může být multithreading (http://www.itnetwork.cz/java/vlakna), který ale sám o sobě dělá "problémy", ale to je spíš záležitost zkušeností. Pokud bys chtěl v tom druhém vláknu ještě něco dělat s oknem, tak opět nastávaly problémy, jde to vyřešit "obklikou" přes různé nástroje z knihovny javafx.animation (Např. Timeline).
Tak jsem přepsal celou logiku a do třídy která obstarává osobu(hráče)a nahradil jsem tak tisknutí a scanování z konzole za komunikaci s GUI, získávání vstupu pomocí textFieldu a tisknutí do labelů. Celá aplikace vypadá tak že spustím nové vlákno stisknutím buttonu a v něm volám metody na kontrolleru. Problém přetrvává, ale v tomhle případě to bude již asi v absenci řešení "obklikou". Znám základy multithreadingu, principy synchronizace atd., ale v takto předepsaných konstrukcích nenám ponětí jak bych to měl řešit. Mohl bys mi prosím alespoň trochu napovědět jak problém řešit oklikou, kde si o tom můžu něco najít nebo jak se jmenuje(rešení problematiky).
Jaký přesně problém přetrvává? Gui pořád na nic nereaguje i poté co jsi odstranil to čtení z konzole nebo co?
Na to aby se po stisknutí tlačítka něco přečetlo z TextFieldu a napsalo se to někam do Labelu přece nepotřebuješ vytvářet nové vlákno. Navíc v JavaFX klasický přístup k vláknům tak jak je například popsán ve zdejších tutoriálech moc nefunguje, JavaFX k tomu má svůj vlastní přístup viz https://docs.oracle.com/…currency.htm
Zobrazeno 10 zpráv z 10.