Saturday, August 31, 2013

Set background color of JavaFX ListView cells, with CSS

The old post show how to "Hide empty cell of TableView with CSS". This example apply similar approach, to set background color for various cells, empty, hover, selected.

Set background color of JavaFX ListView cells
Set background color of JavaFX ListView cells

Create javafx_testtableview/style_tableview.css file.
.table-row-cell:empty {
    -fx-background-color: khaki;
    -fx-border-color: grey
}

.table-row-cell:hover{
    -fx-background-color: blanchedalmond;
}

.table-row-cell:selected{
    -fx-background-color: chocolate;
}


Java code.
package javafx_testtableview;
 
import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
 
/**
 * @web http://java-buddy.blogspot.com/
 */
public class JavaFX_TestTableView extends Application {
 
    public static class Record {
 
        private final SimpleIntegerProperty id;
        private final SimpleStringProperty name;
        private final SimpleStringProperty lastName;
        private final SimpleStringProperty email;
 
        private Record(int id, String name, String lastName, String email) {
            this.id = new SimpleIntegerProperty(id);
            this.name = new SimpleStringProperty(name);
            this.lastName = new SimpleStringProperty(lastName);
            this.email = new SimpleStringProperty(email);
        }
 
        public int getId() {
            return this.id.get();
        }
 
        public void setId(int id) {
            this.id.set(id);
        }
 
        public String getName() {
            return this.name.get();
        }
 
        public void setName(String name) {
            this.name.set(name);
        }
 
        public String getLastName() {
            return this.lastName.get();
        }
 
        public void setLastName(String lastName) {
            this.lastName.set(lastName);
        }
 
        public String getEmail() {
            return this.email.get();
        }
 
        public void setEmail(String email) {
            this.email.set(email);
        }
    }
    private TableView<Record> tableView = new TableView<>();
    private final ObservableList<Record> recordList = FXCollections.observableArrayList();
 
    private void prepareRecordList() {
        recordList.add(new Record(12, "William", "Austin", "xxx@xxx.xxx"));
        recordList.add(new Record(15, "Chris", "redfield", "yyy@yyy.yyy"));
        recordList.add(new Record(1, "Java", "Buddy", "javabuddy@abc.yyy"));
        recordList.add(new Record(2, "Eric", "Buddy", "ericbuddy@abc.yyy"));
        recordList.add(new Record(3, "Peter", "handsome", "peter@abc.yyy"));
    }
 
    @Override
    public void start(Stage primaryStage) {
        Scene scene = new Scene(new Group());
        primaryStage.setTitle("http://java-buddy.blogspot.com/");
        primaryStage.setWidth(400);
        primaryStage.setHeight(400);
 
        prepareRecordList();
 
        tableView.setEditable(false);
 
        Callback<TableColumn, TableCell> integerCellFactory =
                new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn p) {
                MyIntegerTableCell cell = new MyIntegerTableCell();
                cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new MyEventHandler());
                return cell;
            }
        };
 
        Callback<TableColumn, TableCell> stringCellFactory =
                new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn p) {
                MyStringTableCell cell = new MyStringTableCell();
                cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new MyEventHandler());
                return cell;
            }
        };
 
        TableColumn colId = new TableColumn("ID");
        colId.setCellValueFactory(
                new PropertyValueFactory<Record, String>("id"));
        colId.setCellFactory(integerCellFactory);
 
        TableColumn colName = new TableColumn("Name");
        colName.setCellValueFactory(
                new PropertyValueFactory<Record, String>("name"));
        colName.setCellFactory(stringCellFactory);
 
        TableColumn colLastName = new TableColumn("Last Name");
        colLastName.setCellValueFactory(
                new PropertyValueFactory<Record, String>("lastName"));
        colLastName.setCellFactory(stringCellFactory);
 
        TableColumn colEmail = new TableColumn("Email");
        colEmail.setCellValueFactory(
                new PropertyValueFactory<Record, String>("email"));
        colEmail.setCellFactory(stringCellFactory);
 
        tableView.setItems(recordList);
        tableView.getColumns().addAll(colId, colName, colLastName, colEmail);
 
        tableView.getStylesheets().add("javafx_testtableview/style_tableview");
 
        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().add(tableView);
 
        ((Group) scene.getRoot()).getChildren().addAll(vbox);
 
        primaryStage.setScene(scene);
        primaryStage.show();
    }
 
    public static void main(String[] args) {
        launch(args);
    }
 
    class MyIntegerTableCell extends TableCell<Record, Integer> {
 
        @Override
        public void updateItem(Integer item, boolean empty) {
            super.updateItem(item, empty);
            setText(empty ? null : getString());
            setGraphic(null);
        }
 
        private String getString() {
            return getItem() == null ? "" : getItem().toString();
        }
    }
 
    class MyStringTableCell extends TableCell<Record, String> {
 
        @Override
        public void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            setText(empty ? null : getString());
            setGraphic(null);
        }
 
        private String getString() {
            return getItem() == null ? "" : getItem().toString();
        }
    }
 
    class MyEventHandler implements EventHandler<MouseEvent> {
 
        @Override
        public void handle(MouseEvent t) {
            TableCell c = (TableCell) t.getSource();
            int index = c.getIndex();
 
            try {
                Record item = recordList.get(index);
                System.out.println("id = " + item.getId());
                System.out.println("name = " + item.getName());
                System.out.println("lastName = " + item.getLastName());
                System.out.println("email = " + item.getEmail());
            } catch (IndexOutOfBoundsException exception) {
                //...
            }
 
        }
    }
}

