Cannot open file (/var/www/vhosts/java-hair.com/httpdocs/wp-content/backup/.htaccess)Cannot write to file (/var/www/vhosts/java-hair.com/httpdocs/wp-content/backup/.htaccess) JavaFX Flashcard Example Updated for 1.1 | Java Hair

JavaFX Flashcard Example Updated for 1.1

I have updated the sourcecode for my JavaFX flashcard game example to be compatible with release 1.1.  There certainly were a lot of changes from the pre-release to the release and this serverely impacted the example code.  So severely, in fact, that it was just chock full of compile erros and other issues.  I will attempt to cover most of the changes by explaining the resulting new classes.

The actual structure of the program hasn’t changed, The FlashcardApp is the main program, it builds an array of Flashcard objects.  Each Flashcard object is made up of a Word and a CardImage.  The Word is then made up of individual letters.

Let’s start by taking a look at the Letter.fx file.  This Letter.fx is a little better designed than the last one.  In this case, instead of extending the generic CustomNode I extended Text.  After doing that I was able to just override the variables I was interested in. I could set the alignment, font, color and relative position this way. Another change that had to be made was to drop using attribute and use var instead.

I stored the actual letter as a String because I wanted the option of tying two characters together to make one sound (called bends (”cl” or “st”) or diagraphs (”sh” or “ch”)).

The letter is class is repsonsible for displaying the letters and thus needs to know where to position them, therefore the size and position numbers are provided so it can determine where in the canvas to put the letters.

public class Letter extends Text {
    public var myLetter: String; //String the represents a Letter in the Card
    public var position: Number; //Position the letter is in in the current word
    public var size: Number; //Size of the entire word
    override var textAlignment = TextAlignment.CENTER;
    override var textOrigin = TextOrigin.TOP;
    override var translateX = bind ((scene.width - 40) - (((scene.width-40)/size) * (size+1 - position)));
    override var translateY = bind (scene.height - scene.height) / 2 ;
    override var font = Font{ name: 'Arial', size: 150 };
    override var fill = Color.BLACK;
    override var content = bind myLetter;

}

The Word.fx file did not change too much except to extend CustomNode and override the translateX and translateY variables to position the word correctly.

It contains an operation to flip the card, one to show the Word (to reset the state), and a constructor. The interesting part here is the “constructor”. As I mentioned in a previous post, there is no real constructor per say, instead you define a method with the same name as the class and this is used as a constructor.

public class Word extends CustomNode {
    var letters: Letter[];
    var show:Boolean = true;
    override var translateX = bind (scene.width - 40 - boundsInLocal.width) / 2 ;
    override var translateY = bind (300 - boundsInLocal.height)/2 - 20 ;

    public var word: String = null on replace {
       var aSize = word.length();
       var i = 0;
       while (i < aSize) {
            var nLetter = Letter { myLetter:word.substring(i,i+1) position:i+1 size:aSize};
            insert nLetter into letters;
            i++;
       }
    }

    public function flip() {
        show = not show;
    }

    public function showWord() {
        show = true;
    }

    public override function create(): Node {
        return Group {
            visible: bind show
            content: [
                letters
            ]
        };
    }
}

The CardImage file is similar in the changes there. I also made use of fitWidth and fitHeight to make all my images consistent sizes in the ImageView.

The show boolean is used in the CardImage class and the Word class to indicate whether or not it should be visible. This is what allows the flip() function to work in FlashCardApp by just setting one to true and the other to false.

public class CardImage extends CustomNode {
    override var translateX = bind (scene.width - 40 - boundsInLocal.width) / 2 ;
    var show: Boolean = false;

    public var imageSrc: String = null on replace {
        show = false;
    }

    public function flip() {
        show = not show;
    }

    public function hideImage() {
        show = false;
    }

    public function CreateCardImage(anImage:String) : CardImage {
        var cardImage1 = CardImage { imageSrc: anImage
        }
        return cardImage1;
    }

    public override function create():Node {
        var cardImage = Image {
            url: imageSrc
        }
        return ImageView {
            translateY: 25
            fitWidth: 500
            fitHeight: 250
            visible: bind show
            image: cardImage
        }

    };

}

Nothing too exciting in the FlashCard.fx file either, but I’ll include here for the sake of completeness. Note the flip function here as mentioned above. Also, this is the class where the sound integration is done. It isn’t as much sound as I originally intended as it was originally meant to be able to sound out individual letters or letter groups. I don’t think that would be too difficult to implement but I haven’t done it yet and probably won’t since my children have outgrown this little game already.

public class FlashCard extends CustomNode {
    public var cardImage: CardImage;
    public var showFront: Boolean;
    public var cardWord: Word;
    public var mp3: Mp3;

