By default RadioButtons have their text label to the right of the button. I want the label to appear below the button instead. I found an old discussion on the Oracle forums but the solutions aren't great or just don't work.
I can create a custom component with a text-less radio button and a separate text label and position them as in a VBox. But then only the button itself responds to user events and not the whole thing.
Is there no simple way to reposition the label?
There is no "simple" way to do this (simple means setting a single property or something like this).
As a workaround you could do something like you mentioned with a VBox, but with a Label: You can set the RadioButton as the graphic of the Label and set the contentDisplayProperty to TOP (RadioButton is placed on top of the Label). And then you can add an event handler on the Label to select the RadioButton on click.
An example with this approach
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane root = new BorderPane();
Scene scene = new Scene(root, 400, 400);
HBox hbox = new HBox();
hbox.getChildren().add(createRadioLabel("Radio on the left", ContentDisplay.LEFT));
hbox.getChildren().add(createRadioLabel("Radio on the top", ContentDisplay.TOP));
hbox.getChildren().add(createRadioLabel("Radio on the bottom", ContentDisplay.BOTTOM));
hbox.getChildren().add(createRadioLabel("Radio on the right", ContentDisplay.RIGHT));
hbox.setSpacing(30);
root.setCenter(hbox);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
private Label createRadioLabel(String text, ContentDisplay cd) {
Label label = new Label(text);
label.setGraphic(new RadioButton());
label.setContentDisplay(cd);
label.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
RadioButton radioButton = (RadioButton) ((Label) e.getSource()).getGraphic();
radioButton.requestFocus();
radioButton.setSelected(!radioButton.isSelected());
});
return label;
}
public static void main(String[] args) {
launch(args);
}
}
And the produced RadioButtons:
Alternatively, if you want to have the text of the RadioButton rotated around the dot, you can use CSS rotations, with the attribute -fx-rotate:
.radio-button { -fx-rotate:180; }
.radio-button > .text { -fx-rotate: 180; }
The first selector will rotate the whole RadioButton, so as result the text will be placed on the left side of the "dot", upside down. The second selector rotates the text back to the normal direction.
Example
This example shows a RadioButton whose Text can be placed to any side of the "dot" specified by a ComboBox selection.
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane root = new BorderPane();
Scene scene = new Scene(root, 400, 400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
RadioButton rb = new RadioButton("In all directions);
ComboBox<PseudoClass> combo = new ComboBox<>();
combo.getItems().addAll(PseudoClass.getPseudoClass("left"),
PseudoClass.getPseudoClass("top"),
PseudoClass.getPseudoClass("right"),
PseudoClass.getPseudoClass("bottom"));
combo.valueProperty().addListener((obs, oldVal, newVal) -> {
if (oldVal != null)
rb.pseudoClassStateChanged(oldVal, false);
rb.pseudoClassStateChanged(newVal, true);
});
root.setTop(combo);
root.setCenter(rb);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
application.css
.radio-button:left > .text { -fx-rotate: 180; }
.radio-button:left { -fx-rotate:180; }
.radio-button:right > .text { -fx-rotate: 0; }
.radio-button:right { -fx-rotate:0; }
.radio-button:top > .text { -fx-rotate: 0; }
.radio-button:top { -fx-rotate:-90; }
.radio-button:bottom > .text { -fx-rotate: 0; }
.radio-button:bottom { -fx-rotate:90; }
And the displayed RadioButton:
Related
I have a chart. A double click on a table row opens a window in which I can edit the information of the row. Double-clicking on another line opens the corresponding window. Everything works as it should, except that each window should open only once. If it is already open, the window should return to the foreground. Unfortunately I can't see what's wrong here and would be grateful for a hint
private void loadTable() {
// I omitted the part where the table is populated.
mytable.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.isPrimaryButtonDown() && event.getClickCount() == 2) {
TableItem table_item = table_view.getSelectionModel().getSelectedItem();
try {
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource("/application/Popup.fxml"));
Scene scene = new Scene(fxmlLoader.load());
Stage stage = new Stage();
stage.setScene(scene);
MyController controller = fxmlLoader.<MyController>getController();
boolean result = controller.init(stage, table_item);
if (stage.isShowing()) {
stage.toFront();
System.out.println("Show this popup.");
} else {
if (result) {
stage.show();
System.out.println("Open this popup.");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
}
Try adding
stage.initModality(Modality.WINDOW_MODAL);
after
Stage stage = new Stage();
This will make the Parent stage unclickable until this stage is closed.
i want to change color my label "Kategori" when mouse pressed and exit on "paneKategori" (Look at the picture).
my code in fxml controller
#FXML
void btnProdukMouseEntered(javafx.scene.input.MouseEvent event) {
if ( event.getSource() == paneKategori) {
labelKategori.setStyle("-fx-background-color: #FF0000;");
}
}
that is no working for me.
this my GUI in scene builder.
Create handlers for the MOUSE_PRESSED, MOUSE_DRAGGED and MOUSE_RELEASED handlers. Check, if the event's location is inside the node in MOUSE_DRAGGED.
Example
#Override
public void start(Stage primaryStage) throws Exception {
Button button = new Button("Drag me");
final String style = "-fx-background-color: red;";
button.setOnMousePressed(evt -> {
if (evt.isPrimaryButtonDown()) {
button.setStyle(style);
}
});
button.setOnMouseDragged(evt -> {
if (evt.isPrimaryButtonDown()) {
button.setStyle(button.contains(evt.getX(), evt.getY()) ? style : null);
}
});
button.setOnMouseReleased(evt -> {
button.setStyle(null);
});
Scene scene = new Scene(new StackPane(button), 300, 300);
primaryStage.setScene(scene);
primaryStage.show();
}
BTW: Checking the source in an event handler is bad practice in most cases, since you could easily avoid the check by only registering the event handler for the node you're comparing the source property of the event to.
I would like to show an image as a tooltip. It works OK but at some random points it shows fluctuation. I want to show it normally without getting fluctuate.
I show a new scene (in which i added my image-view with image) on mouse enter event and close it on mouse leave event event
// MOUSE ENTER PHOTO CORRECTIO
#FXML
private void mouseEnterPhotoCorrection(MouseEvent event) {
if (f_ShowToolTip) {
Stage stg = funShowImageTooltip();
double x, y;
x = event.getScreenX();
y = event.getScreenY();
stg.setX(x);
stg.setY(y);
stg.show();
f_ShowToolTip = false;
}
}
// MOUSE LEAVE PHOTO CORRECTIO
#FXML
private void mouseLeavePhotoCorrection(MouseEvent event) {
funHideImageTooltip();
f_ShowToolTip = true;
}
/****************************** FUNCTIONS *******************************/
Stage s;
boolean f_ShowToolTip;
// FUNCTION TO SET INITAL STATE OF PHOTOS AND CORRECTION
private void funInitPhotosCorrection()
{
f_ShowToolTip = true;
}
private Stage funShowImageTooltip()
{
try {
s = new Stage();
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("frmImageToolTip.fxml"));
Parent root = (Parent) fxmlLoader.load();
Scene scene = new Scene(root);
s.setScene(scene);
s.setResizable(false);
s.initModality(Modality.WINDOW_MODAL);
s.initStyle(StageStyle.UNDECORATED);
s.setResizable(false);
double x, y;
//x = btn_Red.
s.show();
}catch(Exception e1)
{
}
return s;
}
private void funHideImageTooltip()
{
try {
s.close();
} catch (Exception e) {
}
}
If you just simply want to have a tooltip over a Node (a Button in your case), it is reasonable to use a Tooltip and its graphicProperty rather than showing a different Stage.
// Load the image with the needed size
Image image = new Image("...", 150, 150, true, true);
// Place it over a Button
Button button = new Button();
Tooltip tooltip = new Tooltip();
tooltip.setGraphic(new ImageView(image));
button.setTooltip(tooltip);
I'm trying to add a MouseClicked event listener to a Tree Cell so that It fires when a user clicks on either the Graphic or the String value of the cell.
TestApp.java
public class TestApp extends Application {
#Override
public void start(Stage stage) throws Exception {
Image image = new Image(getClass().getResourceAsStream("icon.png"));
TreeItem<String> root = new TreeItem<String>("Root");
root.setGraphic(new ImageView(image));
TreeItem<String> child = new TreeItem<String>("Child");
root.getChildren().add(child);
TreeView<String> tree = new TreeView<String>(root);
tree.setCellFactory(new TestTreeCellFactory());
StackPane pane = new StackPane();
pane.getChildren().add(tree);
stage.setScene(new Scene(pane, 300, 250));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
private class TestTreeCellFactory implements Callback<TreeView<String>, TreeCell<String>> {
#Override
public TreeCell<String> call(TreeView<String> treeView) {
CheckBoxTreeCell<String> tc = new CheckBoxTreeCell<String>();
tc.setOnMouseClicked((event) -> mousePressed(event, treeView));
return tc;
}
public void mousePressed(MouseEvent event, TreeView<String> treeView) {
if(event.getButton().equals(MouseButton.SECONDARY)) {
System.out.println("Right Mouse Button Clicked!");
}
}
}
}
The mouse event is currently firing when I click on the String Value but is not firing when I click on the Graphic icon. Upon trying to debug the issue, here are some of my observations:
It seems like the Graphic is somehow tied to the Checkbox (clicking on the Graphic will toggle the checkbox value).
Clicking the Graphic will not select the row while clicking on the text value will.
Is there a way to attach the listener to the Tree Cell's graphic once it gets populated or am I thinking about this in the wrong way?
Hello I want to know how to intercept the Paste Event in the JavaFX HTMLEditor.
You can't. The HTMLEditor uses a WebPage internally. Basically during a paste event it sends a "paste" command via
private boolean executeCommand(String command, String value) {
return webPage.executeCommand(command, value);
}
and then a
twkExecuteCommand(getPage(), command, value);
However, you could intercept everything that implicitly invokes the paste event like the button click or a CTRL+V key combination and depending on what you wish to do consume the event.
Example:
public class HTMLEditorSample extends Application {
#Override
public void start(Stage stage) {
final HTMLEditor htmlEditor = new HTMLEditor();
Scene scene = new Scene(htmlEditor, 800, 600);
stage.setScene(scene);
stage.show();
Button button = (Button) htmlEditor.lookup(".html-editor-paste");
button.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> {
System.out.println("paste pressed");
// e.consume();
});
htmlEditor.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
if( e.isControlDown() && e.getCode() == KeyCode.V) {
System.out.println( "CTRL+V pressed");
// e.consume();
}
});
}
public static void main(String[] args) {
launch(args);
}
}
As to your other question with pasting only plain text to the html editor, you could do it like this:
public class HTMLEditorSample extends Application {
#Override
public void start(Stage stage) {
final HTMLEditor htmlEditor = new HTMLEditor();
Scene scene = new Scene(htmlEditor, 800, 600);
stage.setScene(scene);
stage.show();
Button button = (Button) htmlEditor.lookup(".html-editor-paste");
button.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> {
modifyClipboard();
});
htmlEditor.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
if( e.isControlDown() && e.getCode() == KeyCode.V) {
modifyClipboard();
}
});
}
private void modifyClipboard() {
Clipboard clipboard = Clipboard.getSystemClipboard();
String plainText = clipboard.getString();
ClipboardContent content = new ClipboardContent();
content.putString(plainText);
clipboard.setContent(content);
}
public static void main(String[] args) {
launch(args);
}
}
It's a workaround and ugly because you should never modify the clipboard content unless the user wants to, but it works. On the other hand, it may be possible to revert the clipboard content back to its original state after the paste operation.
Edit:
Here's how you could access the contextmenu, e. g. for disabling it:
WebView webView = (WebView) htmlEditor.lookup(".web-view");
webView.setContextMenuEnabled(false);
Don't try this line, because it's always return a NULL:
Button button = (Button) htmlEditor.lookup(".html-editor-paste");
The only way to get the Paste button from HTMLEditor is the solution from #taha:
htmlEditor.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> { if (e.getTarget().toString().contains("html-editor-paste")) { System.out.println("paste pressed"); });