NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: JavaFX

V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Ten Zdeněk :25.1.2016 19:04

Ahoj, mám takový problém, začal jsem svůj velký program převádět do javyFX(místo práce s konzolí) a kdykoliv kliknu mimo spuštěné okno, třeba abych něco zadal do konzole tak okno po chvíli přestane odpovídat a začne načítat, když chci okno zavřít, vyhodí mi formulář jestli chci počkat nebo ukončit program. Když program ukončím v konzoli se mi vypíše :
Java Result: -805306369

Vyvořil jsem program, který je výřezem problému, na který jsem narazil. Jediný rozdíl je že musím nejdříve okno minimalizovat abych ho mohl zavřít.
Omlouvám se jestli je to něco hloupého, ale nad tímto problémem sedím už nějáký ten pátek a nikde jsem nenašel diskuzi nebo článek, který by popisoval aspoň něco trochu podobného.

Výřez(je to základní program který vam vygeneruje netBeants když vytvoříte fxml projekt, kontroler je nezměněn a není v něm nic důležitého):

package project3;

import java.util.Scanner;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

/**
 *
 * @author me
 */
public class Project3 extends Application {

    @Override
    public void start(Stage stage) throws Exception {

        FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));

        AnchorPane pane = (AnchorPane) loader.load();

        FXMLDocumentController controller = loader.<FXMLDocumentController>getController();


        Scene scene = new Scene(pane);



        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 == "ahoj") return s;
        return get(sc);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}
 
Odpovědět
25.1.2016 19:04
Avatar
Atrament
Člen IT Redactor Gang
Avatar
Odpovídá na Ten Zdeněk
Atrament:25.1.2016 20:06

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...

 
Nahoru Odpovědět
25.1.2016 20:06
Avatar
Ten Zdeněk :25.1.2016 20:48

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>
 
Nahoru Odpovědět
25.1.2016 20:48
Avatar
Ten Zdeněk :25.1.2016 20:50

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.

 
Nahoru Odpovědět
25.1.2016 20:50
Avatar
Ten Zdeněk :25.1.2016 21:00

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.

 
Nahoru Odpovědět
25.1.2016 21:00
Avatar
Atrament
Člen IT Redactor Gang
Avatar
Odpovídá na Ten Zdeněk
Atrament:25.1.2016 21:09

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.

 
Nahoru Odpovědět
25.1.2016 21:09
Avatar
pocitac770
Tvůrce
Avatar
pocitac770:26.1.2016 8:06

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).

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
 
Nahoru Odpovědět
26.1.2016 8:06
Avatar
Odpovídá na pocitac770
Ten Zdeněk :27.1.2016 21:38

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).

 
Nahoru Odpovědět
27.1.2016 21:38
Avatar
Odpovídá na Ten Zdeněk
Ten Zdeněk :27.1.2016 21:39

celou logiku třídy*

 
Nahoru Odpovědět
27.1.2016 21:39
Avatar
Atrament
Člen IT Redactor Gang
Avatar
Odpovídá na Ten Zdeněk
Atrament:27.1.2016 22:31

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

 
Nahoru Odpovědět
27.1.2016 22:31
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.