2015-05-14 16 views
5

Mi aspettavo che, quando uso Alt + mnemonico, il pulsante di opzione correlato diventasse attivo e selezionato. Le mie aspettative sono basate sulla mia conoscenza di come funzionano i mnemonici in Swing. Le mie aspettative sono sbagliate?Come funzionano i mnemonici con i pulsanti di scelta

Nel mio codice di esempio qui sotto ho impostato il numero di ciascun pulsante di opzione come mnemonico.

  1. "Opzione 1" viene selezionato all'avvio del programma.
  2. Quando uso Alt + 3, il programma emette un segnale acustico, tutti i mnemonici vengono sottolineati e "Opzione 3" diventa focalizzata ma NON selezionata. La GUI ora assomiglia a questo:

http://i.stack.imgur.com/ip3om.png

  1. Se ho appena tipo 2 ", l'opzione 2 viene messo a fuoco, ma non selezionato

Qui. è il codice:

import javafx.application.Application; 
import javafx.stage.Stage; 
import javafx.scene.*; 
import javafx.scene.control.*; 
import javafx.scene.layout.*; 
import javafx.scene.image.*; 
import javafx.scene.input.*; 
import javafx.scene.effect.*; 
import javafx.scene.paint.*; 
import javafx.beans.value.*; 
import javafx.geometry.*; 

import javafx.event.*; 

public class RadioButtonSSCCE extends Application 
{ 
    public Parent createScene() 
    { 
     ToggleGroup group = new ToggleGroup(); 

     RadioButton rb1 = new RadioButton("Option _1"); 
     rb1.setUserData("Option 1 selected"); 
     rb1.setToggleGroup(group); 

     RadioButton rb2 = new RadioButton("Option _2"); 
     rb2.setUserData("Option 2 selected"); 
     rb2.setToggleGroup(group); 

     RadioButton rb3 = new RadioButton("Option _3"); 
     rb3.setUserData("Option 3 selected"); 
     rb3.setToggleGroup(group); 

     VBox root = new VBox(5); 
     root.setAlignment(Pos.CENTER); 
     root.getChildren().addAll(rb1, rb2, rb3); 

     ChangeListener<Toggle> cl = new ChangeListener<Toggle>() 
     { 
      @Override 
      public void changed(ObservableValue<? extends Toggle> ov, Toggle old_toggle, Toggle new_toggle) 
      { 
       if (group.getSelectedToggle() != null) 
       { 
        String text = group.getSelectedToggle().getUserData().toString(); 
        System.out.println(text); 
       } 
      } 
     }; 
     group.selectedToggleProperty().addListener(cl); 

     rb1.setSelected(true); 

     return root; 
    } 

    @Override 
    public void start(Stage primaryStage) 
    { 
     Scene scene = new Scene(createScene(), 125, 125); 
     primaryStage.setScene(scene); 
     primaryStage.setTitle("Radio Button SSCCE"); 
     primaryStage.show(); 
    } 

    public static void main(String[] args) 
    { 
     launch(args); 
    } 
} 

ho scoperto che per invocare mnemonico devo:

  1. premere e rilasciare il tasto Alt. Ora il mnemonico di ciascun pulsante di opzione è sottolineato.
  2. premere il numero e il pulsante di opzione diventa attivo. Tuttavia, ora ho bisogno di usare la barra spaziatrice per selezionare il pulsante di opzione.

Perché devo premere la barra spaziatrice? Il pulsante radio non deve essere selezionato quando viene premuto il mnemonico?

Inoltre, perché non posso semplicemente usare Alt + mnemonico come combinazione di un singolo tasto per selezionare un pulsante di opzione?

Il mio codice è sbagliato?

Edit:

L'azione è la chiave per la selezione del pulsante di scelta. Ho creato un'azione generica per essere condivisa da tutti i pulsanti:

EventHandler<ActionEvent> onAction = new EventHandler<ActionEvent>() 
{ 
    @Override 
    public void handle(ActionEvent e) 
    { 
     RadioButton button = (RadioButton)e.getSource(); 
     button.setSelected(true); 
    } 
}; 

rb1.setOnAction(onAction); 
rb2.setOnAction(onAction); 
rb3.setOnAction(onAction); 

Dal momento che i pulsanti di opzione fanno parte di un gruppo di pulsanti non volevo la possibilità di deselezionare un pulsante.

+1

Sei andato al lato oscuro che sembra. ;) –

+1

Sembra che i mnemonici causino l'attivazione di eventi di azione sui pulsanti di scelta, ma in realtà non forzano la selezione a cambiare (non posso testare direttamente, perché non sembra riconoscere nulla sul mio mac come "Alt"). Questo non sembra che cambi la selezione ... potrebbe essere un bug. –

+0

@James_D Agisce in questo modo in JavaFX 2.2 e JavaFX 8, quindi sembra essere l'intenzione. 'CheckBox' funziona allo stesso modo. – OttPrime

risposta

2

Il Mnemonic in JavaFX attiva un oggetto Node registrato con Node. Nel caso di RadioButton, ActionEvent non alterna la selezione. È possibile aggiungere un gestore generico allo RadioButton per attivare l'ActionEvent in questo modo (supponendo che si tratti di JavaFX 8).

rb1.setOnAction(event -> rb1.setSelected(!rb1.isSelected())); 
+0

