2016-10-28 167 views
1

我想製作一個程序,允許用戶通過單選按鈕選擇RGB顏色,並使用滑塊從0到255更改值。顏色的變化應該適用於文字。選擇R,G或B時,文本中只應顯示所選顏色(即,如果選擇綠色,紅色和藍色值爲0)。使用滑塊更改文本顏色

目前該程序在某種程度上起作用。例如,如果滑塊位於值150,並且我選擇了一種新顏色,然後移動滑塊,則文本顏色設置爲150,或者在任何情況下滑塊被設置爲開啓的值,然後嘗試將其移動到新的價值。如果我想更新滑塊,我必須在移動滑塊之前選擇一種新顏色。它只爲每個選定的顏色更新一次。我希望它能夠無縫更新所選顏色。下面的代碼示例:

public class Oblig5 extends Application { 

    static int colorValue = 0; 
    static int red = 0; 
    static int green = 0; 
    static int blue = 0; 

    public static void main(String[] args) { 

     launch(args); 

    } 

    public void start(Stage primaryStage) { 
     // Create panes 
     BorderPane bPane = new BorderPane(); 
     VBox vBox = new VBox(); 
     bPane.setLeft(vBox); 

     // Create text and place it in the pane 
     Text text = new Text("Oblig 5"); 
     text.setFont(Font.font("Times New Roman", FontWeight.NORMAL, FontPosture.REGULAR, 40)); 
     bPane.setCenter(text); 

     // Create radio buttons and place them in the VBox 
     RadioButton rbRed = new RadioButton("Red"); 
     RadioButton rbGreen = new RadioButton("Green"); 
     RadioButton rbBlue = new RadioButton("Blue"); 


     ToggleGroup group = new ToggleGroup(); 
     rbRed.setToggleGroup(group); 
     rbGreen.setToggleGroup(group); 
     rbBlue.setToggleGroup(group); 

     // Create handlers for radiobuttons 
     rbRed.setOnAction(e -> { 
      if (rbRed.isSelected()) { 
       red = colorValue; 
       green = 0; 
       blue = 0; 
      } 
     }); 

     rbGreen.setOnAction(e -> { 
      if (rbGreen.isSelected()) { 
       red = 0; 
       green = colorValue; 
       blue = 0; 
      } 
     }); 

     rbBlue.setOnAction(e -> { 
      if (rbBlue.isSelected()) { 
       red = 0; 
       green = 0; 
       blue = colorValue; 
      } 
     }); 

     vBox.getChildren().addAll(rbRed, rbGreen, rbBlue); 

     // Create a slider and place it in the BorderPane 
     Slider slider = new Slider(0, 255, 135); 
     slider.setShowTickLabels(true); 
     slider.setShowTickMarks(true); 
     bPane.setBottom(slider); 
     bPane.setAlignment(slider, Pos.CENTER); 

     // Create a handler for the slider 
     slider.valueProperty().addListener(ov -> { 
      colorValue = (int) slider.getValue(); 
      text.setFill(Color.rgb(red, green, blue)); 
     }); 

     // Create a scene and place it in the stage 
     Scene scene = new Scene(bPane, 400, 400); 
     primaryStage.setScene(scene); 
     primaryStage.setTitle("Oblig 5"); 
     primaryStage.show(); 

    } 

} 

任何輸入值得高度讚賞!

回答

5

[注:@fabian在寫這篇文章時發佈了一個答案。要麼答案是可行的,我想我也會發布這個,因爲它顯示了稍微不同的技術。像往常一樣在JavaFX中有多種好方法來實現同樣的事情。]

當選定的按鈕更改或滑塊值更改時,您需要設置文本填充相應的值。此時,當所選按鈕更改時,只更新變量red,​​和blue(但不要更改文本填充),並且當滑塊值更改時,您可以撥打setFill(...)red,​​和blue,但不要不會改變這些變量的值。

