Diskuze: Jednoduchý 3 2 1 countdown - GUI zamrzne (v JavaFX)
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.


Zobrazeno 20 zpráv z 20.
K personalizaci obsahu a reklam, poskytování funkcí sociálních médií a analýze naší návštěvnosti využíváme soubory cookie. Informace o tom, jak náš web používáte, sdílíme se svými partnery pro sociální média, inzerci a analýzy. Partneři tyto údaje mohou zkombinovat s dalšími informacemi, které jste jim poskytli nebo které získali v důsledku toho, že používáte jejich služby.
Používáme nezbytné cookies pro fungování webu a s tvým souhlasem také analytické a marketingové cookies.
Zajišťují základní funkce, bezpečnost a služby, které sis vyžádal. Nelze je vypnout.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| ITnetwork | ITnetwork | Provoz webu, relace, přihlášení a uložení nastavení cookies. | PHPSESSID, auth_token, sid, itn_consent_impression, __Host-itn_consent | Relace až 1 rok |
| Google Tag Manager | Správa značek a načítání měřicích nástrojů webu. | Žádné | Neukládá se | |
| Google Fonts | Načítání typografie webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google Hosted Libraries | Načítání potřebných knihoven a stylů webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google reCAPTCHA | Ochrana formulářů a webu před zneužitím. | _GRECAPTCHA, rc::a, rc::b, rc::c, rc::f | Relace až 180 dní | |
| YouTube | Přehrávání vloženého video obsahu. | localStorage, IndexedDB; cookies after playback interaction | Relace až trvalé úložiště | |
| Vimeo | Vimeo | Přehrávání vloženého video obsahu. | __cf_bm, _cfuvid, vuid, localStorage, IndexedDB | Relace až 2 roky |
| Facebook Login | Meta | Přihlášení pomocí účtu třetí strany. | Úložiště řízené poskytovatelem | Relace až 1 rok |
| GoPay | GoPay | Zpracování uživatelem vyžádané platby. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
Pomáhají nám porozumět používání webu a zlepšovat ho.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Analytics 4 | Měření návštěvnosti a používání webu. | _ga, _ga_* | Až 2 roky | |
| Microsoft Clarity | Microsoft | Měření návštěvnosti a používání webu. | _clck, _clsk, _cltk | Relace až 1 rok |
Slouží k měření kampaní, personalizaci reklamy a marketingové komunikaci.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Ads | Měření kampaní, reklama a remarketing. | _gcl_au, _gcl_ls | Relace až 90 dní | |
| Meta Pixel | Meta | Měření kampaní, reklama a remarketing. | _fbp, _fbc, localStorage | Až 90 dní |
| Sklik | Seznam.cz | Měření kampaní, reklama a remarketing. | retargeting, sid, szn:* | Relace až trvalé úložiště |
| LinkedIn Insight | Měření kampaní, reklama a remarketing. | bcookie, li_gc, lidc, __cf_bm | Relace až 1 rok | |
| Ecomail | Ecomail.cz | Měření kampaní, reklama a remarketing. | ecmid, Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
| Atribuce kampaní ITnetwork | ITnetwork | Přiřazení návštěvy a objednávky ke kampani. | campaign_clid[*], user_session_context | Až 1 rok |
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.