Grazie. 'Nel caso di RadioButton, ActionEvent non alterna la selezione. - Mi sembra una" feature mancante ". Quando uso un mnemonico su un 'Menu', il menu si apre senza alcun codice aggiuntivo. Inoltre, qualche idea del perché devo usare due tratti chiave? 1) premi/rilascia Alt per dipingere il carattere mnemonico sottolineato 2) premi il carattere mnemonico per invocare l'azione. Ciò va contro qualsiasi cosa abbia mai fatto prima in un'app di Windows pura o in un'app Swing su Windows. Perché non posso usare Alt + mnemonico è un colpo di chiave, senza che il mio computer mi segnali? – camickr

+0

Sfortunatamente, non penso che questa sia un'ottima soluzione per te. Il test continuo mi mostra che fare clic su 'RadioButton' non lo seleziona con precisione. Per quanto riguarda la questione della combinazione di tasti mnemonici, non ne ho esperienza. Posso attivare l'azione utilizzando Alt + 1 in un colpo combinato. Tuttavia, la sottolineatura mnemonica rimane sullo schermo dopo il trigger. – OttPrime

+0

La soluzione ha funzionato bene per me. Nella mia azione ho sempre selezionato il pulsante radio e non ho notato alcun problema, è sempre selezionato e focalizzato. L'azione viene attivata quando uso Alt + 1 (e il mnemonico rimane sottolineato), ma ricevo anche un segnale acustico come se si fosse verificato un errore. Come in un'app Swing e si utilizza il tasto Canc su un campo JTextField vuoto (un campo di testo JavaFX vuoto non emette questo suono). Mi chiedo se si tratta di un problema di piattaforma. Sto usando Windows 7. – camickr

3

Come OttPrime fa notare nella sua risposta e nel Mnemonic Javadoc:

Quando un Mnemonic è registrato su un Scene, e il KeyCombination raggiunge la Scene non consumato, allora l'obiettivo Node verrà inviata una ActionEvent.

ora penso che questo è una specie di un problema, perché non si vuole veramente avere un solo ActionEvent inviato al pulsante di opzione, invece si desidera fire() il pulsante di scelta.

Attiva/disattiva lo stato del pulsante di opzione se e solo se RadioButton non è già selezionato o non fa parte di un Gruppo di Toggle.

Nota: l'attivazione di un pulsante di opzione invia inoltre un ActionEvent al pulsante.

Ecco il codice Java 8u40 per Button::fire

@Override public void fire() { 
    if (!isDisabled()) { 
     fireEvent(new ActionEvent()); 
    } 
} 

Ecco il codice per ToggleButton::fire

@Override public void fire() { 
    // TODO (aruiz): if (!isReadOnly(isSelected()) { 
    if (!isDisabled()) { 
     setSelected(!isSelected()); 
     fireEvent(new ActionEvent()); 
    } 
} 

Ed ecco il codice per RadioButton::fire

@Override public void fire() { 
    // we don't toggle from selected to not selected if part of a group 
    if (getToggleGroup() == null || !isSelected()) { 
     super.fire(); 
    } 
} 

Nota: RadioButton è a ToggleButton, quindi la chiamata a super.fire() invocherà th e Codice ToggleButton fire().

Quindi, un mnemonico per un pulsante andrà bene: tutto ciò che sta facendo il mnemonico è l'invio di un ActionEvent al pulsante (che è esattamente lo stesso dell'implementazione dell'incendio per il pulsante). Tuttavia, ToggleButtons e RadioButtons fanno cose extra nei loro metodi di fuoco per manipolare lo stato di selezione di ToggleButton, quindi le invocazioni mnemoniche non lo faranno.

Ora, si potrebbe dire, bene che va bene, mi limiterò a implementare soluzione di OttPrime:

rb1.setOnAction(event -> rb1.setSelected(!rb1.isSelected())); 

Questo sarà grande quando si seleziona il pulsante tramite un mnemonico, ma (per quanto posso vedere), interromperà altre funzionalità per la selezione dei pulsanti (ad esempio, se si attiva il pulsante di opzione a livello di programmazione e, probabilmente, anche se si fa clic sul pulsante di opzione con un mouse). Questo perché lo stato di selezione del pulsante cambia due volte (una volta nel codice fire() e di nuovo nel codice azione) e probabilmente non lo si desidera. Sfortunatamente, non posso testare questa teoria perché non ho accesso a una macchina che può usare mnemonici.

Quindi, per rispondere alla domanda iniziale "Come funzionano i mnemonici con i pulsanti di opzione"? => Non lo fanno (almeno in IMO, non in alcun modo che abbia davvero senso).

Vorrei consigliare solo disabling Mnemonic parsing per i pulsanti di opzione e i pulsanti di commutazione.

+0

Il codice che ho postato nella mia modifica, usa solo setSelected (true). Dal momento che sto usando i miei pulsanti radio in un gruppo, voglio solo selezionare il pulsante con il mnemonico. Sembra funzionare con questo approccio, o usando il metodo fire(). Tuttavia, ho fatto ulteriori test (in base ai tuoi commenti). Quando un pulsante non appartiene a un gruppo di commutazione, si verificano problemi quando si inizia a utilizzare il mouse. A volte il pulsante rimane allo stesso stato e talvolta ricevo un'eccezione. Sono d'accordo che non funziona come mi aspetterei. (+1) – camickr

+0

Ti capita di sapere come facendo clic sul pulsante di opzione con il mouse cambia lo stato del pulsante? Non è importante, ho appena iniziato a giocare con JavaFX e sono curioso. Ho provato a guardare la fonte ma non riesco a vedere come vengono gestiti gli eventi. Se sai che la classe da guardare sarebbe fantastica. – camickr

+0

Sono d'accordo che questa sia la soluzione più corretta in generale. Ho notato il problema con il clic del mouse dopo aver postato la mia risposta. – OttPrime