import javafx.application.Application; 
import javafx.beans.value.ChangeListener; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.RadioButton; 
import javafx.scene.control.Slider; 
import javafx.scene.control.ToggleGroup; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.VBox; 
import javafx.scene.paint.Color; 
import javafx.scene.text.Font; 
import javafx.scene.text.FontPosture; 
import javafx.scene.text.FontWeight; 
import javafx.scene.text.Text; 
import javafx.stage.Stage; 

public class Oblig5 extends Application { 

    public static void main(String[] args) { 

     launch(args); 

    } 

    public void start(Stage primaryStage) { 
     // Create panes 
     BorderPane bPane = new BorderPane(); 
     VBox vBox = new VBox(); 
     bPane.setLeft(vBox); 

     Text text = new Text("Oblig 5"); 
     text.setFont(Font.font("Times New Roman", FontWeight.NORMAL, FontPosture.REGULAR, 40)); 
     bPane.setCenter(text); 

     RadioButton rbRed = new RadioButton("Red"); 
     RadioButton rbGreen = new RadioButton("Green"); 
     RadioButton rbBlue = new RadioButton("Blue"); 


     ToggleGroup group = new ToggleGroup(); 
     rbRed.setToggleGroup(group); 
     rbGreen.setToggleGroup(group); 
     rbBlue.setToggleGroup(group); 

     vBox.getChildren().addAll(rbRed, rbGreen, rbBlue); 

     Slider slider = new Slider(0, 255, 135); 
     slider.setShowTickLabels(true); 
     slider.setShowTickMarks(true); 
     bPane.setBottom(slider); 
     BorderPane.setAlignment(slider, Pos.CENTER); 

     // Create a handler for the updating text fill: 
     ChangeListener<Object> updateListener = (obs, oldValue, newValue) -> { 
      int colorValue = (int) slider.getValue() ; 
      int red = rbRed.isSelected() ? colorValue : 0 ; 
      int green = rbGreen.isSelected() ? colorValue : 0 ; 
      int blue = rbBlue.isSelected() ? colorValue : 0 ; 
      text.setFill(Color.rgb(red, green, blue)); 
     }; 
     slider.valueProperty().addListener(updateListener); 
     group.selectedToggleProperty().addListener(updateListener); 

     // Create a scene and place it in the stage 
     Scene scene = new Scene(bPane, 400, 400); 
     primaryStage.setScene(scene); 
     primaryStage.setTitle("Oblig 5"); 
     primaryStage.show(); 

    } 


} 
4

您可以將Color設置爲使用userData來切換。這允許你創建基於滑塊值的文本和選擇切換的fill屬性綁定:

// create radio buttons and add color at full brightness 
RadioButton rbRed = new RadioButton("Red"); 
rbRed.setUserData(Color.RED); 
RadioButton rbGreen = new RadioButton("Green"); 
rbGreen.setUserData(Color.LIME); 
RadioButton rbBlue = new RadioButton("Blue"); 
rbBlue.setUserData(Color.BLUE); 

ToggleGroup group = new ToggleGroup(); 
rbRed.setToggleGroup(group); 
rbGreen.setToggleGroup(group); 
rbBlue.setToggleGroup(group); 

group.selectToggle(rbRed); 

... 

// create binding based on toggle user data and slider value 
text.fillProperty().bind(Bindings.createObjectBinding(() -> { 
    Color color = (Color) group.getSelectedToggle().getUserData(); 

    // use color determined by toggle with brightness adjusted based on slider value 
    return color.deriveColor(0, 1, slider.getValue()/slider.getMax(), 1); 
}, slider.valueProperty(), group.selectedToggleProperty())); 

注意,使用這些代碼段中沒有必要保持聽衆。特別是更新文本填充的偵聽器應該被刪除,因爲分配綁定屬性的嘗試會導致異常。

+0

感謝您的回覆!由於這是一個學校任務,教授聽衆的使用,另一個答案更多地被選爲解決方案。無論如何,我已經收到了滿意的答覆,因爲您的答案似乎也是一個很好的選擇。 – Esben86