Affichage des articles dont le libellé est Search TextBox. Afficher tous les articles
Affichage des articles dont le libellé est Search TextBox. Afficher tous les articles

lundi 18 juin 2012

JavaFX 2.x custom component compatible with FXML


In November, last year, I wrote a little example on how to extend an existing component in JavaFx 2.0.
Today, I would use this component in FXML and make a little demo.
The application for the demo is very simple:
  • One SearchTextBox component (custom component) with events on OnCrossButtonMouseClicked and OnSearchEvent.
  • One ComboBox to change the font size of the SearchTextBox component.

samedi 8 mai 2010

JavaFX custom component in JavaFX 1.3

In JavaFX 1.2, Control extended CustomNode then we could override the create function to customize an existing component.  
With JavaFX 1.3, Control now extends
Parent directly then we do not have any more the create function and my custom component doesn’t compile any more … (because I used the create function to customize my components)

Then, to customize an existing component in JavaFX 1.3, I tried another way


I use the initBlock to create the nodes that I want to add to the existing component to customize it
and then I add these nodes to the children sequence of the existing component.

...
   init {
          var g = Group {
                    content: [
                                Group {
                                    ...
                                    content: [
                                        Circle {
                                               ...
                                        }
                                        Rectangle {
                                               ....
                                        }
                                     ...
                                    ]
                                    ...
                    ]
                }
           insert g into children;
        }
   ...
Now, I have a problem with the css, I want to have a default css for my SearchTextBox which is loaded by default by my component (not in the Scene by the developer) and which can be overridden by the developer.
If you have a solution, please let me know!
This example works on: Windows (Seven), Linux (Ubuntu 10.04) and Mac OS X (10.6.3)  with the Default toolkit and the Prism toolkit (JVM argument: -Xtoolkit prism) but there is one bug when you run it as an applet on Mac OS X.
The button have a wrong size, the text is too long….
[update August 8, 2010]this issue is fixed in JavaFX 1.3.1




SearchTextBox.fx
package customcomponent;

import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.input.MouseEvent;
import javafx.scene.control.TextBox;
import javafx.scene.input.KeyEvent;

/**
 * @author Patrick
 */
public class SearchTextBox extends TextBox {

    public var onResetSearch: function(): Void;
    public var onSearch: function(s: String): Void;

    override var style = "-fx-padding: 0 16 0 0; ";
    //override var styleClass = "searchTextBox text-box";
    //override var styleClass = "searchTextBox";

    override var onKeyTyped = function(event:KeyEvent){
        if (this.rawText!=""){
            onSearch(this.rawText);
        }else{
            onResetSearch();
        }
    }

    init {
          var g = Group {
                    content: [
                                Group {
                                    var crossWidth = bind this.layoutBounds.height * 0.45;
                                    var crossHeight = bind this.layoutBounds.height * 0.05;
                                    visible: bind this.rawText.length() > 0
                                    layoutX: bind this.layoutBounds.width - (this.layoutBounds.height / 2.0)
                                    layoutY: bind this.layoutBounds.height / 2.0
                                    content: [
                                        Circle {
                                            fill: Color.GRAY
                                            radius: bind this.layoutBounds.height * 0.325 // 65% of the texbox height and div 2 for the radius
                                        }
                                        Rectangle {
                                            width: bind crossWidth
                                            height: bind crossHeight
                                            translateX: bind 0 - crossWidth / 2.0
                                            translateY: bind 0 - crossHeight / 2.0
                                            fill: Color.WHITE
                                            rotate: 45
                                        }
                                        Rectangle {
                                            width: bind crossWidth
                                            height: bind crossHeight
                                            translateX: bind 0 - crossWidth / 2.0
                                            translateY: bind 0 - crossHeight / 2.0
                                            fill: Color.WHITE
                                            rotate: -45
                                        }
                                    ]
                                    onMouseClicked: function (event: MouseEvent) {
                                        this.commit();
                                        this.text = "";
                                        onResetSearch();
                                    }
                                }
                    ]
                }           
           insert g into children;
        }
}

Main.fx
package searchtextbox;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.control.Button;
import javafx.scene.control.RadioButton;

import javafx.scene.control.ToggleGroup;
import customcomponent.SearchTextBox;

/**
 * @author Patrick
 */

class ExtRadioButton extends RadioButton {
    public var action:function();

    override public var selected on replace {
        if (selected) {
            action();
        }
    }
}

def macStyleSheet="{__DIR__}resources/mac.css";
def defaultStyleSheet = "/customcomponent/stbcaspian.css";
var stylesheets:String = macStyleSheet;

Stage {
    title: "Application title"
    width: 250
    height: 200

    var cssToggleGroup = ToggleGroup {};

    scene: Scene {
        stylesheets : bind stylesheets
        content: [
            Text {
                font : Font {
                    size : 16
                }
                x: 10
                y: 30
                content: "Search "
            }
            SearchTextBox {
                    styleClass : "searchTextBox"
                    translateX :10
                    translateY :40


                    onResetSearch:function(){
                        println("reset !");
                    }
                    onSearch:function(s: String){
                        println("Search of : {s}");
                    }
            }
            Button {
                    text: "just a button to change focus"
                    translateX :10
                    translateY :80
                    action: function() {
                        println("Hello !")
                   }
            }

            ExtRadioButton {
                            text: "use the default CSS"
                            translateX :10
                            translateY :110
                            toggleGroup: cssToggleGroup

                            action: function() {
                                stylesheets = defaultStyleSheet;
                            }
            }

            ExtRadioButton {
                            text: "use the mac CSS"
                            translateX :10
                            translateY :130
                            toggleGroup: cssToggleGroup
                            selected: true

                            action: function() {
                                stylesheets = macStyleSheet;
                            }
            }
        ]
    }
}

mercredi 14 octobre 2009

JavaFX Custom Component

This is just an example to show how you can create your own component from an existing component (here a TextBox).

For that, I wrote a new UI component which is a search text box like you can have it on Mac OS X. This search text box is just a TextBox enhanced with one method which is called each time you enter or delete a character and a small button to reset the criteria in the search text box.

The only problem is this line

override var style = "padding-right: 25 ";

which is not compatible with common profile, but I don’t know how to do that differently.

You can try this JavaFX custom component in the applet below

SearchTextBox.fx
/*
 * StatusField.fx
 *
 * Created on 3 oct. 2009, 00:44:26
 */

package customcomponent;

import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.control.TextBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

import javafx.scene.shape.Rectangle;

import javafx.scene.input.MouseEvent;

import javafx.scene.input.KeyEvent;

/**
 * @author Patrick
 */

public class SearchTextBox extends TextBox {

    public var onResetSearch:function() : Void;
    public var onSearch:function(s: String) : Void;
    override var style = "padding-right: 25 ";

    override var styleClass = "searchTextBox";

    override var onKeyTyped = function(event:KeyEvent){
        if (this.rawText!=""){
            onSearch(this.rawText);
        }
    }
   
    public override function create():Node {
        var t = super.create();
        var resetButton:Group;

        var g = Group {
            content: [
                t,
                resetButton = Group {

                  var crossWidth = bind this.layoutBounds.height * 0.45;
                  var crossHeight = bind this.layoutBounds.height * 0.05;

                  visible : bind this.rawText.length() > 0
                  layoutX: bind this.layoutBounds.width - (this.layoutBounds.height / 2.0)
                  layoutY: bind this.layoutBounds.height / 2.0

                  content: 
                  [
                    Circle {
                        fill: Color.GRAY
                        radius:  bind this.layoutBounds.height * 0.325 // 65% of the texbox height and div 2 for the radius
                    }
                    Rectangle {
                        width: bind crossWidth
                        height:bind crossHeight

                        translateX: bind 0 - crossWidth / 2.0
                        translateY: bind 0 - crossHeight / 2.0

                        fill : Color.WHITE
                        rotate: 45
                    }
                    Rectangle {
                        width: bind crossWidth
                        height:bind crossHeight

                        translateX: bind 0 - crossWidth / 2.0
                        translateY: bind 0 - crossHeight / 2.0

                        fill : Color.WHITE
                        rotate: -45
                    }
                 ]

                 onMouseClicked: function (event:MouseEvent ){
                     commit();
                     this.text="";
                     onResetSearch();
                 }

             }
           ]
       }
       
       return g;
   }
}


Main.fx
/*
 * Main.fx
 *
 * Created on 3 oct. 2009, 00:44:05
 */

package customcomponent;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.control.Button;

/**
 * @author Patrick
 */

Stage {
    title: "Application title"
    width: 250
    height: 200
    
    scene: Scene {
        content: [
            Text {
                font : Font {
                    size : 16
                }
                x: 10
                y: 30
                content: "Search "
            }
            SearchTextBox {
                    translateX :10
                    translateY :40
                    

                    onResetSearch:function(){
                        println("reset !");
                    }
                    onSearch:function(s: String){
                        println("Search of : {s}");
                    }
            }
            Button {
                    text: "just a button to change focus"
                    translateX :10
                    translateY :80
                    action: function() {
                        println("Hello !")
                   }
            }
        ]
    }
}