Evento in Java FX

di il
13 risposte

Evento in Java FX

Qualcuno utilizza Java FX?
Mi serviva una piccola applicazione desktop, quindi ho pensato di utilizzare questo framework aiutandomi con SceneBuilder.

Morale della storia, ho aggiunto delle combobox per la gestione di alcune cose, quindi le inizializzo (il codice che segue si trova nella classe controller creata di default) popolandole all’avvio:
combo1.getItems().addAll(“Cane”,”Gatto”,”Capra”,”Topo”);
combo2.getItems().addAll(“Piatto”,”Formaggio”,”Tovaglia”,”Forchetta”);
combo3.getItems().addAll(“Mimì”,”Cocò”,”E tanta voglia di crescere”,”Altro”);
Ogni volta che viene cliccato un bottone (“pulisci”), vorrei ripristinare tutti i combo con una parola base, esempio: combo1.setValue(“Animale”);
ma non riesco, o meglio, devo cliccare 2 volte lo stesso bottone per ottenere quello che voglio.

Quindi, per la gestione del bottone in questione:
@FXML
void doClear(ActionEvent event) {
	…			
		if(combo1.getValue() != null) {
			combo1.setValue(null);
                        combo1.setValue(“Animale”);
		} 
		if(combo2.getValue() != null) {
			combo2.setValue(null);
                        combo2.setValue(“Oggetto”);
		}
		if(combo3.getValue() != null) {
			combo3.setValue(null);
                        combo3.setValue(“Robaccia”);
		}			
}
...nel caso mi chiedeste cosa contengano gli appositi metodi (sono tutti uguali), li utilizzo solo per ricavare la posizione (indice) e con questo sistema la ottengo:
@FXML
void doCombo1(ActionEvent event) {		
		gruppo = "";
		gruppo = combo1.getValue().toString();
		for (int i = 0; i < combo1.getItems().size(); i++) {
			if (combo1.getItems().get(i).equalsIgnoreCase(gruppo)) {
				n_items = i + 1;
				break;
			}
		}
	}
Adesso, la domanda è: «Come posso ottenere ciò che voglio con un click?»
Così com’è, con il primo click cancella la stringa selezionata, con il secondo inserisce quella nuova.
È un’applicazione con pochissime pretese, fa già quello che mi serve, però mi piacerebbe capire meglio questa cosa.