Ahoj,
Vyhodilo ti to nejakú chybu do konzoly?
Používaš FXML súbor na definovanie GUI, alebo inštancie komponentov
vytváraš v triede? Pokiaľ používaš FXML súbor, skontroluj si, či máš
premennú countdownLabel oAnotovanú @FXML anotáciou a či máš v FXML k
tomuto Labelu určené fx:id s rovnakým menom, napr:
<Label fx:id="countdownLabel />"
Ak táto rada nepomôže, hodil by sa celý kód, alebo aspoň časti, ktoré s tým môžu súvisieť.
Jednoduchá odpověď... Zamrznutí hlavního vlákna. Potřebuješ ten odpočet provést ve vlákně na pozadí, což v javafx zajišťují věci např. z packegů javafx.cuncurrent, nebo javafx.animation... A ano, nejde použít klasický Thread.
//EDIT: ten první pacage má být javafx.concurrent
Je to proto, že se pokoušíš nastavit gui prvek na nesprávném vlákně, v Java FX musíš všechno nastavovat na FX Application vlákně.
Nejsem v JavaFX taky nijak sběhlý, sám ji vůbec nepoužívám, ale myslím, že v tomhle případě bys mohl využít Timeline a binding nějak takto:
private final int countDownSeconds = 3; // bude se odpočítávat od 3 do nuly
private final StringProperty countDownValue = new SimpleStringProperty(countDownSeconds + ""); //StringProperty countDownValue se později 'přibinduje' k countdownLabel, když se změní hodnota countDownValue, změní se i countdownLabel
//nyní vytvoříme timeline s duration 1 sekunda
private final Timeline countdown = new Timeline(new KeyFrame(Duration.seconds(1), (e) -> {
int i = Integer.parseInt(countDownValue.getValue()) - 1; //koukneme jaka je hodnota countDownValue a snížíme o jedna
countDownValue.setValue(i + ""); //nastavíme countDownValue novou hodnotu
}));
někde v initialize() je třeba přibindovat tu countDownValue k countdownLabel:
countdownLabel.textProperty().bind(countDownValue);
a celé se to pak na požádání spustí tak, že někde (třeba při stisku nějakého tlačítka) provedeš:
countdown.setCycleCount(countDownSeconds); //nastaví se počet opakování, tedy pošet sekund k odpočtu
countdown.play(); //a jedeme...
Zde je celý zdrojový kód FXMLDocumentConrtoller.java
Mimochodem, programuji počítadlo pro STIGA Table Hockey.
/*
* 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 stiga.scoreboard;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
/**
*
* @author Vojta
*/
public class FXMLDocumentController implements Initializable {
@FXML
private Label hrac1BodyTextField;
@FXML
private Label hrac2BodyTextField;
@FXML
private Label casTextField;
@FXML
private Button pridejHrac1Button;
@FXML
private Button pridejHrac2Button;
@FXML
private Button odeberHrac1Button;
@FXML
private Button odeberHrac2Button;
@FXML
private Button startButton;
@FXML
private Label countdownLabel;
private int body1 = 0;
private int body2 = 0;
@FXML
private void handlepridejHrac1ButtonAction(ActionEvent event) {
if(body1 < 99)
{
body1 = body1 + 1;
hrac1BodyTextField.setText(String.valueOf(body1));
}
}
@FXML
private void handlepridejHrac2ButtonAction(ActionEvent event) {
if(body2 < 99)
{
body2 = body2 + 1;
hrac2BodyTextField.setText(String.valueOf(body2));
}
}
@FXML
private void handleodeberHrac1ButtonAction(ActionEvent event) {
if(body1 > 0)
{
body1 = body1 - 1;
hrac1BodyTextField.setText(String.valueOf(body1));
}
}
@FXML
private void handleodeberHrac2ButtonAction(ActionEvent event) {
if(body2 > 0)
{
body2 = body2 - 1;
hrac2BodyTextField.setText(String.valueOf(body2));
}
}
@FXML
private void handlestartButtonAction(ActionEvent event)
{
for (int i = 3; i > 0; i--)
{
countdownLabel.setText(String.valueOf(i));
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
System.err.println("Error" + ex);
}
}
}
@Override
public void initialize(URL url, ResourceBundle rb) {
}
}
Jak přesně myslíš toto?:
někde v initialize() je třeba přibindovat tu countDownValue k countdownLabel:countdownLabel.textProperty().bind(countDownValue)
Děkuji moc. Už jsem na to přišel. Poslední dva dny jsem nehledal na
internetu nic jiného. Fakt moc díky 
Ještě jeden dotaz, je nějaký způsob jak za běhu měnit hodnotu countDownSeconds?
private final int countDownSeconds = 3;
Zdravím, ještě jsem se chtěl zeptat, je nějaká možnost, jak celý
tento 321 countdown použít znovu?
Myslím to tak, že po zmáčknutí tlačítka by se odpočítalo 3 2 1, a
poté, kdybych zmáčknul tlačítko znovu, tak by to odpočítalo 321 ještě
jednou...
Přesuň vytváření té Timeline do metody co jí reaguješ na stisk tlačítka, tak aby se pokaždé vytvářela znova. Možná by pak bylo vhodné po odstartování toho odpočtu to tlačítko nastavit jako disabled a opětovně nastavit jako enabled po dokončení toho odpočtu, tak aby nešlo furt na něj klikat a spouštět nový a nový odpočet.
Změnil jsem kód na toto:
private int countDownSeconds = 3; // bude se odpočítávat od 3 do nuly
private StringProperty countDownValue = new SimpleStringProperty(countDownSeconds + "");
@FXML
private void handlespustitCasButtonAction(ActionEvent event)
{
countdownLabel.setVisible(true);
startSequenceSPlay();
startButton.setVisible(false);
zadatOsobyButton.setVisible(false);
Timeline countdown = new Timeline(new KeyFrame(Duration.seconds(1), (e) -> {
int i = Integer.parseInt(countDownValue.getValue()) - 1; //koukneme jaka je hodnota countDownValue a snížíme o jedna
countDownValue.setValue(i + "");//nastavíme countDownValue novou hodnotu
if (i == 0)
{
countDownValue.setValue("");
startTimeLine();
enableGoalButtons();
}
}));
countdown.setCycleCount(countDownSeconds); //nastaví se počet opakování, tedy pošet sekund k odpočtu
countdown.play(); //a jedeme...
spustitCasButton.setDisable(true);
int s = Integer.parseInt(casSekundyValue.getValue());
int m = Integer.parseInt(casMinutyValue.getValue());
if(s <= 33 && m == 0)
{
countdownSPlay();
}
goalSongStop();
Poprvé to funguje, ale když to chci pustit znovu, už to nejde a napíše
to do konzole error.
Napadlo mě, že bych celou timeline měl restartovat. Restartovat jsem to
musel, když se timer dokončí, což znamená v podmínce
if (i == 0)
ale když jsem dovnitř této podmínky umístil
countdown.stop();
aplikaci mi to vůbec nezpustilo a psalo mi to u tohoto řádku chybu:
"variable countdown might not have been initialized"
co s tím? 
Ten samý error, jenom se teď přesunul k řádku
if (i == 0 && countdown != null)
a podtrhnul countdown... 
Prepáč, až teraz som si všimol kde sa tá podmienka nachádza
Problém je v tom, že v čase,
kedy sa môže vykonať podmienka
if(i == 0)
Do countdown ešte nie je priradená žiadna hodnota, pretože tá podmienka sa nachádza pri vytváraní KeyFrame ktoré je parameter pre konštruktor triedy Timeline
ehm... jak to ale vyřešit? 
S animáciami som v JavaFX nepracoval, takže nájsť problém je jediné čo
som pre Teba zatiaľ mohol spraviť
Ale kým ti tu neodpíše niekto zdatnejší, mysím si, že metódu
stop() by nemal volať agregovaný objekt.
Zobrazeno 20 zpráv z 20.