Я хотел бы создать пользовательскую кнопку, которая имеет два состояния нажатыми или нет, например, кнопку переключения. У меня есть два изображения для этого (нажата и не нажата), так как я могу создать кнопку и отобразить ее с помощью моих изображений? Кнопка должна иметь размер изображения.
Я не использую FXML.
Спасибо, что помогли.
JavaFX - создать пользовательскую кнопку с изображением
Ответ 1
Есть несколько способов сделать это, я расскажу о своих избранных.
Используйте ToggleButton и примените к нему особый стиль. Я предлагаю это, потому что ваш требуемый элемент управления "как кнопка переключения", но просто отличается от стиля кнопки переключения по умолчанию.
Мой предпочтительный метод заключается в определении графика для кнопки в 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');
}
ИЛИ используйте прилагаемый css для определения фонового изображения.
// 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');
}
Я предпочитаю -fx-графическую спецификацию по спецификациям -fx-background- *, поскольку правила для укладки фоновых изображений сложны, и настройка фона не позволяет автоматически изменять размер изображения на изображении, тогда как настройка изображения выполняется.
И некоторый пример кода:
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();
}
}
Некоторые преимущества этого:
- Вы получаете поведение кнопки переключателя по умолчанию и не должны повторно выполнять его самостоятельно, добавляя свой собственный стиль фокусировки, мышь и обработчики ключей и т.д.
- Если ваше приложение будет перенесено на другую платформу, например мобильное устройство, оно будет работать вне коробки, реагируя на события касания, а не на события мыши и т.д.
- Ваш стиль отделен от вашей логики приложения, так что вам проще восстановить ваше приложение.
Альтернативой является не использование css и использование ToggleButton, но установка графического изображения в коде:
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();
}
}
Подход на основе кода имеет то преимущество, что вам не нужно использовать css, если вы несовместимы с ним.
Для лучшей производительности и простоты переноса в беззнаковые апплеты и веб-серверные песочницы объедините изображения с вашим приложением и скопируйте их по относительным URL-адресам пути, а не загрузите их из сети.
Ответ 2
Вам просто нужно создать свой собственный класс, унаследованный от родителя. Поместите ImageView на это, а на событиях в мыши и мыши просто измените изображения 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
}
}
Ответ 3
Комбинация предыдущих двух ответов сделала трюк. Благодарю. Новый класс, который наследуется от Button. Примечание: updateImages() следует вызвать перед отображением кнопки.
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);
}
}