13 Risposte

  • Re: Evento in Java FX

  • Re: Evento in Java FX

    ...e invece non è così, anzi ti dirò se non scrivo setValue(null), ma direttamente setValue("Qualcosa"), mi si cancella solo la stringa (anche con 2 click).
  • Re: Evento in Java FX

  • Re: Evento in Java FX

    Non sarà che con quel codice gestisci tutto su una classe, io invece ho la main separata?
    public class Main extends Application {
    		
    	@Override
    	public void start(Stage primaryStage) {
    		try {
    			BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("nome_progetto.fxml"));
    			Scene scene = new Scene(root);
    			scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
    			primaryStage.setScene(scene);
    			primaryStage.show();
    		} catch(Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public static void main(String[] args) {
    		launch(args);
    	}
    }
    Andrea lo so che sei in gamba, però non faccio nulla di strano all'interno della classe controller. Quando si crea un progetto FX con eclipse, principlamente di default crea una classe main, una controller un file con estensione fxml e uno con estensione css, probabilmente (non lo so) dovrei importarmi la root nel controller boh? Comunque così mi ci vogliono 2 click.
  • Re: Evento in Java FX

    Comunque facciamo che domani posto una roba base ma completa così se ne avrai voglia mi mostrerai dove eventualmente sto sbagliando.
    Buona serata.
  • Re: Evento in Java FX

    Allora, devo specificare che non ho studiato JavaFX, in passato ho giusto seguito un paio di tutorial di un’insegnante di una qualche università (adesso non ricordo) che ha pubblicato delle video lezioni su YouTube (Tecniche di Programmazione), quindi vado a memoria.
    Detto questo, ho creato giusto una stupidata per capire (possibilmente) questa cosa.

    Chiaramente tu hai scritto tutto a mano, io sono pigro e ho preferito utilizzare SceneBuilder che fa risparmiare un sacco di tempo.

    Dicevo ieri, che di default vengono create 2 classi la main:
    import javafx.application.Application;
    import javafx.stage.Stage;
    import javafx.scene.Scene;
    import javafx.scene.layout.BorderPane;
    import javafx.fxml.FXMLLoader;
    
    
    public class Main extends Application {
    	@Override
    	public void start(Stage primaryStage) {
    		try {
    			BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("Sample.fxml"));
    			Scene scene = new Scene(root,300,150);
    			scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());					
    			primaryStage.setScene(scene);
    			primaryStage.show();
    		} catch(Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public static void main(String[] args) {
    		launch(args);
    	}
    }
    … e la SampleController, non ho modificato nulla, ne ho impostato il progetto in maniera seria, perché non mi interessa, ho solo dato un nome poi ?avanti ?avanti ? modificato giusto 2 impostazioni ? fine.

    La classe SampleController si presenta vuota, poi si apre SceneBuilder, si crea quello che serve ? salva ? si copia tutto il contenuto presente nello skeleton (così si chiama), e si incolla nell’apposita classe controller.

    Quindi mi ritrovo con questi dati:
    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.scene.control.Button;
    import javafx.scene.control.ComboBox;
    
    public class SampleController {	
        @FXML // ResourceBundle that was given to the FXMLLoader
        private ResourceBundle resources;
    
        @FXML // URL location of the FXML file that was given to the FXMLLoader
        private URL location;
    
        @FXML // fx:id="combo"
        private ComboBox<?> combo; // Value injected by FXMLLoader
    
        @FXML // fx:id="btClean"
        private Button btClean; // Value injected by FXMLLoader
        
        @FXML // fx:id="btClose"
        private Button btClose; // Value injected by FXMLLoader
    
        @FXML
        void gestioneCombo(ActionEvent event) {    	
        }
    
        @FXML
        void resetta(ActionEvent event) {    	
        }
        
        @FXML
        void uscita(ActionEvent event) {    	
        }
    
        @FXML // This method is called by the FXMLLoader when initialization is complete
        void initialize() {
            assert combo != null : "fx:id=\"combo\" was not injected: check your FXML file 'Sample.fxml'.";
            assert btClean != null : "fx:id=\"btClean\" was not injected: check your FXML file 'Sample.fxml'.";
            assert btClose != null : "fx:id=\"btClose\" was not injected: check your FXML file 'Sample.fxml'.";
        }
    }
    Apporto giusto un paio di modifiche:
    
       @FXML // fx:id="combo"
        private ComboBox<String> combo; // Value injected by FXMLLoader
        
       @FXML
        void resetta(ActionEvent event) {
        	// QUESTO È IL BOTTONE 
        	combo.setValue(null);
        	if(combo.getValue() == null)    		
        		//combo.setValue("Nome");
        		combo.getSelectionModel().select(combo.getPromptText());
        }
        
         @FXML
        void uscita(ActionEvent event) {
        	System.exit(0);
        }
    
        @FXML // This method is called by the FXMLLoader when initialization is complete
        void initialize() {
           ...                
            combo.getItems().addAll("Pippo", "Paperino", "Pluto", "Topolino");
        }
    ...e questa robetta è già bella che pronta.

    Il file fxml si riempe quasi in automatico, basta aprirlo una volta per far rilevare le modifiche a Eclipse. Una volta fatto ciò, si può tranquillamente provare l’applicazione.

    File fxml:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.geometry.Insets?>
    <?import javafx.scene.Cursor?>
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.ComboBox?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.layout.BorderPane?>
    <?import javafx.scene.layout.HBox?>
    <?import javafx.scene.layout.VBox?>
    <?import javafx.scene.text.Font?>
    
    
    <BorderPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.171" fx:controller="application.SampleController">
       <top>
          <Label text="PROVA COMBOBOX" BorderPane.alignment="CENTER">
             <font>
                <Font name="Abyssinica SIL" size="18.0" />
             </font>
             <BorderPane.margin>
                <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
             </BorderPane.margin>
          </Label>
       </top>
       <center>
          <VBox alignment="TOP_CENTER" BorderPane.alignment="CENTER">
             <BorderPane.margin>
                <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
             </BorderPane.margin>
             <children>
                <ComboBox fx:id="combo" minWidth="210.0" onAction="#gestioneCombo" opacity="0.98" promptText="Nome">
                   <VBox.margin>
                      <Insets />
                   </VBox.margin>
                   <padding>
                      <Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
                   </padding>
                   <cursor>
                      <Cursor fx:constant="DEFAULT" />
                   </cursor>
                </ComboBox>
             </children>
          </VBox>
       </center>
       <bottom>
          <HBox alignment="BOTTOM_CENTER" BorderPane.alignment="CENTER">
             <children>
                <Button fx:id="btClean" alignment="CENTER" minWidth="100.0" mnemonicParsing="false" onAction="#resetta" text="Cancella">
                   <padding>
                      <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
                   </padding>
                   <font>
                      <Font name="Abyssinica SIL" size="18.0" />
                   </font>
                   <HBox.margin>
                      <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
                   </HBox.margin>
                </Button>
                <Button fx:id="btClose" alignment="CENTER" minWidth="100.0" mnemonicParsing="false" onAction="#uscita" text="Chiudi">
                   <font>
                      <Font name="Abyssinica SIL" size="18.0" />
                   </font>
                   <padding>
                      <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
                   </padding>
                   <HBox.margin>
                      <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
                   </HBox.margin>
                </Button>
             </children>
             <BorderPane.margin>
                <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
             </BorderPane.margin>
          </HBox>
       </bottom>
    </BorderPane>
    Come vedi non ho fatto chissà cosa, e con queste 2 righe di codice succede questo...


    Ieri forse non mi sono spiegato bene, cliccando sul bottone cancella non deve selezionare una stringa già presente nella lista, a me interessa mostrare il TextPrompt, quello base che ho inserito con SceneBuilder, questo perché non voglio che la stringa “Nome” (per questo esempio), si veda cliccando la comboBox.

    Perché se inserisco “Nome” come primo elemento della lista, risolverei il problema, ma non è una cosa pulita, non riesco neanche eventualmente a nasconderla.

    Ad esempio potrei aggiungere
     combo.getItems().addAll(?"Nome"?,"Pippo", "Paperino", "Pluto", "Topolino");
    poi nel metodo apposito scrivo:
     @FXML
        void resetta(ActionEvent event) {
        	combo.getSelectionModel().selectFirst();
        }
    E a questo punto mi ritrovo Nome senza dover cliccare 2 volte, ma come dicevo, in questo modo cliccando la comboBox si vede in lista, e io non voglio.

    E questo è quanto...

    Se hai tempo, tu o qualcun'altro...
  • Re: Evento in Java FX

  • Re: Evento in Java FX

  • Re: Evento in Java FX

    A me non funziona, sto utilizzando Eclipse Oxigen e sono su Linux, non utilizzo praticamente mai Windows. Questa cosa potrebbe influenzare il funzionamento dell'applicazione?

    Potrei registre lo schermo per mostrarti che non dico bugie, poi però dovrei caricare il video e non ho molta voglia.

    Quindi, esiste la possibilità che provando questa cosa su Windows funzioni?

    Proverò, mi sembra strano ma ormai non mi stupisce più nulla...

    Grazie Andrea!
  • Re: Evento in Java FX

  • Re: Evento in Java FX

    Ciao, niente ho provato su Windows 10 JDK 9, e il risultato non cambia, è un mistero...

    Mi rimarrebbe da testare su macchina virtuale, ma dal momento che non è un progetto serio, è per un amico, va bene così, quello che mi è stato chiesto lo fa anche alla grande, va più che bene, insomma. Non faccio figuracce per intenderci.

    Mi scoccia non comprendere questa cosa a fondo, però va beh, ogni tanto capita anche questo.
  • Re: Evento in Java FX

  • Re: Evento in Java FX

    Incollo il codice, ma ti anticipo 2 cose:
    1) serve solo per il font, tutto il resto è inutile
    2) su Windows ho ricreato un progetto nuovo (diverso) senza css.
    /* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */
    .combo-box-base {    
        -fx-alignment: center;
        -fx-content-display: center;
        -fx-font: 18px "Abyssinica SIL";
    }
    
    .combo-box .text-field {
        -fx-prompt-text-fill: rgba(255, 0, 0, 0.5) ;
    }
    .combo-box .text-field:focused {
        -fx-prompt-text-fill: transparent ;
    }
    Se il codice è il mio non vedo perché a te deve funzionare e a me no!
Devi accedere o registrarti per scrivere nel forum
13 risposte