i'm studying the mechanism of the event handler on javaFX ,but i'm not sure that i have understand it , in Fact I have a little doubt :
if i have two object , they have all necessary code to handle the event (EventHandler interface ecc..),that they BELONG at the SAME stackPane ,the question is : is there a way for the 1st object to launch an event (ActionEvent for example ) that will be handled by the 2 object though they belong at the same Pane?
Because for what i have understand about the "event route",this is not possible ,at least directly.
In essence my little program have a splitpane that divided in two stackpane the screen,in the left panel i have put a gridpane with the button, each of them have the function that permit to draw a different shape ,in the right panel with a canvas.
My idea it was to launch an ActionEvent in setonaction of each button ,implements the EventHandlers on canvas to capture the event
with relative handle method ,and in the corp of he handle mode discriminate which button is Clicked for drawing the correct shape.
Can someone help me ? Thanks a lot anyway
package es1;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
*
* #author DAVIDE
*/
public class Es1 extends Application {
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
lanciaevento(this.getClass().toString());
}
});
//add a button on left panel and a textfiled on the right for test if the event launched
//on the click of the button is reached by the textfield
Textfield text = new Textfield();
StackPane panel1 = new StackPane();
panel1.getChildren().addAll(btn);
StackPane panel2 = new StackPane();
panel2.getChildren().addAll(text);
splitpane divisore = new splitpane();
divisore.addEventHandler(ActionEvent.ACTION, divisore);
divisore.getItems().addAll(panel1,panel2);
Scene scene = new Scene(divisore, 600, 450);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public void lanciaevento(String oggetto)
{
ActionEvent evento = new ActionEvent();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
package es1;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.SplitPane;
/**
*
* #author DAVIDE
*/
public class splitpane extends SplitPane implements EventHandler<ActionEvent>{
private String message_event;
public String get_message()
{
return(message_event);
}
public void set_message(String messaggio)
{
message_event = messaggio;
}
#Override
public void handle(ActionEvent event) {
System.out.println("mi ha mandato un messaggio "+event.getSource().toString());
}
}
/*
* To change this license header, choose License Headers in Project Properties.
package es1;
import javafx.event.ActionEvent;
javafx.event.EventHandler;
import javafx.scene.control.TextField;
/**
*
* #author DAVIDE
*/
public class Textfield extends TextField implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent event) {
this.appendText(event.getSource().toString());
}
}
Related
I am trying to create a Javafx game and I want the user to be able to input their name using a dialogue. The problem is that when I try to position the dialogue using setY() or setX() nothing changes. I should note that I am using an online IDE so if this is the problem please somebody tell me.
import javafx.stage.Modality;
import javafx.scene.control.*;
import javafx.scene.control.Dialog;
import javafx.geometry.*;
import javafx.stage.Stage;
import javafx.scene.Scene;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
VBox page = new VBox();
Scene scene = new Scene(page, 600, 700);
primaryStage.setScene(scene);
primaryStage.show();
setUserName();
}
public static void setUserName() {
Dialog<String> dialog = new Dialog<String>();
dialog.setTitle("Dialog");
ButtonType type = new ButtonType("Ok", ButtonData.OK_DONE);
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initStyle(StageStyle.UNDECORATED);
dialog.setContentText("Hello World");
dialog.setY(100);
dialog.showAndWait();
}
public static void main(String[] args) {
launch(args);
}
}
I've been working a lot in JavaFX lately, by writing code only -- no CSS no FXML and I want to keep it that way. I've managed to do all of the stuff I wanted that way except that now I can't set the text color of TextField without using CSS, so I'm asking for advice here. Is there any way to do it, no matter how hacky it is?
Note that I'm still using Java 8 version.
Considering your points : "No CSS" and "how hacky it can be.." below is one way to achieve the text coloring.
import com.sun.javafx.scene.control.skin.TextFieldSkin;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class TextField_TextColor_Demo extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
TextField textField = new TextField();
textField.setSkin(new TextFieldSkin(textField){
#Override
protected void layoutChildren(double x, double y, double w, double h) {
super.layoutChildren(x, y, w, h);
if(textField.getProperties().get("colorChanged")==null) {
textFill.setValue(Color.RED);
textField.getProperties().put("colorChanged",true);
}
}
});
StackPane root = new StackPane(textField);
Scene scene = new Scene(root, 300,300);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String... args){
Application.launch(args);
}
}
I could not make it work. But made another solution. Although the caret color also changes.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.skin.TextFieldSkin;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.stage.Stage;
public class TextField_TextColor_Demo extends Application {
#Override
public void start(Stage stage) throws Exception {
TextField txt = new TextField();
CustomTextFieldSkin skin = new CustomTextFieldSkin(txt);
txt.setSkin(skin);
skin.setHighlight(Color.RED);
HBox box = new HBox(txt);;
Scene scene = new Scene(box, 300, 100);
stage.setScene(scene);
stage.show();
}
public class CustomTextFieldSkin extends TextFieldSkin{
public CustomTextFieldSkin(TextField textField) {
super(textField);
}
public void setHighlight(Paint value) {
setTextFill(value);
}
}
public static void main(String... args){
Application.launch(args);
}
}
Seems it is possible to color the caret separately, according these two answers:
https://stackoverflow.com/a/47876289/7989121
https://stackoverflow.com/a/27323035/7989121
Both use caretPath though, which I could not use due it not being visible according to my IDE
I run into a problem, that I really don't know how to probably create a functional buttons in Java Swing GUI ( I guess this is how I should call it). I create a print statement to check whether if my buttons work or not,and it doesn't work.Here is my code.
import javax.swing.JFrame;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.*;
import java.awt.event.*;
/**
* Create a JFrame to hold our beautiful drawings.
*/
public class Jan1UI implements ActionListener
{
/**
* Creates a JFrame and adds our drawings
*
* #param args not used
*/
static JFrame frame = new JFrame();
static JButton nextBut = new JButton("NEXT");
static NextDayComponents nextDaycomponent = new NextDayComponents();
public static void main(String[] args)
{
//Set up the JFrame
nextBut.setBounds(860, 540, 100, 40);
/*nextBut.setOpaque(false);
nextBut.setContentAreaFilled(false);
nextBut.setBorderPainted(false);
*/
frame.setSize(1920, 1080);
frame.setTitle("Jan1UI demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.WHITE);
frame.setVisible(true);
frame.add(nextBut);
frame.add(nextDaycomponent);
}
public void actionPerformed(ActionEvent e)
{
JButton b = (JButton)e.getSource();
if (b == nextBut)
{
System.out.println("ok");
}
}
}
/*static class Butt implements ActionListener
{
}*/
You need to add an action listener to the button, but cant do that in main as it is a static method. Instead, create a constructor to do thework similar to this:
public class Jan1UI implements ActionListener
{
public static void main(String[] args)
{
Jan1UI ui = new Jan1UI();
}
public Jan1UI ()
{
JFrame frame = new JFrame();
JButton nextBut = new JButton("NEXT");
nextBut.setBounds(860, 540, 100, 40);
nextBut.addActionListener(this);
frame.setSize(1920, 1080);
frame.setTitle("Jan1UI demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.WHITE);
frame.setVisible(true);
frame.add(nextBut);
}
public void actionPerformed(ActionEvent e)
{
System.out.println("ok");
}
}
You must bound an ActionListener to the button:
nextBut.setBounds(860, 540, 100, 40);
nextBut.addActionListener(new Jan1UI());
I have a StackPane containing several elements (Rectangles). I added an ActionEventHandler to all of them. I expect that when Rectangle object is clicked it starts anly the event added to its. Instead I see that both events are started, like I have pressed Rectangle and StackPane together. Here's the code:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package provapanetile;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.TilePane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
/**
*
* #author Ambra
*/
public class ProvaPaneTile extends Application {
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
TilePane tp = new TilePane();
tp.setVgap(10);
tp.setHgap(10);
for(int i = 0; i<5; i++){
tp.getChildren().add(new Rectangle(50, 50, Color.AZURE));
}
addListners(root, tp);
root.getChildren().add(tp);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public void addListners(StackPane sp, TilePane tp){
sp.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("You pressed StackPointer");
}
});
tp.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("You pressed TilePane");
}
});
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Clicking ones on a Rectangle I get this 2 messagges:
You pressed TilePane
You pressed StackPointer
Consume the event in the handler on the tile pane:
tp.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("You pressed TilePane");
event.consume();
}
});
Now when you click on the TilePane, only the handler registered with the tile pane will be invoked.
Note that in this example, the TilePane entirely covers the StackPane, so it's impossible to actually invoke the handler on the StackPane, which is probably not what you want. To fix that, you would need to manage the layout so that the TilePane did not grow to the full size of the StackPane; but obviously this is just an example to demonstrate the issue so perhaps this is enough for your real application...
When I add image and text to a button, by default elements are set horizontally. How can I change this behavior to get text under image ?
Set the contentDisplayProperty on the button.
button.setContentDisplay(ContentDisplay.TOP);
Here is an executable example:
import javafx.application.Application;
import javafx.event.*;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ButtonGraphicTest extends Application {
#Override public void start(final Stage stage) throws Exception {
final Label response = new Label();
final ImageView imageView = new ImageView(
new Image("http://icons.iconarchive.com/icons/eponas-deeway/colobrush/128/heart-2-icon.png")
);
final Button button = new Button("I love you", imageView);
button.setStyle("-fx-base: coral;");
button.setContentDisplay(ContentDisplay.TOP);
button.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
response.setText("I love you too!");
}
});
final VBox layout = new VBox(10);
layout.setAlignment(Pos.CENTER);
layout.getChildren().addAll(button, response);
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10; -fx-font-size: 20;");
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) { launch(args); }
}
// icon license: (creative commons with attribution) http://creativecommons.org/licenses/by-nc-nd/3.0/
// icon artist attribution page: (eponas-deeway) http://eponas-deeway.deviantart.com/gallery/#/d1s7uih