Friday, August 30, 2013

JavaFX example: bind more than one value with NumberBinding

This example show to to bind the value of sliderSum to the sum of slider1 and slider2 values with NumberBinding.

bind more than one value with NumberBinding
Bind more than one value with NumberBinding

package javafx_numberbinding;

import javafx.application.Application;
import javafx.beans.binding.NumberBinding;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

/**
 *
 * @web http://java-buddy.blogspot.com/
 */
public class JavaFX_NumberBinding extends Application {
    
    @Override
    public void start(Stage primaryStage) {

        Slider slider1 = new Slider(0, 100, 0);
        Slider slider2 = new Slider(0, 50, 0);
        Slider sliderBind1 = new Slider(0, 100, 0);
        Slider sliderBind2 = new Slider(0, 50, 0);
        Slider sliderSum = new Slider(0, 150, 0);
        
        sliderBind1.valueProperty().bind(slider1.valueProperty());
        sliderBind2.valueProperty().bind(slider2.valueProperty());
        
        NumberBinding numberSum = slider1.valueProperty().add(slider2.valueProperty());
        sliderSum.valueProperty().bind(numberSum);
        
        VBox vBox = new VBox();
        vBox.setPadding(new Insets(5, 5, 5, 5));
        vBox.setSpacing(5);
        vBox.getChildren().addAll(
                slider1, 
                slider2,
                sliderBind1,
                sliderBind2,
                sliderSum);
        
        StackPane root = new StackPane();
        root.getChildren().add(vBox);
        
        Scene scene = new Scene(root, 300, 250);
        
        primaryStage.setTitle("java-buddy.blogspot.com");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}


Sunday, August 25, 2013

Implement custom Properties for bind() and ChangeListener()

In the post of "JavaFX example of Service", the UI elements progressBar and labelCount are bind to build-in properties, progressProperty and messageProperty, of Service. Now I want to update progressBar and labelCount in 5 second; we can create our custom Properties, process5sec and Message5sec, such that we can bind them to UI elements or addListener() to trace the changing for them.

Implement custom Properties for bind() and ChangeListener()
Implement custom Properties for bind() and ChangeListener()

package javafx_service;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

/**
 *
 * @web http://java-buddy.blogspot.com/
 */
public class JavaFX_Service extends Application {

    MyService myService;

    @Override
    public void start(Stage primaryStage) {

        final ProgressBar progressBar = new ProgressBar();
        final Label labelCount = new Label();
        final Label labelState = new Label();
        final Label labelSucceeded = new Label();

        myService = new MyService();

        myService.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
            @Override
            public void handle(WorkerStateEvent t) {
                labelSucceeded.setText("OnSucceeded");
            }
        });

        myService.setOnRunning(new EventHandler<WorkerStateEvent>() {
            @Override
            public void handle(WorkerStateEvent t) {
                labelSucceeded.setText("OnRunning");
            }
        });

        myService.setOnFailed(new EventHandler<WorkerStateEvent>() {
            @Override
            public void handle(WorkerStateEvent t) {
                labelSucceeded.setText("OnFailed");
            }
        });

        myService.process5secProperty().addListener(new ChangeListener(){

            @Override
            public void changed(ObservableValue ov, Object t, Object t1) {
                
                double p = (double)(((Integer)t1).intValue());
                progressBar.setProgress(p/50);
            }
        });
        
        labelCount.textProperty().bind(myService.Message5sec);

        Button btnStart = new Button("Start Service");
        btnStart.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                myService.start();
            }
        });

        Button btnReadTaskState = new Button("Read Service State");
        btnReadTaskState.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                labelState.setText(myService.getState().toString());
            }
        });

        VBox vBox = new VBox();
        vBox.setPadding(new Insets(5, 5, 5, 5));
        vBox.setSpacing(5);
        vBox.getChildren().addAll(
                progressBar,
                labelCount,
                btnStart,
                btnReadTaskState,
                labelState,
                labelSucceeded);

        StackPane root = new StackPane();
        root.getChildren().add(vBox);

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("java-buddy.blogspot.com");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

    private class MyService extends Service<Void> {

        private final IntegerProperty process5sec = new SimpleIntegerProperty();

        public int getProcess5sec() {
            return process5sec.get();
        }

        public void setProcess5sec(int value) {
            process5sec.set(value);
        }

        public IntegerProperty process5secProperty() {
            return process5sec;
        }
        private final StringProperty Message5sec = new SimpleStringProperty();

        public String getMessage5sec() {
            return Message5sec.get();
        }

        public void setMessage5sec(String value) {
            Message5sec.set(value);
        }

        public StringProperty Message5secProperty() {
            return Message5sec;
        }

        @Override
        protected Task<Void> createTask() {
            return new Task<Void>() {
                @Override
                protected Void call() throws Exception {
                    int max = 50;
                    for (int i = 1; i <= max; i++) {
                        if (isCancelled()) {
                            break;
                        }

                        if (i % 5 == 0) {
                            final int i5sec = i;
                            Platform.runLater(new Runnable() {
                                @Override
                                public void run() {
                                    setProcess5sec(i5sec);
                                    setMessage5sec(String.valueOf(i5sec));    
                                }
                            });
                        }

                        Thread.sleep(100);
                    }
                    return null;
                }
            };
        }
    }
}