2012-05-09 63 views
15

Tôi muốn tạo nút tùy chỉnh, có hai trạng thái được nhấn hoặc không, như nút chuyển đổi. Tôi đã có hai hình ảnh để làm điều này (nhấn và không ép), vì vậy làm thế nào tôi có thể tạo ra các nút và hiển thị nó với hình ảnh của tôi? Nút phải có kích thước của hình ảnh.
Tôi không sử dụng FXML. Cảm ơn bạn đã trợ giúp.JavaFX - tạo nút tùy chỉnh với hình ảnh

Trả lời

40

Có một vài cách khác nhau để thực hiện việc này, tôi sẽ phác thảo các mục yêu thích của mình.

Sử dụng ToggleButton và áp dụng kiểu tùy chỉnh cho nó. Tôi đề nghị điều này bởi vì điều khiển yêu cầu của bạn là "giống như nút chuyển đổi" nhưng có vẻ khác với kiểu nút chuyển đổi mặc định.

phương pháp ưa thích của tôi là để xác định một hình ảnh cho các nút trong css:

.toggle-button { 
    -fx-graphic: url('http://icons.iconarchive.com/icons/aha-soft/desktop-buffet/128/Pizza-icon.png'); 
} 

.toggle-button:selected { 
    -fx-graphic: url('http://icons.iconarchive.com/icons/aha-soft/desktop-buffet/128/Piece-of-cake-icon.png'); 
} 

HOẶC sử dụng css kèm theo để xác định một hình nền.

// file imagetogglebutton.css deployed in the same package as ToggleButtonImage.class 
.toggle-button { 
    -fx-background-image: url('http://icons.iconarchive.com/icons/aha-soft/desktop-buffet/128/Pizza-icon.png'); 
    -fx-background-repeat: no-repeat; 
    -fx-background-position: center; 
} 

.toggle-button:selected { 
    -fx-background-image: url('http://icons.iconarchive.com/icons/aha-soft/desktop-buffet/128/Piece-of-cake-icon.png'); 
} 

Tôi thích các đặc điểm kỹ -fx-đồ họa so với thông số kỹ thuật * -fx-background- như các quy tắc cho hình ảnh nền phong cách rất khéo léo và thiết lập nền không tự động kích thước nút để hình ảnh, trong khi thiết lập đồ họa.

Và một số mẫu mã:

import javafx.application.Application; 
import javafx.scene.*; 
import javafx.scene.control.ToggleButton; 
import javafx.scene.layout.StackPaneBuilder; 
import javafx.stage.Stage; 

public class ToggleButtonImage extends Application { 
    public static void main(String[] args) throws Exception { launch(args); } 
    @Override public void start(final Stage stage) throws Exception { 
    final ToggleButton toggle = new ToggleButton(); 
    toggle.getStylesheets().add(this.getClass().getResource(
     "imagetogglebutton.css" 
    ).toExternalForm()); 
    toggle.setMinSize(148, 148); toggle.setMaxSize(148, 148); 
    stage.setScene(new Scene(
     StackPaneBuilder.create() 
     .children(toggle) 
     .style("-fx-padding:10; -fx-background-color: cornsilk;") 
     .build() 
    )); 
    stage.show(); 
    } 
} 

Một số ưu điểm của việc này là:

  1. Bạn nhận được các hành vi nút bật tắt mặc định và không cần phải tái thực hiện nó cho mình bằng cách thêm của bạn thiết kế lấy nét, chuột và các bộ xử lý chính vv
  2. Nếu ứng dụng của bạn được chuyển sang nền tảng khác, chẳng hạn như thiết bị di động, nó sẽ hoạt động ngoài hộp phản hồi sự kiện chạm thay vì sự kiện chuột, v.v.
  3. Kiểu dáng của bạn được tách biệt với logic ứng dụng của bạn để dễ dàng thay đổi lại ứng dụng của bạn.

Một thay thế là không sử dụng css và vẫn sử dụng một ToggleButton, nhưng thiết lập đồ họa hình ảnh trong mã:

import javafx.application.Application; 
import javafx.beans.binding.Bindings; 
import javafx.scene.*; 
import javafx.scene.control.ToggleButton; 
import javafx.scene.image.*; 
import javafx.scene.layout.StackPaneBuilder; 
import javafx.stage.Stage; 