    public var aWord:String = null on replace {
       cardWord = Word{ word:aWord };
    }

    public var anImage:String = null on replace {
        cardImage = CardImage{imageSrc:anImage};
    }

    public var aMp3:String = null on replace {
        mp3 = new Mp3(aMp3);
    }

    public function showWord() {
        cardWord.showWord();
        cardImage.hideImage();
    }

    public function flip() {
        cardWord.flip();
        cardImage.flip();
        mp3.play();
    }

    public override function create():Node {
        return Group{
            content: [
            Rectangle {
                x: 10
                y: 10
                height: 300
                width: 550
                arcHeight: 20
                arcWidth: 20
                fill: Color.WHITE
                stroke: Color.BLACK
                strokeWidth: 2
            }
            ,
                Group {
                    content: [ cardWord,
                            cardImage ]
                }
            ]
        };
    }

}

FlashCardApp.fx had a couple of changes and some things of interest. First of all, instead of using a Frame, it uses a Stage component, as the Frame no longer exists. Inside the VBox I had to put the content inside a Group in order for the displayed FlashCard to be updated when the index changed. Essentially I needed to bind the “card” variable and I could not do that without it being inside a Group component.

The last thing I had to change was to remove a slash from the pointers to the images and mp3’s. The old insert statement looked like this:
insert FlashCard{aWord:”cat”, anImage:”{__DIR__}/img/cat.png”, aMp3:”{__DIR__}/sounds/cat.mp3″} into flashcards;

Note the “/” after the {__DIR__} in both instances. I had to remove that slash so that it now looks like:
insert FlashCard{aWord:”cat”, anImage:”{__DIR__}img/cat.png”, aMp3:”{__DIR__}sounds/cat.mp3″} into flashcards;

At first I thought this might have been because i was developing this new version on Linux, but it appears that it is necessary for Windows also. It appears the {__DIR__} includes a slash at the end of the directory and having 2 was a problem for the classes.

var flashcards:FlashCard[];
var myIndex:Integer = 0;
var size:Number = 5;
var card = bind flashcards[myIndex];
insert FlashCard{aWord:"cat", anImage:"{__DIR__}img/cat.png", aMp3:"{__DIR__}sounds/cat.mp3"} into flashcards;
insert FlashCard{aWord:"dog", anImage:"{__DIR__}img/dog.png", aMp3:"{__DIR__}sounds/dog.mp3"} into flashcards;
insert FlashCard{aWord:"car", anImage:"{__DIR__}img/car.png", aMp3:"{__DIR__}sounds/car.mp3"} into flashcards;
insert FlashCard{aWord:"hat", anImage:"{__DIR__}img/hat.png", aMp3:"{__DIR__}sounds/hat.mp3"} into flashcards;
insert FlashCard{aWord:"fish", anImage:"{__DIR__}img/fish.png", aMp3:"{__DIR__}sounds/fish.mp3"} into flashcards;

Stage {
    title: "Flash Card JavaFX"
    width: 600
    height: 400
    scene: Scene {
    fill: Color.GREY
    content: VBox {
        content: [
            Group { content: bind card },
            HBox {
                content: [
                    SwingButton {
                        translateX:0
                        translateY:10
                        text: "Next"
                        action: function() {
                            flashcards[myIndex].showWord();
                            if (myIndex < (size - 1)) {
                                myIndex++;
                            } else {
                                myIndex = 0;
                            }
                        }
                    },
                    SwingButton {
                        translateX:20
                        translateY:10
                        text: "Flip Me!"
                        action: function() {
                            flashcards[myIndex].flip();
                        }
                    }
                ]
            }

        ],
        }
    }

You can download all of the new sourcecode here. You will need the JLayer library for the Mp3 class to compile.

Be sure to check out the other articles on my blog related to JavaFX and the Flashcard game for more details on the Flashcard JavaFX code itself.

Stephin Chin has a good post about some of the changes from the pre-release to the release.

Share/Save/Bookmark

Related posts:

  1. Adding Sound to the FlashCard JavaFX Game I finally had a small amount of time to look...
  2. JavaFX Example - FlashCard Game Note: An updated version of the source code for JavaFX...
  3. JavaFX FlashCard Source Code and Web Start Link This is the post I promised that contains a link...
  4. Create and Deploy a JavaFX WebStart Application I realized when I updated my FlashCard JFX game that...
  5. Learning JavaFX This is my week off.  I had a nice little...

1 comment

  1. JavaFX Example - FlashCard Game | Java Hair

Leave a reply

You must be logged in to post a comment.