public class ToggleButtonImageViaGraphic extends Application { 
    public static void main(String[] args) throws Exception { launch(args); } 
    @Override public void start(final Stage stage) throws Exception { 
    final ToggleButton toggle  = new ToggleButton(); 
    final Image  unselected = new Image(
     "http://icons.iconarchive.com/icons/aha-soft/desktop-buffet/128/Pizza-icon.png" 
    ); 
    final Image  selected = new Image(
     "http://icons.iconarchive.com/icons/aha-soft/desktop-buffet/128/Piece-of-cake-icon.png" 
    ); 
    final ImageView toggleImage = new ImageView(); 
    toggle.setGraphic(toggleImage); 
    toggleImage.imageProperty().bind(Bindings 
     .when(toggle.selectedProperty()) 
     .then(selected) 
     .otherwise(unselected) 
    ); 

    stage.setScene(new Scene(
     StackPaneBuilder.create() 
     .children(toggle) 
     .style("-fx-padding:10; -fx-background-color: cornsilk;") 
     .build() 
    )); 
    stage.show(); 
    } 
} 

Cách tiếp cận dựa trên mã có ưu điểm là bạn không cần phải sử dụng css nếu bạn không hài lòng với nó.

Để có hiệu suất tốt nhất và dễ dàng chuyển đến các hộp cát applet và webstart chưa được ký, hãy gộp hình ảnh với ứng dụng của bạn và tham chiếu chúng bằng url đường dẫn tương đối thay vì tải chúng xuống mạng.

+0

Thật tuyệt vời! Tôi có thể nói gì ?Đó là một câu trả lời thực sự tuyệt vời, cảm ơn rất nhiều. Tôi nghĩ rằng tôi sẽ đi cho các giải pháp đầu tiên, tôi sẽ áp dụng kích thước cho nút của tôi trong mã, nó có vẻ là phổ biến trong ứng dụng JavaFX không giống như Swing. – jerome

+1

Tôi phải thêm -fx-background-color: transparent; trong css để chỉ có nút của tôi chứa đầy hình ảnh của tôi. – jerome

+0

Đó là một câu trả lời hay nhưng thể hiện một điểm yếu trong JavaFX. Loại yêu cầu này là lộn xộn và không được bảo vệ trong thế kỷ 21. –

6

Bạn chỉ cần tạo lớp của riêng bạn được kế thừa từ cấp độ gốc. Đặt một ImageView trên đó và trên các sự kiện chuột và chuột lên chỉ cần thay đổi hình ảnh của ImageView.

public class ImageButton extends Parent { 

    private static final Image NORMAL_IMAGE = ...; 
    private static final Image PRESSED_IMAGE = ...; 

    private final ImageView iv; 

    public ImageButton() { 
     this.iv = new ImageView(NORMAL_IMAGE); 
     this.getChildren().add(this.iv); 

     this.iv.setOnMousePressed(new EventHandler<MouseEvent>() { 

      public void handle(MouseEvent evt) { 
       iv.setImage(PRESSED_IMAGE); 
      } 

     }); 

     // TODO other event handlers like mouse up 

    } 

} 
+0

Đó là một khởi đầu tuyệt vời nhờ – jerome

2

Một sự kết hợp của 2 câu trả lời trước đã thực hiện thủ thuật. Cảm ơn. Một lớp mới kế thừa từ Button. Lưu ý: updateImages() nên được gọi trước khi hiển thị nút.

import javafx.event.EventHandler; 
import javafx.scene.control.Button; 
import javafx.scene.image.Image; 
import javafx.scene.image.ImageView; 
import javafx.scene.input.MouseEvent; 

public class ImageButton extends Button { 

    public void updateImages(final Image selected, final Image unselected) { 
     final ImageView iv = new ImageView(selected); 
     this.getChildren().add(iv); 

     iv.setOnMousePressed(new EventHandler<MouseEvent>() { 
      public void handle(MouseEvent evt) { 
       iv.setImage(unselected); 
      } 
     }); 
     iv.setOnMouseReleased(new EventHandler<MouseEvent>() { 
      public void handle(MouseEvent evt) { 
       iv.setImage(selected); 
      } 
     }); 

     super.setGraphic(iv); 
    } 
} 
Các vấn đề liên quan