Escolar Documentos
Profissional Documentos
Cultura Documentos
pdfcrowd.com
pdfcrowd.com
Preface
The book "Java for Kids" was written by Yakov Fain, Java Champion. The
goal is to help students learn to program in the most popular language in the
world: Java. This book starts from an introduction to Java and then explains
how to write programs that have Graphic User Interface by writing the TicTac-Toe and Ping-Pong games.
The "Java for Kids" book can be used in multiple ways:
1. Teenagers can use it to teach themselves
2. Parents can use this book for teaching their kids Java
3. School teachers can use it as a text book in introductory classes on
programming
4. University professors can use it as a supplement to their "Computer
pdfcrowd.com
teach you how to publish your code on the Web on a super popular site called
GitHub. Millions of programmers share their programs there and you should
too.
Yuri Fain produced illustrations for this book. If this material seems too easy
for you get the second edition of my book for adults "Java 24-Hour Trainer" or
a video course "Introduction to Java and Java EE".
The online version of this book is offered for free under Creative Commons
license, but the author would appreciate a donation if you find this book useful.
After making a donation, youll be entitled to receive the PDF version of the
book as well as in MOBI (for Kindle) and EPUB (for iBook) formats.
Join the Internet group where readers can post their questions and comments
regarding the content of this book.
If you find an error in the code samples email your comments directly to me at
yakovfain@gmail.com or open an issue at code samples repository on GitHub.
All rights reserved. Yakov Fain 2015.
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
Java can be embedded in tiny microchips that control various home appliances
or industrial devices like the ones that power smart homes where the heat or
light can be programmed remotely from your phone. These Internet-connected
things can be programmed in Java.
Programming languages can have some general characteristics and we say that
Java is an object-oriented language. Its program elements (classes) represent
objects from the real world. For example, you can create a class called Car
and give it attributes that real cars have, like doors, wheels, and so on. Next,
you can create another class based on the Car class, like Tesla , with all the
features of the Car class (doors, wheels) plus an electric motor.
And the software required to write Java is free. With so many million of
professional Java programmers in the world, youll find lots of sample program
online so if youre run into a problem, you can either find the solution by
searching or ask in one of the popular online forums like Stack Overflow, and
someone will probably answer your question!
But enough talk. Lets start learning Java.
pdfcrowd.com
To start programming in Java you need to download the Java Development Kit
(JDK) from the company called Oracle, which makes releases and updates of
Java versions. The full name of the software to download is Java SE
Development Kit. Well download the Java SE 8, which was the latest version
of Java available while writing this book. Just visitOracles Web site. Accept
the license agreement and select the proper link depending on the Operational
System (OS) installed on your computer.
While Java programmers need JDK installed, the users of
NOTE
pdfcrowd.com
pdfcrowd.com
Environment Variables. Youll see all system variables that exist in your OS As
shown on the screenshot Windows OS - System Variables. If you have
administrators rights onto your Windows PC, you can set user variables that
will apply only when a certain user logs into your PC, or system variables that
will apply to all users.
pdfcrowd.com
Press the lower button Edit and add the bin directory from your JDK at the
beginning of the Path variable value. For example, add c:\Program
Files\java\jdk1.8.0\bin; if this is where your JDK is installed:
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
For example, if you want to write a program called HelloWorld , enter its
open in browser PRO version
pdfcrowd.com
code in a text editor.Here is the program that prints the words Hello World! on
your computers screen:
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello World!");
}
}
Save the above code with the name HelloWorld.java in the folder practice.
Keep in mind that you are not allowed to use blank spaces in Java file names.
Ill explain how and why this program works a little later in this chapter. For
now, if you followed each step correctly, the program will print the words
Hello World on the screen that we will go over in step 3.
Programmers often use the words the source code to refer to a program. So its
safe to say the we wrote the source code of the program Hello World. Unless
youre an experienced Java programmer, you cant just assume that this
program is written correctly. Lets proceed to Step 2 to find out.
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
Change the directory to practice with the command cd practice. If you have
never used the command cd before, read the online instructions on how to do it
on Windows or on Mac OS. Now compile the program using the following
command:
javac HelloWorld.java
You wont see any confirmation message that your program HelloWorld
has been compiled successfully. Having no messages means there no problems
occurred during compilation. Type a command dir on Windows or ls on Mac
and youll see the list of files in folder practice. This is how it looks in my
Terminal window:
pdfcrowd.com
First, Ive entered the pwd command to make sure Im in the practice folder.
You should see a new file named HelloWorld.class . This proves that
your program has been successfully compiled. Your original file
HelloWorld.java can also be found there, and you can modify this file
pdfcrowd.com
time youve used the program java and not javac? This is how you start JRE
by providing it the name of the application to run ( HelloWorld in this
case).
Keep in mind that Java does not treat capital and small letters the same, which
means that if you originally named the program HelloWorld with a capital
H and a capital W , do not try to start the program helloworld or
helloWorld the JRE will signal an error. The file name should match the
class name as well. Typically, each file of your application contains the code of
one class.
Now lets have some fun trying to guess how to modify the code of the
program that prints Hello World. Ill explain how this program works in the
next chapter, but for now attempt to guess what has to be done to say hello to
open in browser PRO version
pdfcrowd.com
your pet, friend or print your address. Go through all three steps to see if the
program still works after your changes. If you dont have a pet, you can
always say hello to my puppy - his name is Sammy. Are you up for the
challenge to write a program that prints Hello Sammy! on the screen?
pdfcrowd.com
pdfcrowd.com
In the next chapter youll learn how to write, compile and run your programs
in a more convenient environment than just a text editor and a Command
window.:toc-placement!::imagesdir: .
pdfcrowd.com
(lets just call it IDEA). Then well create a project called Hello . Youll see
that creating the Hello World application is a lot easier inside IDEA.
pdfcrowd.com
On Windows, youll need to select the folder where IDEA will be install as
shown below. Windows installer will also offer to create a desktop icon for
IDEA - agree with this.
open in browser PRO version
pdfcrowd.com
In several seconds youll get the IDEA installed by clicking on the Next button.
If you use MAC OS, find it using Spotlight on the top right corner of the
screen and click on it. If you use Windows, click on the newly created IDEA
icon on your desktop. The first question IDEA asks is if you want to import
open in browser PRO version
pdfcrowd.com
the settings from the older versions of IDEA. Do not select this. Next comes
this Welcome screen:
pdfcrowd.com
pdfcrowd.com
Select the option to create a Java project. In IDEA projects consist of modules.
open in browser PRO version
pdfcrowd.com
By selecting Java we state that our project will have a Java module. Hit the
button Next and then again on the following window that will ask about
selecting a template that will be used in this project. Now we need to give our
project a name and select the JDK to be used with this project.
We dont want our project to be untitled, so replace this name with hello in the
top box. Note how the name of the folder in the Project location box changes
accordingly. When youll try to do it on your computer, the project location
will appear different than mine. Now you need to select the JDK. If you have
never worked with Java before, the only JDK you will have is the one installed
in Chapter 1 although Java programmers sometimes have more than one JDK
installed. For example, they may not be allowed to use the latest JDK 8 for
work projects, so they keep the JDK 7 around, but all the fun projects will be
created with JDK 8.
We dont have such restrictions, so JDK 8 is our only choice. Now figure out
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
Press the button Finish and your new project is created. Every time you start
open in browser PRO version
pdfcrowd.com
IDEA it offers you little tips on how to use its cool features. You can opt out
from this, but I recommend you read them - you might find some little gems
that will make your work with IDEA more fun. The project hello is ready, and
you can start writing your Hello World program.
This project consists of the module hello and External Libraries. The source
code of your program(s) will be located in the folder src in the hello module.
The file hello.iml is where IDEA remembers the settings of the project hello you dont need to touch it. Under External Libraries youll find a bunch of files
open in browser PRO version
pdfcrowd.com
that end in .jar. These JARs are the libraries of code that came with JDK.
A simple project like our HelloWorld will have just one file with the
source code HelloWorld.java. More advanced projects will consist of multiple
files. To simplify the application deployment, all these files could be packaged
in one or more JARs too. Both JRE and Java SDK include dozens of JARs.
Java comes with a jar utility that is used to archive multiple Java classes and
other files into a file having the name extension .jar. Internal formats of .jar and
.zip files are the same. If your IDEA project will have multiple classes, you can
package them into one JAR by using the menu File | Project Structure |
Artifacts and then selecting the type JAR.
pdfcrowd.com
pdfcrowd.com
project, and then select the menu File | New | Java Class. Youll see a little
popup window asking for a class name. Enter the name HelloWorld there.
pdfcrowd.com
The text between /** and */ is one of the ways to write comments in your
programs. This is an area where you can type any text you want that describes
your program in general or any particular code inside the class. Well talk
about various ways to write comments in the next chapter.
You can certainly type the above declaration, and IDEA will obediently start
open in browser PRO version
pdfcrowd.com
helping as you start typing. For example, I started typing the word public ,
and after entering the pu IDEA suggested the following selection of
keywords that are appropriate in the current location inside the class.
Pressing the button Tab on the keyboard will turn pu into public . You can
also press the keys Control-Space to see suggested code completion at any
time. But there is an even faster way to enter the declaration of the main
method. Just type in the first letters of these keywords psvm , and press the
open in browser PRO version
pdfcrowd.com
Tab key. IDEA will unfold these letters into the following:
public static void main(String[] args) {
}
Great job, IDEA! Such code completion minimizes typing and the number of
typos you could make. At the end of this chapter in the section Additional
Reading youll find the link to a Web page showing more advanced features of
code completion in IDEA. It may be a little early for you to understand
everything thats explained there, but bookmark a link to this page for future
reference.
To become a real pro in IDEA, you should use the hotkeys,
which are combinations of key-presses on the keyboard. With
TIP
Now we have the class HelloWorld with an empty method main . The
word method means action. To run a Java class as a program, this class must
open in browser PRO version
pdfcrowd.com
have a method called main . Usually your applications will have many
classes, but only one of them will have the method main . This class becomes
the entry point in your application.
To complete our program, place the cursor after the curly brace in the line with
main , push the button Enter and type the following on the new line:
System.out.println("Hello World!");
After learning about the psvm shortcut you may be wondering, is there a way
to do a similar trick with System.out.println() . Just type in sout
and press the Tab key. Voila! The sout magically turns into
System.out.println(); . Java programmers often use printing to the
compiler found the error, the line is marked with the red mark on the right, and
if youll hover the mouse pointer over this little red rectangle, youll see the
open in browser PRO version
pdfcrowd.com
error message:
As your project becomes larger, itll have several files and the compiler may
catch more than one error. Can you see a list of errors from all classes? By
default, IDEA doesnt compile all the classes from your project, but you can
request compiling of the entire project every time you make a change or save
the source code. Go to the IDEA menu Preferences (or Settings), select
Compiler and check off the option Make project automatically. Now select the
open in browser PRO version
pdfcrowd.com
menu View | Tool Windows | Problems to see all the problems in one list:
In our case we only have one compiler error. Java reached the end of the file
while parsing (trying to understand your code), and something could not be
found - the curly brace, of course. But what does this mysterious (8,6) mean?
The error was found in the line number 8 around the sixth character from the
left. To see line numbers, right-click on the gray vertical bar to the left of the
code editor and select the option Show Line Numbers. Now its easier to map
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
tested, does what it supposed to do (e.g. print Hello World), and if you want to
give it to your friends youll need to give only compiled .class files. They
dont need source code of your program, but they do need the JRE (not JDK)
installed on their computer.
Java programmers can run their programs not only from a command window
demonstrated in Chapter 1, but right from the IDE. Just right-click on the name
HelloWorld in the Project view and select the menu item Run
HelloWorld.main(). The program will run and youll see the results in the
Console View right inside IDEA:
pdfcrowd.com
pdfcrowd.com
the method main could be accessed by any other Java class or the JRE
itself.
This method is static . The keyword static means that you dont
have to create an instance of the HelloWorld object in memory to use
this method. Well talk about classes and object instances in the next
chapter.
Does the method main return any data? Say, if youll write a method to
add two numbers, it can return a result. The keyword void means that the
method main doesnt return any data to whomever calls it (JRE in this
case).
The method name main goes right before parentheses.
Some methods have parameters (a.k.a. arguments), which go inside the
parentheses. Its the data that could be given to the method from another
place of the program that invokes this method. The method main has
parameters - and an array of text values String[] args . Youll learn
how to use the parameters of the method main in Chapter 9 in the section
Command Line Arguments.
A Java program can consist of several classes, and each class may include
methods. Usually, a Java class has several methods. For example, a class
open in browser PRO version
pdfcrowd.com
so on. But only one class in the application will have the method main .
The body of our method main has only only one statement:
System.out.println("Hello World!");
Every statement or a method call must end with a semicolon. The method
println knows how to print data on the system console (command
window). Java method names are always followed by parentheses. If you see a
method with empty parentheses, this means that this method does not have any
arguments and doesnt expect to receive any data. The above method
println has one argument - a String with the value Hello World! .
System.out means that the variable out is defined inside the class
System that comes with Java. How are you supposed to know that theres
something called out in the class System ? IDEA will help you with this.
After you type the word System and a dot, IDEA will show you everything
that is available in this class. You can also put a cursor after the dot and press
Ctrl-Space at any time to bring up a help box similar to this one:
pdfcrowd.com
Figure 23. Peeking inside the System class with code completion
This tells me that the Java class System has a variable out of type
PrintStream . Are you curious as to what PrintStream is? Click on
out in your code and select the menu View | Quick Documentation to read
the dry documentation. The fact that a period goes after out followed by a
method name - out.println() - tells us that out represents an object,
which apparently has a method called println() .
We call it a dot notation. We write class_name.method_name or
variable_name.method_name. Say you have a class PingPongGame that has
open in browser PRO version
pdfcrowd.com
In this example, the arguments may be given to the method for some kind of
processing like saving the score on the disk. Since the name Dave was placed
in parentheses, we can guess that the first argument has a String type,
which is used for text. The second argument is clearly of a numeric type but
we can tell whats the exact type only after reading the declaration of the
method saveScore inside the source code of the class PingPongGame .
In the next chapter well spend a lot more time seeing what Java classes consist
of.:toc-placement!::imagesdir: .
pdfcrowd.com
In the real world you see and use various objects, and each of them is belongs
to some kind such as toys, food, animals, electronics et al. In Java, instead of
saying what kind of objects, we say what class of objects. In other words, each
object belongs to a class. A class is like a blueprint of an object. In this chapter
youll get familiar with classes - the main constructs of the Java language.
Any program that youll write will have at least one class. Youll learn how to
declare a class and how to create one or more objects based on the class
declaration. Youll also learn about a classs internals what a class can consist
of. Finally, Ill show you how to create a class that inherits features of another
class.
Java defines a number of data types. Some of them are simple, like int ,
which represents integer numbers. Some of them are more complex - they are
called classes, like System , which can be used for things like printing text
on the screen, exiting a program, or cleaning a computers memory.
When you installed Java on your computer, you installed thousands of Java
classes. Your Java programs will also consist of classes that can represent
objects from the real world. If a class is a data type, an object is a
representative of a specific type. For instance, you can see ten dogs on the
street, and they all represent the class Dog .
open in browser PRO version
pdfcrowd.com
3.1.1. Classes
Lets see what Java classes can consist of. A very simple class can have
nothing inside. Take a look at this class declaration:
class VideoGame {
}
This class is empty. It knows nothing and cant do anything because there is no
open in browser PRO version
pdfcrowd.com
code between the curly braces. From the Java syntax perspective, this class is
legitimate and compiler wont complain. There is a valid keyword class
followed by its name VideoGame . The opening curly brace has the matching
closing one. We need classes that can do stuff. We can place methods and
attributes inside the class.
Methods define actions that a class can perform.
Attributes describe various properties of a class.
A method consists of a callable code fragment, that can be called (and
executed) by name from another part of the program. For example, a class can
have a method named saveScore that contains a dozen of lines of code to
save the game score. Lets add some methods and attributes to the class
VideoGame . This class may have several methods, which can tell what an
object of this class can do: start the game, stop it, save the score, ask for
additional lives on Facebook, and so on. This class also may have some
attributes (a.k.a. fields): color, price and others. An object that represents the
class VideoGame can look like this:
class VideoGame {
pdfcrowd.com
String color;
int price;
void start () {
// The code to start the game goes here
}
void stop () {
// The code to stop the game goes here
}
void saveScore(String playerName, int score) {
// The code to save score goes here
}
}
This class has two attributes color and price . The color attribute has the
String data type, which is used for storing any text. The price attribute
is of an int type, which is used for storing integer numbers. The class
VideoGame has three methods: start , stop , and saveScore . These
are the actions that our video game should perform. Each of these method
declarations start with a keyword void , which means that these methods do
not return a value to the caller of the method. In the next chapter Ill show you
a class Fish , which will include a method dive that returns a value.
open in browser PRO version
pdfcrowd.com
At this point each of these methods has just a single line that starts with two
slashes //.
If a line starts with two slashes, it contains a single line
comment - just the description of a code fragment. If you
NOTE
Our class VideoGame can be used as a starting building block for pretty
much any video game all game consoles have the color attribute, all of them
allow to save score, and all of them have price tags.
pdfcrowd.com
pdfcrowd.com
properties that are specific to the model Play Station 4, for example sharing on
Facebook and Twitter. So among other things, the class PlayStation4 will
have methods shareOnFacebook and shareOnTwitter .
class PlayStation4{
int hardDiskSize;
// Some other attributes and methods go here
void shareOnFacebook(){
// Code to share on Facebook go here
}
void shareOnTwitter(){
// Code to share on Twitter go here
}
}
3.1.2. Objects
open in browser PRO version
pdfcrowd.com
Well often use the phrase create an instance of an object, which means to
create an object in a computers memory based on some class declaration. If a
game factory will produce ten thousand games, a programmer can say that they
created ten thousand instances of the class PlayStation4 .
The factory description of PlayStation4 relates to an actual game the
same way as a Java class relates to its instance in memory. The process of
building actual games based on this description in the game factory is similar
to the process of creating instances of PlayStation4 objects in Java. For
example, the next code sample creates one instance of the class
PlayStation4 and calls its method shareOnFacebook .
public class CreatePlayStation4Objects {
public static void main(String[] args) {
// create one instance of PlayStation4 class
PlayStation4 firstPlayStation = new PlayStation4();
// call the method shareOnFacebook
firstPlayStation.shareOnFacebook();
}
}
open in browser PRO version
pdfcrowd.com
In many cases, a program can use a Java class only after creating the instance
of an object. The same with manufacturers - they create thousands of game
copies based on the same description. Even though these copies represent the
same class, they may have different values in their attributes - some of them
are black while others can be silver. Some of them have 500GB hard disk dive
while some are upgraded to 1TB.
pdfcrowd.com
attribute.
pdfcrowd.com
If the size of the hard disk is 500GB, we can assign this value to the variable
hardDiskSize as follows:
open in browser PRO version
pdfcrowd.com
hardDiskSize="500GB";
String values are placed inside the quotes, and the numbers arent.
The method parameters (a.k.a. arguments) are also stored in variables. The
method saveStore has two arguments: playerName of type String
and score of type int :
void saveScore(String playerName, int score)
3.2.1. Primitives
Simple Java data types are called primitives. Their keywords are written in
small letters (e.g. int , long , char , boolean ). So the score is of a
primitive data type, while the playerName is not. In Java you have to
declare the type and the name of a variable first and then use it.
Remember algebra equations like y=x+2 ? In Java youd need to start with
declaring the variables x and y of some numeric data type like int ,
float or double :
pdfcrowd.com
int x;
int y;
Now you can use the variables. The next two lines show how you can assign
them values. If your program assigns the value of five to the variable x , after
evaluating x+2 the variable y will be equal to seven:
x=5;
y=x+2;
In Java you are also allowed to change the value of a variable in a somewhat
unusual way. The following two lines change the value of the variable y from
five to six:
int y=5;
y++;
Despite the two plus signs, JVM is still going to increment the value of the
variable y by one. The y++ means read the value of the variable y ,
increment it by one, and assign it back to y . The longer syntax to achieve the
same result would be y=y+1 . After the next code fragment, the value of the
open in browser PRO version
pdfcrowd.com
You can also use multiplication, division and subtraction the same way. Look at
the following piece of code:
int myScore=10;
myScore--;
myScore=myScore*2;
myScore=myScore/3;
System.out.println("My score is " + myScore);
What do you think this code prints? IntelliJ IDEA has a useful tool called
Groovy Console (its under the Tools menu). It allows you to test any code
snippet (like the one above) without even creating a class or methods. If youll
copy the above code fragment into Groovy Console and hit the green button
play, you see that the value of the variable myScore is 6.
open in browser PRO version
pdfcrowd.com
click
My score is 6
In this example the argument of the method println was constructed from
two pieces the text My score is and the value of the variable myScore .
Putting two or more strings together is called concatenation. Even though
myScore is a number, Java is smart enough to convert this variable into a
String and then attach it to the text "My Score is ".
open in browser PRO version
pdfcrowd.com
//
//
//
//
it's
it's
it's
it's
the
the
the
the
same
same
same
same
as
as
as
as
`myScore*=2;
`myScore+=2;
`myScore-=2;
`myScore/=2;
There are eight primitive data types in Java, and you have to decide which
ones to use depending on the type and size of data you are planning to store in
your variables. These are Java primitives:
Four data types for storing integer values byte , short , int , and
long .
Two data types for values with a decimal point float and double .
One data type for storing a single character values char .
One logical data type boolean that allows only two values: true or
false .
You can assign an initial value to a variable during its declaration, and this is
called variable initialization, for example:
open in browser PRO version
pdfcrowd.com
In the last two lines the values have letters at the end. The f is for float
and l means long.
If you declare, but wont initialize primitive variables, Java will do it for you
by assigning zero to each numeric variable, false to boolean variables,
and a special code \u0000 to variables of type char .
pdfcrowd.com
used to store only one character, Java also has a class String for working
with a longer text, for example:
String lastName="Smith";
If you declare your own class, consider it a new data type. You can start
declaring variables of this type, for example, you can declare the variable
named myFirstGame of type VideoGame :
VideoGame myFirstGame
Java programmers have agreed to name variables starting with small letters. To
make the variable name more meaningful, it can consist of several words, and
each word starts with the capital letter as in myFirstGame . Youre also
allowed to start variable names with the dollar sign like $myMoney or
underscore: _myBestFriend . Variable names cannot contain spaces.
Java also has a special keyword final , and if its used in a declaration of a
variable, it means that you can assign a value to this variable only once, and
this value cannot be changed afterwards. In Java we usually name final
variables using capital letters:
pdfcrowd.com
pdfcrowd.com
actions in the methods of the class Pet . Well also give our pet the following
attributes: age, height, weight, and color.
Its time for hands-on work. Start IDEA IDE and create a new project as
explained in Chapter 2. This time name it MyPet instead of Hello . Click
on the src folder in IDEA and create a Java class called Pet using the menu
File | New | Java Class.
Your screen should look similar to this one:
Now we are ready to declare attributes and methods in the class Pet . Java
classes and methods enclose their bodies in curly braces.
To declare variables for class attributes we should pick data types for them. I
suggest an int type for the age, float for weight and height, and
open in browser PRO version
pdfcrowd.com
The next step is to add some methods to this class. Before declaring a method
you should decide if it should take any arguments and should return a value.
This is what I suggest:
The method sleep will just print a message Good night, see you
tomorrow it does not need any arguments and will not return any value.
The same is true for the method eat .It will print the message Im so
hungry, let me have a snack like nachos!.
The method talk will not be printing any messages, but will prepare a
message based on the word or a phrase passed to this method as an
argument. This method will build a phrase using the argument and will
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
This class represents these friendly little monsters from the "real world":
Lets talk now about the signatures of each method in detail starting with the
open in browser PRO version
pdfcrowd.com
method sleep :
public void sleep()
This method signature tells us that sleep can be called from any other Java
class ( because its public ). This method does not return any data (the
keyword void ). The empty parentheses mean that this method does not take
any arguments - it does not need any data from the outside world to print the
same text.
The signature of the method eat is similar to sleep .
The signature of the method talk looks like this:
public String talk(String aWord)
This method can also be called from any other Java class, but has to return
some text, which is prescribed by the keyword String in front of the
method name. Besides, it expects some text data from outside, hence the
argument String aWord .
pdfcrowd.com
pdfcrowd.com
Pet didnt have one). Remember from Chapter 2, typing psvm followed by
the Tab key will quickly create the method main . Well place the code
communicating with the class Pet inside the method main .
NOTE
(1)
(2)
myPet.eat();
(3)
(5)
(6)
}
}
open in browser PRO version
pdfcrowd.com
1. The variable petReaction will store the value returned by the method
say .
2. This is how to create an instance of the object Pet using the Java
operator new . This line declares a variable of type Pet - thats right, you
can treat any classes created by you as new Java data types.
3. Calling the method eat on the object Pet . After the instance of Pet
was created, the variable myPet knows its address in memory. So you
can call the method eat (as well as any other) on this particular instance
of Pet .
4. If a method returns a value, specify a variable that will store returned value
to the left of the equal sign. In our code its petReaction of type
String . Such variable should have the same type as the return value of
the method.
5. The value of the variable petReaction is passed as an argument to the
To run the class PetMaster right-click on its name in the Project view in
open in browser PRO version
pdfcrowd.com
IDEA, and select the option Run PetMaster.main(). This program will output
the following:
Im so hungry,let me have a snack like nachos!OK!! OK!! Tweet!! Tweet!!Good
night, see you tomorrow!
pdfcrowd.com
At this point the project MyPet consists of two Java classes: Pet and
PetMaster . The role of the class Pet is to represent attributes and
behavior of a pet, while the class PetMaster starts the program, instantiates
the class Pet and calls its methods. Your typical projects will consist of
multiple Java classes, but only one of them will have have the main method,
which is the entry point of the application.
pdfcrowd.com
Java has a special keyword extends that will do the trick. Create a new
class Fish in IDEA and then add to its declaration extends Pet so itll
look as follows:
class Fish extends Pet{
}
This class Fish is a subclass of the class Pet . Accordingly, the class Pet
is a superclass of the class Fish . In other words, you use the class Pet as a
template for creating a class Fish . The keyword extends defines
relationship between classes. Since our Fish extends a Pet , we can say that
a fish is a pet. But we cant say that a pet is a fish.
Even if you will leave the class Fish empty as it is now, you can still use
every method and attribute inherited from the class Pet , because a fish is a
pet! Take a look, were creating an instance of the object Fish and are
calling its method sleep :
Fish myLittleFish = new Fish();
myLittleFish.sleep();
open in browser PRO version
pdfcrowd.com
myLittleFish.sleep();
Even though we have not declared any methods in the class Fish yet, we call
(invoke) the method sleep , which was declared in its superclass Pet ! In
Java all classes are automatically inherited from the class Object . Even
though weve declared the class Pet without using the keyword extends it
still extends the class Object . With the keyword extends you can build
class hierarchies. For example, many animal classes can extend the class Pet .
pdfcrowd.com
Lets not forget, however, that weve created the class Fish as a subclass of
Pet , because we wanted to add some additional features that only fish have
and reuse some of the code that we wrote for a general pet.For instance, not all
pets can dive, but fish certainly can. Lets add a new method dive to the
open in browser PRO version
pdfcrowd.com
class Fish .
public class Fish extends Pet {
int currentDepth=0;
public int dive(int howDeep){
currentDepth=currentDepth + howDeep;
System.out.println("Diving for " +
howDeep + " feet");
System.out.println("I'm at " + currentDepth +
" feet below sea level");
return currentDepth;
}
}
The method dive has an argument (a.k.a. parameter) howDeep that tells
the fish how deep it should go. Weve also declared a class variable
currentDepth that will store and update the current depth every time you
call the method dive . This method returns the current value of the variable
currenDepth to the calling class. The plus sign in the pintln lines are
pdfcrowd.com
pieces.
Using IDEA, create another class named FishMaster that will look like
this:
public class FishMaster {
public static void main(String[] args) {
Fish myFish = new Fish();
myFish.dive(2);
myFish.dive(3);
myFish.sleep();
}
}
The method main instantiates the object Fish and calls its method dive
twice with different arguments - two and three. After that, it calls the method
sleep . When you run the program FishMaster , it will print the
following messages:
pdfcrowd.com
Have you noticed that beside the methods defined in the class Fish , the
FishMaster also calls method sleep from its superclass Pet ? This is
what inheritance is all about you do not have to copy and paste code from the
class Pet just use the keyword extends , and the class Fish can use
Pet s methods!
pdfcrowd.com
One more thing, even though the method dive returns the value of
currentDepth , our FishMaster does not use it. Thats fine, because
our class`FishMaster` does not use the returned value, but there may be some
other classes that will also use the class Fish , and they may find knowing
the current depth useful. For example, think of a class
FishTrafficDispatcher that has to know positions of other fish under
pdfcrowd.com
Now add the following three lines to the method main of the class
FishMaster (after creating the instance of the Fish ):
String fishReaction;
fishReaction = myFish.talk("Hello");
System.out.println(fishReaction);
This proves that Pet s method talk has been overridden, or in other
words, suppressed.
Wow! Weve learned a lot in this chapter lets just take a break.
pdfcrowd.com
prices?
2. Create a new project in IDEA named chapter3 and a new Java class Car
The method drive has one argument - the driving time. The method has
to return the total distance driven by the car for the specified time. Use the
following formula to calculate the distance: distance =
howlong*60; . Use the statement return distance as the last line
instance of the object Car and call its methods. The result of each method
call has to be printed using System.out.println() .
5. Create a subclass of Car named JamesBondCar and override the
method drive there. Now use the following formula to calculate the
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
You can add any text comments to your program to explain what a particular
line, method or class is for. First of all, someone else may read your program
so comments would help in understanding your intentions. Second, even the
author of the code cant remember every program he or she wrote. Besides, if a
professional programmer decides to change the employer, if would be nice to
leave well-commented code behind.
There are three different types of comments - single-line comments, block
comments, and a javadoc comments. Heres what they are for:
If your comment fits in one line, start it with two slashes:
// This method calculates the distance between A and B.
If you want to write multi-line comments, instead of starting each line with
two slashes, just surround the entire text with these symbols: /* and */ , for
example:
/* Now we'll handle the current
position of the Fish.
*/
open in browser PRO version
pdfcrowd.com
Java comes with a special program javadoc that can extract all comments
from your programs into a separate help file that can be displayed by any Web
browser. This file can be used as a technical documentation for your programs.
Such comments are enclosed in symbols /** and */ . Note the two asterisks
after the first slash. Only the most important comments like the description of a
class or a method should be placed between these symbols.
/** This method calculates the discount that depends
on the price paid. If the price is more than $100,
give the user 20% off, otherwise only 10%.
*/
The javadoc tool can process your code, extract all comments that start with
/** and create program documentation that can be published online or kept
locally on the company server. We are not going to use javadoc in this book,
but if youre interested in learning more about this tool, read Oracles tutorial
How to Write Doc Comments for the Javadoc Tool.
From now on, Ill be adding comments to code samples to give you a better
idea how and where to use them.
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
Lets modify the method dive() in the class Fish from Chapter 3 to make
sure that our fish is not allowed to dive below 100 feet:
public class Fish extends Pet {
int currentDepth=0;
public int dive(int howDeep){
currentDepth=currentDepth + howDeep;
if (currentDepth > 100){
System.out.println("I am a little fish and "
+ " can't dive below 100 feet");
currentDepth=currentDepth - howDeep;
}else{
System.out.println("Diving for " + howDeep +
" feet");
System.out.println("I'm at " + currentDepth +
" feet below the sea level");
}
return currentDepth;
}
public String talk(String something){
return "Don't you know that fish do not talk?";
}
open in browser PRO version
pdfcrowd.com
Now just make a small change in the class FishMaster let it try to make
our fish go deep under the sea:
public class FishMaster {
public static void main(String[] args) {
Fish myFish = new Fish();
// Try to have the fish go below 100 feet
myFish.dive(2); // go 2 feet down
myFish.dive(97); // go another 97 feet down
myFish.dive(3); // go 3 more feet down
myFish.sleep();
}
}
Run this program and itll print the following on the system console:
pdfcrowd.com
pdfcrowd.com
{
// do something
}
You can also rewrite this if statement using two vertical bars:
if (state.equals("Texas") || state.equals("California"))
{
// do something
}
The difference between these two examples is that if you use two bars, and the
first expression is true , the second expression wont even be checked. If
you place just a single bar, JVM will evaluate both expressions.
The logical and is represented by one or two ampersands ( && ) and each
expression in the parentheses must be true to make the entire expression
true . For example, charge the sales tax only if the state is New York and the
price is more than $110. Both conditions must be true at the same time:
if (state.equals("New York") && price >110)
{
open in browser PRO version
pdfcrowd.com
// do something
}
or
if (state.equals("New York") & price >110)
{
// do something
}
If you use double ampersand and the first expression is false , the second
one wont even be checked, because the entire expression will be false
anyway. With the single ampersand both expressions will be evaluated.
The logical not is also known as negation and is represented by the
exclamation point. The logical not changes expression to the opposite
meaning. For example, if you want to perform some actions only if the state is
not New York, use this syntax:
if (!state.equals("New York")) {
// do something
}
open in browser PRO version
pdfcrowd.com
The following two expressions will produce the same result, because more
than 50 and not less than or equal to 50 have the same meaning:
if (price > 50) {
// do something
}
if (!(price <= 50)) {
// do something
}
pdfcrowd.com
If the price is greater than fifty, the variable discount will get a value of 10,
otherwise discount will have a value of 5. Its just a shorter replacement of
the following if statement:
if (price > 50){
discount = 10;
} else {
discount = 5;
}
pdfcrowd.com
String studentName;
/**
The method convertGrades has one integer argument - the
result of the school test. The method returns one letter
A, B, C or D depending on the argument's value.
*/
public char convertGrades( int testResult){
char grade;
if (testResult >= 90){
grade = 'A';
} else if (testResult >= 80 && testResult < 90){
grade = 'B';
}else if (testResult >= 70 && testResult < 80){
grade = 'C';
}else {
grade = 'D';
}
return grade;
}
public static void main(String[] args){
ReportCard rc = new ReportCard();
open in browser PRO version
pdfcrowd.com
Beside using the else if condition, this example also shows you how to
use variables of type char . You can also see that with the && operator you
can check if a number falls into specific range. You can not just write if
testResult between 80 and 89, but with logical and you can check the condition
when testResult is greater than or equal to 80 and less then 89 at the
same time:
testResult >= 80 && testResult < 89
Take a guess as to why we could not use the logical or operator here? Say the
testResult is 100. Its greater than 80, and the above expression would
evaluate to true, because for the || operator having one true is enough to
open in browser PRO version
pdfcrowd.com
make the entire expression true. But this is not what we want - we need the
above expression to be true only if the value of testResult is between 80
and 89. The logical and operator does the job by ensuring that both conditions
are true.
pdfcrowd.com
System.out.println("Good Job!");
break;
case 'C':
System.out.println("Need to work more!");
break;
case 'D':
System.out.println("Change your attitude!");
break;
}
// Some other program code goes here
}
Say, the value of yourGrade is B . Then the above code will print "Good
Job!" and will break out of the switch statement to continue executing the
rest of the program code if any.
Do not forget to put the keyword break at the end of each case statement
to make the code jump out of the switch . For example, if you forget to put
the break in the case 'B' block, the above code would print "Good Job!"
followed by "You need to work more!".
pdfcrowd.com
pdfcrowd.com
variable is called local. This means that this variable is available only for the
code within this method. When the method is complete, this variable
automatically gets removed from memory.
Programmers use the word scope to say how long a variable will live, for
example you can say that variables declared inside a method have a local
scope. If a variable is declared within the code block surrounded with curly
braces (e.g. in the if statement), it has a block scope and wont be visible
outside of this block.
If a variable has to be reused by several method calls, or it has to be visible
from more than one method in a class, you should declare such a variable
outside of any method. In the class Fish from Chapter 3, the
currentDepth is a member variable. The member variable
currentDepth is alive until the instance of the object Fish exists in the
pdfcrowd.com
discuss shortly.
Member variables can be shared and reused by all methods of the class, and we
can make them visible from external classes too, if need be. For example the
method main of the class ReportCard includes the statement
System.out.println() . It uses the class variable out that was
When you start any Java program it loads the definition of the required classes
in memory. The definition of a class can be used for creation of one or more
instances of this class. For example:
ReportCard rc = new ReportCard();
rc1.studentName = "Jerry Lee";
ReportCard rc2 = new ReportCard();
rc2.studentName = "Sarah Smith";
open in browser PRO version
pdfcrowd.com
In this example we have two instances of the class ReportCard , and each
of them has its own value in the variable studentName , which is an
instance variable. Now, lets change the declaration of this variable by adding
the keyword static :
static String studentName;
In this case both instances of the ReportCard would share the same
variable studentName , and the above code would first assign "Jerry Lee" to
this variable, and then it would be replaced with "Sarah Smith". This doesnt
seem like a good idea does it?
Moreover, if the declaration of a member variable or a method starts with
static , you do not have to create an instance of this class to use such a
variable or a method. Static members of a class are used to store the values
that are the same for all instances of the class.
For example, the method convertGrades should be declared as static
in the class ReportCard , because its code does not use member variables to
store values specific to a particular instance of the class.
open in browser PRO version
pdfcrowd.com
Heres another example: Java has a class Math that contains several dozen
mathematical methods like sqrt , sin , abs and others. All these methods
are static and you do not need to create an instance of the class Math to
invoke them, for example:
double squareRoot = Math.sqrt(4.0);
pdfcrowd.com
Parentheses after the word Fish tell us that this class has some method called
Fish . Yes, there are special methods that are called constructors, and these
Any class can have more than one constructor. If you do not create a
constructor for the class, Java automatically creates one during the compilation
time - its so-called default no-argument constructor. Thats why Java compiler
has never complained about the statements new Fish() or new
ReportCard() , even though neither class Fish nor class ReportCard
pdfcrowd.com
constructor that just assigns the arguments value to the instance variable
currentDepth for future use.
public class Fish extends Pet {
int currentDepth;
// This is constructor
Fish(int startingPosition){
currentDepth=startingPosition;
}
}
Now the class FishMaster can create an instance of the Fish and assign
the initial position of the fish. The next example creates an instance of the
Fish that is submerged 20 feet under the sea:
Fish myFish = new Fish(20);
If a constructor with arguments has been defined in a class, you can no longer
use the default no-argument constructor. If youd like to have a constructor
without arguments - write one.
pdfcrowd.com
Have you noticed that the member variable and the constructors argument
have the same name? The keyword this helps to avoid name conflicts. In
this code sample this.currentDepth refers to the objects member
variable currentDepth , while the currentDepth refers to the
arguments value. In other words, the code points at the current instance of the
Fish object.
pdfcrowd.com
pdfcrowd.com
Youll see another important example of using the keyword this in Chapter
6 in the section How to Pass Data Between Classes.
4.6. Arrays
An array is an object that holds several values of the same type - primitives or
objects. Lets say your program has to store the names of four game players.
Instead of declaring four different String variables, you can declare one
String array that has four elements. Arrays are marked by placing square
brackets either after the variable name, or after the data type:
String [] players;
or
String players[];
These declarations just tell the Java compiler that you are planning to store
several text strings in the array players . Each element has its own index
(position number) starting from zero. The next sample actually creates an
instance of an array that can store four String elements and assigns the
open in browser PRO version
pdfcrowd.com
=
=
=
=
"David";
"Daniel";
"Anna";
"Gregory";
You must declare the size of the array before assigning values to its elements.
If you do not know in advance how many elements you are going to have, you
cannot use arrays, but you should look into other classes - Java collections. For
example the ArrayList object does not require you to announce the exact
number of elements in advance. Ill show you some examples of using the
ArrayList collection in Chapter 10 about data collections.
Any array has an attribute called length that stores the number of elements
in this array, and you can always find out how many elements are there:
int totalPlayers = players.length;
If you know all the values that will be stored in the array at the time when you
open in browser PRO version
pdfcrowd.com
declare it, Java allows you to declare and initialize such array in one shot:
String [] players = {"David", "Daniel", "Anna",
"Gregory"};
Imagine that the second player is a winner and youd like to write the code to
congratulate this kid. If the players names are stored in an array get its second
element:
String theWinner = players[1];
System.out.println("Congratulations, " + theWinner +
"!");
pdfcrowd.com
The output from these two lines of code will look like this:
Congratulations, Daniel!
Do you know why the second element has the index [1]? Of course you do,
because the index of the first element is always [0].
The array of players in our example is called one-dimensional array. Imagine
the players sitting like ducks in a row. The single dimension is the seat number
here. If the players (or game spectators) will occupy several rows, then well
have two dimensions - the row number and a set number within the row. This is
the case where wed need to declare a two-dimensional array. Java allows
creation of multi-dimensional arrays, and Ill show you how to do this in
Chapter 10.
pdfcrowd.com
JVM executes every line between the curly braces and then returns back to the
first line of the loop to increment the counter and check the conditional
expression.
There is another flavor of the for loop known as for each loop. It allows the
open in browser PRO version
pdfcrowd.com
program to repeat the same action to every element of the collection without
even knowing how many are there. You are basically saying, do this for each
element.The for-each loop allows to congratulate players in a more concise
manner:
for (String pl: players){
System.out.println("Congratulations," + pl +"!");
}
pdfcrowd.com
In Chapter 9 youll learn how to save the data on the disk and how to read the
saved data back into computers memory. If you read game scores from the
disk file, you do not know in advance how many scores were saved there. Most
likely youll be reading the scores using the while or for-each loop, which
dont require you to state the number of iterations upfront.
You can also use two important keywords with loops: break and
continue .
As with switch statements, the keyword break is used to jump out of the
loop when some particular condition is true . Lets say we do not want to
print more than 3 congratulations, regardless of how many players weve got.
In the next example, after printing the array elements 0, 1 and 2, the break
open in browser PRO version
pdfcrowd.com
will make the code go out of the loop and the program will continue from the
line after the closing curly brace.
The next code sample has the double equal sign == in the if statement. This
means that you are comparing the value of the variable counter with
number 3. A single equal sign in the here would mean assigning the value of 3
to the variable counter . Placing = in an if statement instead of == is a
very tricky mistake, and it can lead to unpredictable program errors that may
be dificcult to find.
int counter =0;
while (counter< totalPlayers){
if (counter == 3){
break; // Jump out of the loop
}
String thePlayer = players[counter];
System.out.println("Congratulations, "+thePlayer+ "!");
counter++;
}
The keyword continue allows the code to skip some code lines and return
back to the beginning of the loop. Imagine that you want to congratulate
open in browser PRO version
pdfcrowd.com
everyone but David the keyword continue will return the program back
to the beginning of the loop:
while (counter< totalPlayers){
counter++;
String thePlayer = players[counter];
if (thePlayer.equals("David"){
continue;
}
System.out.println("Congratulations, "+ thePlayer+ !");
}
There is yet another type of the while loop that starts with the word do , for
example:
do {
System.out.println("Congratulations, "+
players[counter] + !");
counter++;
} while (counter< totalPlayers);
open in browser PRO version
pdfcrowd.com
Such loops check an expression after executing the code between curly braces,
which means that code in the loop will be executed at least once. Loops that
start with the keyword while might not be executed at all if the loop
expression is false to begin with.
named TemperatureConverter.
3. Add the method convertTemp() so the code of the class looks like
this:
public class TemperatureConverter {
public static float convertTemp (float
temperature,
char convertTo) {
}
}
pdfcrowd.com
5. Add the method main using the shortcut psvm + Tab as explained in
pdfcrowd.com
System.out.println("Converting 21C to
Fahrenheit. " + convertTemp(21,'F'));
System.out.println("Converting 70F to Celsius.
" + convertTemp(70,'C'));
}
temperature with two digits after the decimal point. Study Oracles tutorial
about formatting numeric output: http://goo.gl/3riLIZ.:toc-placement!:
:imagesdir: .
pdfcrowd.com
pdfcrowd.com
Since the method talk is not implemented here, its called abstract.
NOTE
open in browser PRO version
pdfcrowd.com
NOTE
pdfcrowd.com
These three classes use the Java keyword implements , which means they
promise to implement all abstract methods in the interface(s) listed after the
keyword implements otherwise the Java compiler will complain: "You
promised to implement all abstract methods from Talkable , where are
they? Keep your promise!"
What if we need to create the class Fish that uses interfaces? Fish dont talk.
But they swim. Dogs can talk (bark) and swim, right? Why wont we declare
yet another interface Swimmable with the methods swim and dive ?
public interface Swimmable {
open in browser PRO version
pdfcrowd.com
Now lets leave the parrots alone. Lets create a new class Fish and change
the class Dog just a little bit. The Fish will implement Swimmable and
the Dog will implement two interfaces:
public class Fish implements Swimmable {
public void swim(int howFar){
System.out.println("OK, will swim " + howFar + "
feet");
}
public void dive(int howDeep){
System.out.println("OK, will dive " + howDeep + "
feet");
}
}
public class Dog implements Talkative, Swimmable {
public void talk(){
System.out.println("Bark! Bark-bark!");
}
open in browser PRO version
pdfcrowd.com
When a class implements several interfaces, make sure to implement each and
every abstract method declared in these interfaces. A class can extend another
class and implement interfaces at the same time, for example:
class Fish extends Pet implements Swimmable{
// your code implementing swim(), dive()
// and any other methods goes here
}
pdfcrowd.com
method dive in the class Dog ? Yes, it can. Java 8 introduced a new
keyword default . Now youre allowed to write a default implementation of
a method in the interface. Such a method wont be considered abstract
anymore, and you wont be forced to implement it in your class. Lets add a
default implementation of the method dive to Swimmable .
public interface Swimmable {
public void swim(int howFar);
public default void dive(int howDeep){
open in browser PRO version
pdfcrowd.com
Now the class Dog doesnt have to implement the method dive - the
compiler will see a default implementation and wont complain. The next
version of the class Dog implements only the method swim from
Swimmable .
public class Dog implements Talkative, Swimmable {
public void talk(){
System.out.println("Bark! Bark-bark!");
}
public void swim(int howFar){
System.out.println("Will swim about a half of
this distance: " + howFar/2 + " feet");
}
}
pdfcrowd.com
method dive on the instance of the Dog class - the default implementation
will be invoked. The next class PetMaster will demonstrate this.
public class PetMaster {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.talk();
myDog.swim(7);
myDog.dive(2); // will use default method
Fish myFish = new Fish();
myFish.swim(50);
myFish.dive(20);
}
}
Run this program and youll see the following output on the console:
_Bark! Bark-bark!
Will swim about a half of this distance: 3 feet
Can't dive, sorry
OK, will swim 50 feet
OK, will dive 20 feet
open in browser PRO version
pdfcrowd.com
The message "Cant dive, sorry" was printed by the default method dive
from the interface Swimmable .
pdfcrowd.com
methods of the interface. The following example illustrates the use of a static
method in the interface. Now the default implementation of the method dive
wont just reject an offer to swim, but will check the current month: if its
June, July, or August then diving is allowed because the water should be warm.
The modified version of the Swimmable interface includes a static method
isSummer that checks the current month and returns true if its June, July,
or August. Im using the Java Date and Time API here. The default method
dive calls the static method isSummer and either agrees or disagrees to
pdfcrowd.com
The method isSummer uses the class LocalTime to get Month , which
has a data type enum that I havent used so far. Its a special data type to
represent a fixed number of some values, like months in this case. There are
only 12 months, and Java Date and Time API listed them by name in the
enum called Month . The only values that are allowed here are
Month.JANUARY to Month.DECEMBER . Using enums makes the
programs more readable - its easier to deal with months by names than by
open in browser PRO version
pdfcrowd.com
numbers.
But this syntax is difficult to read so we use the import statements above
the class declaration to let the compiler know the location of the class,
interface, or enumeration. For example:
import java.time.LocalDate;
open in browser PRO version
pdfcrowd.com
Now you can use just the class name without the need to specify the package
name:
LocalDate todaysDate = LocalDate.now();
The packages are stored in directories and subdirectories on the disk. If you
see a full class name java.time.LocalDate it means that this class was
originally created in the subdirectory time of the directory java.
From now on well use packages and import statement in every chapter of this
book. If you want to place your class into a package, just create a subdirectory
(e.g. pets) and add a package statement on the top of your class definition,
for example:
package pets;
class Dog{
// your code goes here
}
One last thing: Lazy kids use the wild cards in import statements. Instead of
writing one import statement per class, they would use an asterisk:
open in browser PRO version
pdfcrowd.com
import java.time.*;
This means that definitions needed for my program are located in the package
java.time . Of course, writing one import statement instead of several ones
looks appealing, but the readability of the program suffers. Packages can have
dozens of classes and its better to explicitly state which classes your program
uses.
pdfcrowd.com
the code inside the interface or in the classes that implements it. For example,
the interface Swimmable can define the maximum depth allowed for diving.
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
interfaces using lambda expressions, which well discuss later in this lesson.
pdfcrowd.com
The class Animal has two implemented methods: setName and sleep
and one abstract method talk . Since the abstract class can not be
instantiated, the programmer has to create a descendant class and implement
the method talk there if he or she wants to create an instance of such a
class, for example:
public class Dog extends Animal{
public void talk(){
System.out.println("Bark! Bark-bark!");
}
}
open in browser PRO version
pdfcrowd.com
Strictly speaking, its not a must to implement the method talk in the class
Dog , but in this case Dog remains abstract and cant be instantiated. Maybe
the programmer wants to create a class Puppy that extends Dog and
implements the method talk there?
And again you might be wondering, "Why complicate a programmers life by
declaring non-implemented methods?" If you want to build a hierarchy of
classes that extend from Animal you might want to declare an unified
method signature, so each class ( Dog , Parrot , Fish et al.) will have the
same way of initiating the talk.
Interfaces cant have instance methods, but they dont enforce any class
hierarchy. So you can have a class Dog that extends any class, while
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
First comes the version that doesnt use anonymous classes - Ill just use one
method for each operation. The code of the class Calculator is pretty
simple. Note the first line that declares the package where the class
Calculator belongs.
package calc;
public class Calculator {
static double addTwoNumbers (double first, double
second){
double result = first + second;
System.out.println("" + first + " + " +
second + " = " + result );
return result;
}
open in browser PRO version
pdfcrowd.com
This class has two methods that manipulate numbers (one per operation), and
its main method invokes each method passing the same values as arguments.
After performing the arithmetic operation each method prints the result.
Running this program produces the following output:
3.55 + 50.0 = 53.55
open in browser PRO version
pdfcrowd.com
Now lets redesign this application. Instead of writing a separate method for
each operation, I want to write a generic method that can receive the code of
the operation and two numbers to be operated upon. This method will have
three arguments: the arithmetic operation, the first, and the second number.
The operation is a behavior, so lets declare an interface to represent it using a
functional interface with a single abstract method:
package calc;
public interface ArithmeticOperation {
public double performOperation(double a, double b);
}
pdfcrowd.com
package calc;
public class CalculatorWithAnonymousClasses {
// The first anonymous class for addition
static ArithmeticOperation addition = new
ArithmeticOperation() {
public double performOperation(double first,
double second) {
double result = first + second;
System.out.println("" + first + " * " +
second + " = " + result );
return result;
}
};
// The second anonymous class for subtraction
static ArithmeticOperation subtraction = new
ArithmeticOperation() {
public double performOperation(double first,
double second) {
double result = first - second;
System.out.println("" + first + " - " +
second + " = " + result );
return result;
}
};
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
Access Levels
In many code samples Ive been using the keyword public in declaration
of member variables and methods. This means that such a variable or a
method can be accessed by any other code from the project. In the next
chapter Ill explain how to control access levels in Java.
pdfcrowd.com
But there are functional programming languages that dont need to wrap
behavior inside classes. They allow you to implement behavior by writing
functions, which are similar to methods in that they can have names, take
arguments, and return results. But functions dont have to be placed inside
classes and can live independently.
A lambda expression is a function without a name or anonymous function that
you can assign to a variable, pass as an argument to a method or return from a
method. In earlier versions of Java you could pass a value to a method only if
this value was an object or a primitive. But now a function (a piece of code)
becomes a value that can be passed around. Now lets see it in action.
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
You may wonder, "Why are there no data types specified for the lambda
parameters first and second?" The reason being that Java compiler is smart
enough to guess their data types because it knows which abstract method this
lambda implements. An educated guess such as this is called type inference.
IntelliJ IDEA can automatically convert anonymous classes
NOTE
pdfcrowd.com
classes. Earlier in this chapter weve created the classes Dog , Parrot and
the only difference between them was the implementation of the interface
Talkative . But we can declare just one class with a method that can take
Now lets write the class Pet with a method speakup that will take
implementation of the Talkative interface as the first argument and the
pets name as a second one. The class Pet may have many other useful
methods, but Id like to focus on the speakup that can receive a piece of
code defining the rules of talking and apply this code.
pdfcrowd.com
pdfcrowd.com
"Sammy"));
// parrots
Pet myParrot = new Pet();
Talkative parrotTalkRules = (name) -> {
return "I'm a parrot. Don't call me " + name;
};
System.out.println(myDog.speakup(parrotTalkRules,
"Charlie"));
}
}
Weve defined different rules for talking parrots and dogs as lambdas in
variables parrotTalkRules and dogTalkRules accordingly. Not that I
have not specified the data type of the variable name . Its yet another example
of the inferred typing - the Talkative interface has a single abstract method
with the argument of type String . The second argument of the method
speakup will be passed to the method talk . Run this program and itll
pdfcrowd.com
'
'
By using lambda expressions I was able to eliminate the need for creating a
separate class for each animal. Of course, this is possible only if the only
difference between classes Dog and Parrot was implementation of the
talking behavior.
Id like to draw your attention to the fact, that my class Pet has no state - it
doesnt define any class variables. This means that we dont even need to
create instances of the class Pet , but could simply define its method
speakup as static and call it just like this:
Pet.saySomething(dogTalkRules, "Mary")
In Chapter 9 Ill show you more lambda expressions while explaining how to
process GUI events such as click on a button or a mouse move. In the Part 2 of
the assignment that youre about to work on, Ill challenge you to re-write the
class Pet so itll keep the rules of talking in its class variable.
pdfcrowd.com
Part 1. In this part youll do an exercise to prove that you understand Java
interfaces.
1. Create a new IDEA project named chapter5.
2. Create a package named pets.
3. In the package pets recreate the final versions of classes Dog , Fish and
Bark-Bark!"
8. Run and test the PetMaster program.
open in browser PRO version
pdfcrowd.com
Part 2. In this part youll do an exercise to prove that you understand the
basics of lambda expressions.
1. In the project chapter5 create a new package called lambdapets.
2. In the package lambdapets declare the following Talkative interface:
public interface Talkative {
public String talk(String petName);
}
3. Create a new version of the class Pet with the constructor that takes the
rules of talking and pets name as arguments. Its method speakup will
not have arguments. This is how the code of the new Pet should look
like:
public class Pet {
String name;
Talkative myTalkingRules;
Pet(Talkative talkRules, String name){
this.name = name;
myTalkingRules = talkRules;
open in browser PRO version
pdfcrowd.com
}
public String speakup(){
return myTalkingRules.talk(name);
}
}
talking rules for dogs and parrots. It should create two instances of Pet
(one for a dog, and one for a parrot) and invoke the method speakup on
each instance.:toc-placement!::imagesdir: .
pdfcrowd.com
type. Remember arrays and their limitations? Java collections offer alternative
ways of storing similar objects. Then youll get familiar with the mechanism of
generics that allows Java compiler to ensure that you wont be using the wrong
data types with data collections or other objects.
Finally, Ill give you a very light introduction to parallel computing using
multi-threading.
compiler assumes that its a package access level - this element can be
accessed only from the code located in the same package (directory).
One of the main features of object-oriented languages is encapsulation - the
ability to hide and protect data or code. But who do you need to hide or
protect the code from? This is not a protection from bad guys who are not
allowed to see your code. You hide and protect the code from misuse. For
open in browser PRO version
pdfcrowd.com
example, another programmer extended your class and is trying to change the
value of a variable in your class, which may result in bug.
Lets consider an example from the real world. Think of a car most people
have no clue how many parts are under the hood, and what actually happens
when a driver pushes the brake pedal. If car designers would not hide control
of some of the under-the-hood operations, the driver would have to deal with
hundreds of buttons, switches and gauges on the cars dashboard.
pdfcrowd.com
When you design a class, hide methods and class member variables that should
not be visible from outside. Some of the methods of member variables are
meant to be used internally and not to be exposed to other classes.
Well start learning about hiding and protecting data with the private
access level. If a variable or a method are declared private, they can be used
open in browser PRO version
pdfcrowd.com
only within the class where they were declared. The next code sample
represents the class Car and declares some of its members as private .
Note that Ive created this class in the package vehicles .
package vehicles;
public class Car {
// This private variable is visible only inside this
class
private String brakesCondition;
// The public method brake calls private methods
// to decide which brakes to use
public void brake(int pedalPressure){
boolean useRegularBrakes;
useRegularBrakes=
checkForAntiLockBrakes (pedalPressure);
if (useRegularBrakes==true){
useRegularBrakes();
}else{
useAntiLockBrakes();
}
}
open in browser PRO version
pdfcrowd.com
By looking at this code I can say that the class Car exposes only one public
open in browser PRO version
pdfcrowd.com
method brake , which internally may invoke several other functions that a
driver does not need to know about. For example, if the driver pushes the
brakes pedal too hard, the cars computer may apply special anti-lock brakes
implemented in private methods.
I took the next screen shot in IntelliJ IDEA while writing a class CarMaster
that uses Car . IDEA helps me with suggesting the Car class members that I
can use in this context. Only the method brake is visible from the class
Car (other methods are from the class Object ).
pdfcrowd.com
The private access level is the most restrictive one. If youre not sure when
to use it, just declare all of your call member variables and methods as private,
and loosen this restriction if other classes need to use these members.
What do you think will happen if you simply remove the private keyword
from one of the methods of the class Car ? Will the CarMaster see it? No,
open in browser PRO version
pdfcrowd.com
it wont because the absence of the access qualifier gives a package access
level to this member. Only classes that are located in the package vehicles
can access it, and CarMaster is not one of them.
The class members declared with the protected keyword can be accessed
from other members of the same class, from its descendants or classes located
in the same package. Even if a descendant class is located in a different
package, itll be able to access protected methods of its ancestors.
Some software developers are creating libraries or frameworks of classes to be
used by other developers. These classes can be extended, and their creators
may use the keyword protected trying to allow access to certain member
only descendant classes. But in the real world no one can predict what the
developer may want to do with their libraries, and the keyword protected
may become an obstacle in achieving of their goals. I do not use the keyword
protected in my projects. As you gain more experience with Java, see for
6.2. Casting
In Java all classes are directly or indirectly inherited from the class Object ,
which is the root of the class hierarchy. In Figure 2 youve seen a class Car
open in browser PRO version
pdfcrowd.com
that has number of methods that weve never declared - they belong to the
class Object , and the class Car extends Object even though weve
never asked for it. So any of your application classes have an ancestor Object .
When you declare a variable to represent an instance of your class, you can
give it a type either of your class or any of its ancestors. For example, both of
the following declarations are correct:
Car myCar = new Car();
Object myOtherCar = new Car();
Java compiler can cast (convert) one data type to another as long they have
inheritance relation. In particular, Java compiler can automatically cast the type
to the class ancestors. This is called upcasting. But if a variable has the type of
a super class, it wont see any members of the subclass. The next screen shot
shows that the variable myOtherCar doesnt see the method brake
declared in the class Car .
pdfcrowd.com
Figure 45. The Object type variable doesnt see Cars members
But you can say, "Doesnt the variable myOtherCar point at the instance of
the class Car , which has a public method brake ?" Thats right, but since I
declared this variable of the type Object the variable myOtherCar
assumes that its just a general object. The programmer can downcast the
general type to a more specific one, but this has to be done explicitly by
placing the specific type of the object in parentheses before the variable of
more general type, for example:
open in browser PRO version
pdfcrowd.com
Its like youre saying, "I know that the variable myOtherCar is of type
`Object , but it actually points at the Car instance". Now the variable
myOtherCarAfterCasting will see the method brake declared in the
class Car :
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
Pretty much any objects that can be used with the word list can be stored in an
ArrayList .
Why use arrays, then? Lets just always use ArrayList ! Unfortunately,
nothing comes for free, and you have to pay the price for having a convenience
of dynamically sized arrays. The ArrayList works a little slower than a
regular array. Besides, you can only store objects there, while arrays allows
you to store primitives too.To create and populate an ArrayList you should
instantiate it first and then create instances of the objects you are planning to
store there. Add each object to the ArrayList by calling its method add .
The next little program will populate an ArrayList with String objects
and then print each element of this collection.
import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String[] args) {
// Create and populate an ArrayList
ArrayList friends = new ArrayList();
friends.add("Mary");
friends.add("Ann");
friends.add("David");
open in browser PRO version
pdfcrowd.com
friends.add("Roy");
// How many friends are there?
int friendsCount = friends.size();
// Print the content of the ArrayList
for (int i=0; i<friendsCount; i++){
System.out.println("Friend #" + i + " is "
+ friends.get(i));
}
}
}
#0
#1
#2
#3
is
is
is
is
Mary
Ann
David
Roy
The method get extracts the element located at the specified position in the
ArrayList . Since you can store any objects in this collection, the method
get returns each element of the Object type. The program has to cast this
object to a proper data type. We did not do it in the previous example only
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
Note that the class fields color and weight are private variables. But
this class also defines public getters and setters - the methods that read or
modify the fields. In this example the setters and getters dont contain any
application logic, but they could. For example, you could encapsulate the logic
that checks the credentials of the users of this class so not everyone can modify
the weight property. By Java naming conventions the setter name starts with
the prefix set followed by the capitalized letter of the corresponding
private variable. Accordingly, the getter starts with get .
pdfcrowd.com
NOTE
for the class. Just right-click on the class name and select the
options Refactor | Encapsulate Fields.
pdfcrowd.com
First, this program creates a couple of instances of the class Fish passing the
values for the fields via constructor. Note the letter f in the weight value of the
first fish: 2.5f . In Java all decimal literals have the type double unless
you mark it with the suffix f for float .
Each instance is added to the collection fishTank . Then, the program gets
the objects from this collection, casts them to the class Fish and prints their
values using getters. Heres the output of the program FishTank :
Got the Red fish that weighs 2.5 pounds.
Got the Green fish that weighs 5.0 pounds.
The ArrayList collection uses Java arrays internally and initially creates an
open in browser PRO version
pdfcrowd.com
array for 10 elements. But if you keep adding more elements to ArrayList
it internally will create another array of the larger size and copy all existing
elements there. Because of this additional memory allocations and data
copying ArrayList collections works a little slower than arrays, which
allocate enough memory in advance.
pdfcrowd.com
(the keys), and then will print the phone number of the second contact.
import java.util.Hashtable;
public class HashTableDemo {
public static void main(String[] args) {
ContactDetail friend1 = new ContactDetail();
friend1.fullName = "Jackie Allen";
friend1.email = "jallen@gmail.com";
friend1.facebookID = "jallen";
friend1.phone="212-545-5545";
ContactDetail friend2 = new ContactDetail();
friend2.fullName = "Art Jones";
friend2.email = "ajones@gmail.com";
friend2.facebookID = "ajones";
friend2.phone="212-333-2121";
Hashtable friends = new Hashtable();
friends.put("Jackie", friend1);
friends.put("Art", friend2);
pdfcrowd.com
In this example I used the first name as the key in the method put that adds
elements to a Hashtable . Hence one contact can be referred by the key
get("Jackie") , and the other one as get("Art") . The method get
pdfcrowd.com
pdfcrowd.com
named Art and will create a new instance of the ContactDetail object.
If youll add it to the same collection under the same key friends.put("Art", friend3); itll replace the contact details of the
first Art with the data of the second one. This happens because Java
Hashtable internally generates a hash key (the number) from your key and
uses it as an index to find the element when need be.The same names will
generate the same hash keys. So either give the second Art a nickname like
ArtFromNYC or use another Java collection like ArrayList to store your
pdfcrowd.com
collection that can store any data you can pass it a parameter to allow only the
objects of certain data types. Instead of declaring and instantiating a general
collection to store friends like this:
ArrayList friends = new ArrayList();
you can do it with a parameter so it can store only String objects like this:
ArrayList<String> friends = new ArrayList<>();
The parameter(s) goes in the angle brackets right after the data type. Note the
so called diamond operator <> on the right. Since you already declared the
required data type on the left, there is no need to repeat it on the right compiler will guess the type. Its also an example of type inference introduced
in the previous lesson about lambda expressions. Now, if by mistake youll try
to add an object of another type to friends the Java compiler will
open in browser PRO version
pdfcrowd.com
complain.
I was able to specify a parameter for ArrayList only because it was created
with this ability. If youll read the online documentation for ArrayList
youll see that its declared as follows:
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
That <E> means that youre allowed to specify a parameter type of elements
that will be stored in the the ArrayList . In case of the friends
collection the Java compiler would see that in this collection <String>
should be the <E> .The online documentation for the class Hashtable looks
even scarier:
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, Serializable
But <K,V> simply means that you can specify two parameters: K is the the
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
Java compiler sees no crime here - the Hashtable can store any
descendants of the class Object . But if youll run this program, youll get an
open in browser PRO version
pdfcrowd.com
error in the line that tries to cast the collection element to ContactDetail
type. This is how my IntelliJ IDEA screen with the error looks like:
pdfcrowd.com
Now Ill copy the code of HashTableBrokenDemo into the new class
called HashTableGenericsDemo . Ill make a small change there - I will
declare the collection friends with parameters:
Hashtable<String, ContactDetail> friends = new
Hashtable<>();
Now Im explicitly stating that my intention is to use the String objects for
keys, and ContactDetail objects as values. The program
HashTableGenericsDemo is shown next - it wont even compile!
public class HashTableGenericsDemo {
public static void main(String[] args) {
ContactDetail friend1 = new ContactDetail();
friend1.fullName = "Jackie Allen";
friend1.email = "jallen@gmail.com";
friend1.facebookID = "jallen";
friend1.phone="212-545-5545";
open in browser PRO version
pdfcrowd.com
The compiler will complain about the line, where Im trying to call the method
put with two String objects as arguments. The Java compiler will
Another important thing to note is that there is no casting needed when the
program gets the information about Jackies phone. Now the friends
open in browser PRO version
pdfcrowd.com
collection knows from the very beginning that it stores not just some Object
types, but the ContactDetail instances.
What have we achieved? The program HashTableBrokenDemo allowed us
to store anything in the collection but crashed during the runtime, but
HashTableGenericsDemo prevented this error from happening. Having a
compilers error its a lot better than getting surprises during the runtime, isnt
it? Besides, with generics weve eliminated the need to cast objects.
Ive been using the parameterized data type Hashtable that was
conveniently offered by the creators of Java, but you can define your own
classes with parameters too. Creating your own parameterized classes is one of
the more advanced topics, and I wont be covering it in this book. Check out
Oracles tutorial if interested.
pdfcrowd.com
In a real life though, we can do several things in parallel like eat, talk on the
phone, watch TV, and do the homework. To do all these actions in parallel we
use several "processors": hands, eyes, and mouth.
pdfcrowd.com
Today, only your grandmas computer has a single processor (a.k.a. Central
Processing Unit or CPU). A CPU performs calculations, sends commands to
open in browser PRO version
pdfcrowd.com
the monitor, hard disk or a solid state drive, remote computers on the Internet,
and so on. Most likely your computer has at least two CPUs and a GPU
(Graphics Processing Unit) for processing graphics if any.
But even a single processor can perform several actions at once if a program
uses multiple threads. One Java class can start several threads of execution
that will take turns in getting time slices of the processors time. For example,
the program asks the user a question and waits for the response. Meantime the
CPU can be used for performing some other application logic instead of idling
as shown in Figure 7.
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
The first loop simply multiplies the variable i to itself four times. In the
second loop I simply concatenate a String, the value of k and an exclamation
point. The second loop will start only after the first loop is complete, and no
matter how many times youll run this program, the output on the console will
always look like this:
The
The
The
The
open in browser PRO version
value
value
value
value
of
of
of
of
i
i
i
i
in
in
in
in
power
power
power
power
of
of
of
of
4
4
4
4
is
is
is
is
0
1
32
243
pdfcrowd.com
The
***
***
***
***
***
This was an example of a sequential code execution in a single thread. But the
actions that we do in each loop dont depend on each other and can be
executed in parallel, right?
Lets change this example a little bit. The following class
MultiThreadedDemo executes two loops in parallel. It creates a separate
thread for the fist loop, and starts it in a separate thread so the main thread,
which has the second loop doesnt wait for the first one to complete.
public class MultiThreadedDemo {
public static void main(String[] args) {
Thread myThread = new Thread(
(1)
() ->{
(2)
for (int i=0; i<5;i++){
System.out.println("The value of i in power
of 4 is " + i*i*i*i*i);
open in browser PRO version
pdfcrowd.com
}
}
(3)
);
myThread.start();
(4)
1. We start the program with creating a new instance of the Thread class
Note that the lambda expression doesnt specify any parameter. Java
compiler is smart enough to guess that since the constructor of Thread
expects an instance of Runnable then our lambda expression
implements this interface. The for loop automatically becomes an
implementation of the method run . This is what we want to run in a
separate thread
open in browser PRO version
pdfcrowd.com
which is defined in the class Thread and will internally invoke the
method run , which is implemented as lambda. The method start
doesnt wait for the completion of the method run so the next line in our
main method is executed.
The value of k is 0!
The value of k is 1!
value of i in power of
value of i in power of
The value of k is 2!
The value of k is 3!
The value of k is 4!
value of i in power of
value of i in power of
value of i in power of
4 is 0
4 is 1
4 is 32
4 is 243
4 is 1024
pdfcrowd.com
Note that the first two lines print the output from the second loop! This means
that after calling the method start on the thread myThread the program
didnt wait for the completion of the first loop, which ran in parallel thread.
Then the first loop had something to print. Then the second, etc. The entire
console output is a mix of two parallel number-crunching threads.
You may say, is it even a real-world example? Who needs to run such simple
loops in parallel? I made this example simple to get across the message that
one program can do stuff in parallel.
For a more realistic scenario think of a game with fancy graphics that needs to
update the images on the screen and perform some complex algorithms. If such
a program would sequentially do the screen updates and algorithms, the game
would run slow with noticeable delays in the graphics during times when the
program does number crunching. In Chapter 8 Ill illustrate the effect of the
"frozen" screen and how to deal with it using a separate thread for screen
updates.
pdfcrowd.com
this:
public class ContactDetail {
private String fullName;
private String facebookID;
private String phone;
private String email;
public String toString(){
return "Name: " + fullName +
", Facebook ID: " + facebookID +
", phone: " + phone +
", email: " + email;
};
}
Note that Im overriding the method toString that exists in the class
Object .
open in browser PRO version
pdfcrowd.com
4. In IntelliJ IDEA right-click on the class name and select the options
Refactor | Encapsulate Fields to generate public getters and setters for all
fields.
5. In the package contacts write a program MyContacts that will declare
print all their contact informationby simply printing each object from the
collection friends . Since the class ContactDetails has an
overriden method toString , you can simply print the objects as shown
below - the method toString will be invoked automatically:
for (ContactDetail friend: friends){
System.out.println(friend);
}
pdfcrowd.com
9. The output of the program MyContacts should look similar to this one:
Name: Jackie Allen, Facebook ID: jallen, phone:
212-545-5545, email: jallen@gmail.com
Name: Art Jones, Facebook ID: ajones, phone:
212-333-2121, email: ajones@gmail.com
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
the Stage object - this is where your GUI components will live and perform.
Pretend that youre a play director and need to set up one or more scenes
(views) on stage. But if in a real scene youd expect to see some chairs, tables
open in browser PRO version
pdfcrowd.com
and other pieces of furniture, each JavaFX scene consists of GUI containers
and components. In JavaFX youll create components, add them to the scene
and then add a scene to the stage. When the stage is ready, open the curtain by
calling the method show .
All GUI components are subclasses of the class javafx.scene.Node , and
when Ill be using the word node just think of a GUI component. Now you
have a choice: create these nodes using Java classes or load the pre-created
design from the .fxml file as it was done in the code generated by IDEA.
The method start loads the file sample.fxml, sets the title of the stage and
creates a Scene 300 by 275 pixels.The content of the generated sample.fxml
looks like this:
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<GridPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml"
alignment="center" hgap="10" vgap="10">
</GridPane>
open in browser PRO version
pdfcrowd.com
shown next:
pdfcrowd.com
pdfcrowd.com
HBox
VBox
FlowPane
GridPane
BorderPane
StackPane
TilePane
AnchorPane
The HBox class (the horizontal box) places controls in a row next to each
other. The vertical box VBox places controls vertically. The FlowPane
places the nodes in a row and then wraps to the next row if there is no room
left in the current one.
The GridPane allows to arrange UI controls in rows and columns and assign
constraints (properties) to each cell.
The BorderPane splits the scene into five regions, which are called left ,
top , right , bottom , and center .
open in browser PRO version
pdfcrowd.com
The TilePane layout is similar to the FlowPane , but it places each GUI
components in a cell of the same size similarly to tiles on the wall. Say, you
need to display several images in a tile layout. Adding the ImageView
components to the TilePane will shows them as tiles next to each other.
The StackPane layout works as a deck of playing cards - only one child
node will be shown at a time covering the other nodes.
The AnchorPane lets you to anchor nodes at left, top, right, and bottom of
the scene. Imagine a music player application with the buttons Rewind on the
left and the Fast Forward on the right. For example, the AncorPane allows
you to force the Rewind button to always remain at 20 pixels from the left
border of the window and 10 pixels from the bottom even when the window
resizes. For that you can use the leftAnchor and bottomAnchor
properties. For example,
AnchorPane.setLeftAnchor(rewindBtn, 20);
AnchorPane.setBottomAnchor(rewindBtn, 10);
pdfcrowd.com
youd be writing the code manually in Java, youd be going through the
following steps with any layout:
1. Create instances of child nodes to be used within the layout container.
2. Create an instance of the selected layout class (e.g. HBox ). This instance
will serve as a container and a layout manager for all child nodes that
youll add to it.
3. Add the child nodes to the container using either the method add() or
addAll() .
4. If this layout instance needs to be used inside another layout (e.g. an
HBox can be placed inside the BorderPane ) add the instance created
pdfcrowd.com
pdfcrowd.com
On the left panel you can select containers, controls, menus, shapes and drag
and drop them onto the central canvas area. Note the GridPanel layout shown
at the bottom left - the arrangement of GUI components inside of this scene
will be controlled by GridLayout . Let me select the Button from the
Controls section on the left and drop it on the canvas in the middle. The Screen
Builders window will look like this:
open in browser PRO version
pdfcrowd.com
The right panel allows you to change the properties of this button. These little
boxes with the digit one represent so called row and column constraints - well
discuss them shortly.
The Scene Builders menu Preview | Show Preview in Window will show how
your GUI will look during the runtime. So far our one-button screen is not too
open in browser PRO version
pdfcrowd.com
Lets save the changes in sample.fxml (menu File | Save) and open this file in
the IDEA text editor. When IDEA generated sample.fxml there was no content
between <GridPanel> and `</GridPanel>`in the generated sample.fxml, but
now there is:
<?xml version="1.0" encoding="UTF-8"?>
<?import
<?import
<?import
<?import
<?import
<?import
<?import
open in browser PRO version
javafx.scene.control.*?>
java.lang.*?>
javafx.scene.layout.*?>
javafx.geometry.Insets?>
javafx.scene.layout.GridPane?>
javafx.scene.control.Button?>
javafx.scene.control.Label?>
pdfcrowd.com
Ill go through the details of the GridPane layout in the next section, but
please note that Scene Builder created some tags to specify the constraints for
the rows and columns of the grid. The Button component is placed inside
the grid in the cell located in the intersection of the column 1 and row 1.
pdfcrowd.com
components (the nodes) into the grid cells. With GridPane layout cells dont
have to have the same size - a node can span (be as wide or as tall as several
others). If the screen size changes, the content wont be rearranged and will
maintain the grid look.
Before placing the node into a particular cell you have to specify the grid
constraints such as rowIndex and columnIndex (the coordinate of the
cell, which starts with 0,0). The rowSpans and columnSpan allow you to
make the cell as wide (or as tall) as several other cells. The GridPane
documentation describes lots of various constraints that can define the behavior
of each cells content if the windows gets resized. Ill show you a basic
example that uses some of these constraints.
pdfcrowd.com
I want to create a Sign In window where the user can enter the id, password
and press the button Sign In. The scene will use GridPane layout. The first
row will contain a Label and TextField for user id, the second row will
have a similar pair for the password, and the third row of the grid will have one
Button Sign In that should span two columns. This is how this window
pdfcrowd.com
Ill start with creating a new IDEA JavaFX project (menus File | New Project |
JavaFX Application) giving it the name Signin . The project with classes
Main , Controller and the file sample.fxml will be generated. Lets
rename this FXML file into signin.fxml. IDEA will automatically change the
corresponding line in the Main class to load this file instead of sample.fxml:
Parent root =
FXMLLoader.load(getClass().getResource("signin.fxml"));
Open the generated signin.fxml in Scene Builder. Since this file has
open in browser PRO version
pdfcrowd.com
already empty <GrigPane> tag, youll see GridPane(0,0) as the root of the
hierarchy in the bottom left corner as in Figure 4 above. So far this grid has
zero rows and zero columns. Right-click on the grid in the middle of the screen
and add three rows and two columns to the grid by using the right-click menus
GridPane | Add Row Below and Add Column After. When the GridPane is
selected The Scene Builders window may look similar to this:
Now lets drag two Label controls and a Button from the Controls section
open in browser PRO version
pdfcrowd.com
on the left and drop them into the appropriate cells in the first grid column.
Change the text on these components to be UserID:, Password, and Sign In.
Then we could drag and drop two TextField objects in the top two cells in
the second column. Actually, its not a good idea to enter password in the clear
text. Ill use the TextField for the user ID, and the PasswordField (it
marks users input) for password.
pdfcrowd.com
Note that the hierarchy of nodes is shown in the bottom left panel of Scene
Builder. If you want to change the properties of a component on a scene with a
complex GUI layout it might be easier to select the GUI control in the
Hierarchy panel than in the design area in the middle. Now select the menu
Preview | Show Preview in Window and youll see the following window:
This window doesnt look exactly as we wanted: there are some issues with
alignments, there is no spacing between the container and components, and the
button Sign In doesnt span. But on the bright side, the GridPane controls
open in browser PRO version
pdfcrowd.com
the layout and if youll try to stretch this window, GUI components wont
change their relative positioning:
pdfcrowd.com
Lets do a couple of more property changes before well run this application
from IDEA. In Scene Builder the Properties panel is located on the right and
has three sections: Properties, Layout, and Code, and youll find the properties
to be changed in one of these sections.
1. On the left panel of Scene Builder select the GridPane and on the right
We need some spacing between the borders of the scene and the grid.
3. Select the Button on the left and then change the column span to be 2
and the preferred width to be a large number, say 300. This will make the
button wide.
4. Select the first column of the grid row by clicking on the little 0 on top of
the grid. Set the both preferred and maximum width for this column to be
70.
5. Select the second column of the grid row by clicking on the little 1 on top
of the grid. Set the both preferred and maximum width for this column to
be 100.
After you do all these changes and save them, the file signin.fxml will
open in browser PRO version
pdfcrowd.com
javafx.geometry.*?>
javafx.scene.control.*?>
java.lang.*?>
javafx.scene.layout.*?>
javafx.geometry.Insets?>
javafx.scene.layout.GridPane?>
javafx.scene.control.Button?>
javafx.scene.control.Label?>
pdfcrowd.com
pdfcrowd.com
ensures that there is some space between the grid borders and its children.
This is a declarative way of creating GUI in FXML. No Java coding was
required to create the GUI for this application.
Finally, lets set the size of the stage so it can accommodate all components
from our scene. In IDEA, open the class Main , and in the code set the size of
the scene to be 200x150 pixels.
primaryStage.setScene(new Scene(root, 200, 150));
Run the Main program and youll see the window that looks similar to the
one in Figure 7 above. The work that weve done in Scene Builder was a little
tedious, but it didnt require any knowledge of Java. This means that this work
can be given to a UI designer, while youll concentrate on programming the
application logic in Java.
pdfcrowd.com
do it. Below is the Java code of the Sign In window that Ive written purely in
Java without using Scene Builder. Itll produce the same output as in Figure 7.
public class GridPaneSample extends Application {
public void start(Stage primaryStage) {
final int TWO_COLUMN_SPAN = 2;
Label userIdLbl = new Label("User ID:");
TextField userIdTxt = new TextField();
Label userPwdLbl = new Label("Password:");
PasswordField userPwdTxt = new PasswordField();
GridPane root = new GridPane();
root.setVgap(10);
root.setPadding(new Insets(10));
root.setAlignment(Pos.CENTER);
// Using static methods for setting node
constraints
GridPane.setConstraints(userIdLbl, 0, 0);
GridPane.setConstraints(userIdTxt, 1, 0);
GridPane.setConstraints(userPwdLbl, 0, 1);
GridPane.setConstraints(userPwdTxt, 1, 1);
open in browser PRO version
pdfcrowd.com
root.getChildren().addAll(userIdLbl, userIdTxt,
userPwdLbl, userPwdTxt);
Button signInBtn = new Button ("Sign In");
// Allow the button to be wider overriding
preferred width
signInBtn.setPrefWidth(Double.MAX_VALUE);
// using instance method for directly adding the
node
root.add(signInBtn,0,2,TWO_COLUMN_SPAN,1);
Scene scene = new Scene(root,250,150);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
After all your efforts in Scene Builder, this Java program shouldnt be difficult
for you to understand. As you see, I use classes named similarly to FXML tags.
open in browser PRO version
pdfcrowd.com
FXML tags can have attributes (e.g. vgap="10" `), and in Java
youd need to call the corresponding setter (e.g.
`root.setVgap(10) ). So the choice is yours - FXML or Java. If you have
pdfcrowd.com
interested in how to create custom skins, visit Oracle online tutorial Skinning
JavaFX applications with CSS.
Even if you wont create your own CSS file, your JavaFX application applies
default CSS style to the components of your view. In Scene Builder you can
see these styles. Just select any component and then go to the menu View |
Show CSS Analyzer. Youll see a number of styles the start with the prefix
fx- , which makes JavaFX CSS a little different from a standard CSS syntax.
Covering CSS in detail would require a separate book, but Ill show you a
simple example of how the look of the GUI can be changed without the need
to modify the Java code.
You can either create so-called CSS selectors to style a specific GUI
component, a type of components (e.g. all buttons), or create a reusable style
that can be applied programmatically to a selected component.
To style a specific component it has to have a unique id. If you program GUI
in Java, set in your Java code using the method setId() , for example:
Button signInBtn = new Button ("Sign In");
signInBtn.setId("submitBtn");
open in browser PRO version
pdfcrowd.com
For a button with an id submitBtn you can add the following section to the
CSS file to make its background color red:
#submitBtn{
-fx-background-color: red;
}
You can find the names of the main CSS colors online. In CSS the id type
selectors start with the #-sign as in #submitBtn .
If you want to apply a style to several components of the same type, you need
to define a type selector. For example, to make the text of all Label
components red, you can define the following CSS type selector:
.label{
-fx-text-fill: red;
open in browser PRO version
pdfcrowd.com
Note that CSS type selectors start with the dot. To create a CSS class selector
that can be applied to any component, define the selector with an arbitrary
name and apply it programmatically to the components of your choice. For
example, you can specify the class selector .blueLable :
.bluelabel{
-fx-text-fill: blue;
-fx-font-family:verdana;
-fx-font-style:italic;
}
This class selector defines the rules that will display text of the component in
blue bold verdana font in italic style. Typically, youll be loading the entire
CSS file when the application starts so all styles are available for use. If you
use Java for GUI programming, you can apply a class selector to a specific
button just like this:
Label userPwdLbl = new Label("Password:");
userPwdLbl.getStyleClass().add("bluelabel");
open in browser PRO version
pdfcrowd.com
You may ask, "How am I supposed to know which style properties are
available for a given JavaFX component?" All JavaFX styles are described in
the online document titled "JavaFX CSS Reference Guide".
Lets learn how to apply all these styling techniques to the Sign In window
from the previous section. Using IDEA menu File | New create a new file
signin.css in Signin project. Then add the following content to it:
#submitBtn{
-fx-background-color: lightskyblue;
-fx-font-family:verdana;
-fx-font-size:20;
-fx-font-weight: bold;
-fx-stroke:navy;
-fx-font-style:italic;
-fx-border-radius: 20;
open in browser PRO version
pdfcrowd.com
-fx-background-radius: 20;
-fx-padding: 5;
}
.label{
-fx-text-fill: red;
}
.bluelabel{
-fx-text-fill: blue;
-fx-font-family:verdana;
-fx-font-style:italic;
}
pdfcrowd.com
pdfcrowd.com
launch(args);
}
}
Run the Main application and youll see a differently styled Sign In window:
When the application starts loading our CSS file it sees that all labels must be
open in browser PRO version
pdfcrowd.com
red because of the type selector for labels. But then the application notices a
more specific style for the Label Password:
styleClass="bluelabel" , so it paints the text Password in blue.
Each of these regions can contain either a single GUI component or a container
that will have "children" - components allocated in their own container, e.g.
inside a GridPane . Youll use BorderPane layout with a nested
GridPane while working on the calculator following instructions from the
Project section at the end of this chapter. Meanwhile, lets create a very basic
window illustrating how the BorderPane layout works.
Open Scene Builder and create a new FXML file by selecting the menu File |
New. Then drag the BorderPane from the left and drop in the middle. Click
open in browser PRO version
pdfcrowd.com
on the BorderPane and youll see a screen that can look as follows:
Now select Insert TOP at the bottom left, and then drag and drop a Label
from the Controls section onto the middle section of Screen Builder. Set the
labels title to "This is the Header". This text will be displayed at the top.
Select Insert LEFT and then drag and drop VBox from the Containers area to
the left side of the middle section of the Screen Builder. The VBox is a
container for arranging GUI components vertically, which is what we need for
open in browser PRO version
pdfcrowd.com
creating a navigation menu. Youll see an empty gray area on the left.
Now select VBOX at the bottom left and add a couple of menu items to the
empty VBox . Drag a Button from the Controls section and drop it onto the
VBox . Change its text to read "Menu 1", and make it a little wider so it fits
the VBox nicely. Add two more buttons labeled "Menu 2" and "Menu 3".
pdfcrowd.com
Our left navigation bar has a menu thats implemented as buttons. In Chapter
10 while developing a Tic-Tac-Toe game Ill show you how to create real
menus.
Lets add a footer to the window now. Select Insert BOTTOM at the bottom
left and then drag the HBox from the Containers area to the middle section.
Itll look like a gray area at the bottom. Adjust its height so the footer doesnt
take too much real estate in our scene. Now add three Hyperlink
open in browser PRO version
pdfcrowd.com
components from the Contols section to the footer and set their text to "Link
1", "Link 2", and "Link 3" correspondingly. The Scene Builders window
should look like this:
Select the menu Preview | Show Preview in Window will help you to see how
the window will look during the runtime:
pdfcrowd.com
Of course, this window may need more work on styling controls and adjusting
sizes and alignments, but as long as you understand how to lay out a scene,
they shouldnt be too difficult. Creating and applying CSS styles can make this
windows a lot prettier.
pdfcrowd.com
Save the layout in a file border.fxml using Scene Builders menu File | Save.
While youve been dragging and dropping components, Scene builder was
working hard generating the corresponding FXML code in border.fxml. If you
open this file in any text editor, its content may look similar to this:
<?xml version="1.0" encoding="UTF-8"?>
<?import
<?import
<?import
<?import
javafx.scene.image.*?>
javafx.scene.control.*?>
java.lang.*?>
javafx.scene.layout.*?>
pdfcrowd.com
<Button mnemonicParsing="false"
prefHeight="26.0" prefWidth="99.0" text="Menu 1" />
<Button mnemonicParsing="false"
prefHeight="26.0" prefWidth="99.0" text="Menu 2" />
<Button mnemonicParsing="false"
prefHeight="26.0" prefWidth="99.0" text="Menu 3" />
</children>
</VBox>
</left>
<bottom>
<HBox prefHeight="42.0" prefWidth="600.0"
BorderPane.alignment="CENTER">
<children>
<Hyperlink text="Link 1" />
<Hyperlink text="Link 2" />
<Hyperlink text="Link 3" />
</children>
</HBox>
</bottom>
</BorderPane>
Dont be overwhelmed with the amount of tags and attributes in the above
code. You can identify the regions of the BorderPane layout. The <top>
region contains a label, while the left and <bottom> regions have
containers with their own layouts. In this example I have not used the
open in browser PRO version
pdfcrowd.com
the content of the central area based on the user actions. For example, if the
user clicks on the "Menu 1" button in the left region, JavaFX will generate a
clicked event and youll show the content required for this selection in the
central area.
Youll learn how to process events in the next chapter. Now its time to
practice in working with combined layouts
7.1. Add the TextField to the north region of the BorderPane . Then
add a GridPane container to the center area - youll add buttons to this
container.
Most of the calculators have a display field on top and the buttons just below
it. As you can see on Figure 1, the grid with buttons has four columns and six
rows. The default GridPane contains two columns and three rows. Youll
need to right-click on the grid and use the menus GridPane | Add Row Above
and Add Column After to until you see a 4x6 grid as shown below.
open in browser PRO version
pdfcrowd.com
Note that I set the Padding property to be 10 for all sides of the grid and the
Hgap and Vgap to 5 (the gap between the cells).
Save the layout in the file calculator.fxml. Then drop a Button into the top
left cell of the grid. Set the Margin property to 5 for each side of this button.
This is the distance between the button and cell borders. Drag the buttons
open in browser PRO version
pdfcrowd.com
If youre curious how this button looks in the calculator.fxml, open this file in
any text editor and note the section <children> that in my case looks like
this:
pdfcrowd.com
<children>
<Button mnemonicParsing="false" prefHeight="37.0"
prefWidth="132.0" text="Button">
<GridPane.margin>
<Insets bottom="5.0" left="5.0" right="5.0"
top="5.0" />
</GridPane.margin>
</Button>
</children>
There is no indication of the cell (0,0) because zeros are the default values for
GridPane.columnIndex and GridPane.rowIndex properties. Now
you need to replicate this button in other cells. You can use multiple CtrlC/Ctrl-V commands and then drag/drop the buttons into other cells. See how
the content of the calculator.fxml changes as you add more buttons. I find it
faster to copy/paste the generated code in the FXML file than using Scene
Builder for mass duplication.
Note that in Figure 7.1, the button with coordinates (0,5) spans two columns,
and the button with coordinates (3,4) spans two rows. For these buttons youll
need to enter 2 as the row (or column) span, and select MAX_VALUE as
maximum width (or height). This is what you should see by now:
open in browser PRO version
pdfcrowd.com
Change the text of each button to look Figure 7.1, and the layout is done.
Then create a new JavaFX project Calculator in IDEA and replace the
generated sample.fxml with calculator.fxml created by Scene Builder. Modify
the generated class Main to use calculator.fxml. Rename the package from
sample to mycalculator. Set the size of the scene to be large enough to
open in browser PRO version
pdfcrowd.com
Run the Main program from IDEA to ensure that your calculator looks as
expected. Dont allow the users to resize your calculator by invoking the
method setResizable on the stage object.
Then create a CSS file to add some cool styling to the calculators buttons.
open in browser PRO version
pdfcrowd.com
Save the CSS file in your IDEA project and modify the code of the Main
class to use your CSS file similarly to how it was done in the section "Styling
With CSS" above. Make your calculator look better than mine - its not too
difficult.
After completing this assignment your buttons wont work just yet. In the next
chapter youll learn how to make the buttons (or other components) to react to
user actions, so youll be able to complete the calculator. In this chapter my
goal was to introduce you to basic rules of designing JavaFX GUI with the
help of Scene Builder. Watch this YouTube video to see how easy it is to
design more complex views with Scene Builder.:toc-placement!::imagesdir: .
pdfcrowd.com
you click on the Sign In or calculators buttons, nothing will happen because
we didnt teach the application how to react to user-generated events. Events
are notifications that something important for the application has happened
(e.g. the user clicked on the button). In this chapter Ill explain how to write
code to handle such events.
When IDEA creates a new JavaFX project it generates an empty class
Controller , which is the right place for the code that communicates with
GUI components. In this chapter well establish a link between GUI and the
controller. Well also add event handlers and will write code to modify the
GUI. Ill continue working with FXML samples created in the previous
chapter, but this time the GUI events will be handled by the code from the
controller class.
Youll learn how data binding can automatically update the properties of a GUI
component if a property of a Java controller class changes. Ill also show the
difference between wrong and the right way of updating the GUI to make the
used interaction more responsive.
8.1. Events
JavaFX applications have to deal with various events. For example, a button
open in browser PRO version
pdfcrowd.com
click, the movement of the mouse etc. When the event happens, the event
object is represented by one of the subclasses of the class Event located in
the packages javafx.event and javafx.scene.input . You need to
decide what events are important to your program and, as the programmers
say, "listen to these events". Youll always write event handlers (a.k.a. event
listeners) in Java, but there are different ways of assigning event handlers to
GUI elements. If your GUI is designed using FXML, youll need to specify the
name of your controller class right in the FXML file. If your GUI is designed
with Java, using a separate controller class is not a must, but is a good idea if
your code has to process multiple events.
pdfcrowd.com
You can create an instance of your controller class either with the new
operator or inject it into Java code. Ill explain what injection means in a bit.
pdfcrowd.com
pdfcrowd.com
The hgap and vgap attributes specify the padding between the grid
columns and rows. The xmlns attributes specify so called namespaces
required for proper parsing of FXML files. And the attribute
fx:controller specifies the full name of the class Controller , which
pdfcrowd.com
pdfcrowd.com
If you run the Main program and click the Sign In button three times, the
console will print the hello message three times as shown on Figure 8-3.
pdfcrowd.com
So there is a link between the GUI and the controller. If we had several buttons
on the GUI, we could either map each of them to a separate method in
controller, or have one method for all buttons with the code recognizing which
button was clicked. The controller will invoke your event handler providing
the ActionEvent object as an argument. Its property target identifies
the target of the event, which is a Sign In button in our case.
I ran our application in the debug mode just to show you that the target
property on the ActionEvent correctly recognizes the event target shown
open in browser PRO version
pdfcrowd.com
in Figure 8-4.
The ActionEvent has another property called source , which has the
same value as target in our application. There are cases when source
and target are different because an event travels through all containers until
it reaches the target. Then it bubles up through all the containers. This is an
advanced topic, but I still want to give you an illustration.
While handling button clicks, you dont really care where exactly inside the
button was the mouse pointer when the user clicked on the button. So handing
ActionEvent was sufficient. But there is another event called
open in browser PRO version
pdfcrowd.com
MouseEvent , which gives you more details on the click event like the
coordinate of the mouse pointer, or if some of the keys were down during the
click.
In signin.fxml youre allowed to use onMouseClicked instead of
onAction for the button. But if you do so, the Button will be considered
a container for a special skin class LabeledText with the text Sign In, and
if you click on the words Sign In the source of the event will be Button , and
the target would be the class LabeledSkin . Just for the illustration
purposes, Ive created an event handler signInMouseClicked and ran it
through a debugger. Now the source and target of the event are different.
pdfcrowd.com
pdfcrowd.com
Only the TextField and PasswordField have the attribute fx:id open in browser PRO version
pdfcrowd.com
this is how you can assign ids in FXML. The next step is to inject references
to these GUI components into the variables in the Controller class. The
following code fragment shows how to inject component references into the
id and pwd fields. Ive declared two Java variables in the Controller
Java has so called annotations (not covered in this book). They start with the @
sign and can be placed in front of the variable, class, or a method declaration
depending on how the annotation was defined. Some annotations are used by
Java compiler, and some by the JVM. The JavaFX annotation @FXML instructs
runtime to inject the references to the specifies GUI objects into the variables.
In other words, JavaFX runtime will read the first line as follows:"I need to get
the object that I created after loading signin.fxml file, and find the
component with fx:id="id" inside this object. Finally, I need to insert the
reference to this component into the Java variable id ". The same applies to
the variable pwd .
open in browser PRO version
pdfcrowd.com
The rest is easy. Just use the injected values in your event handler. The code of
our Controller is shown next. Its method signInClicked checks the
value entered in the User ID field in the GUI, and if its not equal to "Yakov",
then the code sets the background of the GUI component to the light pink
color.
public class Controller {
@FXML private TextField id;
(1)
(1)
(2)
(2)
if (!"Yakov".equals(userID)){
(3)
id.setStyle("-fx-background-color:lightpink;"); (4)
} else{
id.setStyle("-fx-background-color:white;");
(5)
}
System.out.println("got id:" + userID + ", got
password: " + password);
open in browser PRO version
pdfcrowd.com
operator ! here.
4. Set the background color to lightpink if the entered user id is not
Yakov.
If you run the Main program and enter the wrong user id, the window will
look as follows:
pdfcrowd.com
methods.
open in browser PRO version
pdfcrowd.com
You can provide event handling code to the convenience methods using
anonymous inner classes, lambda expressions, or method references (not
covered in this book). Implementing event handlers as lambda expressions is
easier than with anonymous inner classes. Typically, youll be writing code to
react if an event has happened. For example, if you have a button represented
by a variable myButton you can write an event handler for the click event:
Button signInButton = new Button("Sign In");
signInButton.setOnAction(evt ->
System.out.println("The Sign In button was clicked.")
);
pdfcrowd.com
javafx.application.Application;
javafx.geometry.Insets;
javafx.geometry.Pos;
javafx.scene.*;
(1)
(2)
pdfcrowd.com
(3)
(4)
root.getChildren().addAll(userIdLbl, userIdTxt,
userPwdLbl, userPwdTxt);
(5)
(7)
pdfcrowd.com
(8)
(9)
pdfcrowd.com
}
public static void main(String[] args) {
launch(args);
}
}
1. This programs uses the GridPane layout with three rows and two
columns. Since the Sign In button will span two columns, I declared a final
variable TWO_COLUMN_SPAN that will be used when the button will be
added to the grid.
2. Then I instantiate labels and text fields.
3. After that I create an instance of the GridPane container.
4. To add the labels and text fields to the proper cells of the first two rows of
set so I add them as children to the root of the scene graph - the
GridPane .
6. Now I create the instance of the Sign In button and give it an id. This was
pdfcrowd.com
time you see so called method chaining. All these lines that starts with dots
are methods chained together - all of them are sequentially invoked on the
scene object.
9. Finally, the scene is added to the stage and the curtain goes up.
Some programmers prefer working GUI designer tools where they can drag
and drop components. Some prefer writing Java code for UI. I like the
declarative way of designing GUI components with FXML, because its just
more productive. The fact that FXML separates the screen design from the
application logic is great because even a person who doesnt know
programming (e.g. a UI designer) can master Scene Builder and create nice
GUI layouts allowing programmers to take care of application logic.
pdfcrowd.com
user pressed the mouse key and we need to know coordinates of the mouse
pointer), TouchEvent (the user touched the screen), WindowEvent (e.g.
the user is about to close the window) et al. For more detailed explanation of
JavaFX events visit Oracles tutorial about handling events at
http://docs.oracle.com/javafx/2/events/jfxpub-events.htm.
allowing to bind the GUI components with properties of other Java objects. If a
property on a Java object changes, the new value will be automatically
reflected on the appropriate GUI component and visa versa. Bi-directional
binding is available too, so no matter what changes - the GUI or the Java
object - the other party will be immediately notified.
Imagine that youre developing a multi-player game that has a Java object
receiving the moves of other gamers from a central server. When a Java object
receives a new move, you need to modify the content of the corresponding
GUI component of the game. With JavaFX you can simply bind a property of a
Java class that stores players moves (e.g. playersMove ) to the property of,
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
MVC stands for Mode View Controller. This design pattern recommends
separating the code that stores application data (Model) from the code
implementing the user interface (View) and from the code that controls the
data exchange and implements application logic (Controller). As a matter of
fact weve almost implemented MVC in one of the versions of the Sign In
application. The file signin.fxml was a view, and the class
Controller played a role of a controller. Since this example had just two
variables ( id and pwd ) we didnt create a special model class for them.
Observer design pattern is used to implement scenarios when one object,
a.k.a. the observer needs to watch changes in other object(s), the observables.
For example, if a Twitter user (the observable) posts a twit all of his followers
(observers) will get notified. If a programming language or a library supports
data binding, implementing the observer design pattern becomes pretty easy,
which youll see later in this chapter.
If youre interested in detailed coverage of design patterns, get the book
"Head First Design Patterns" published by OReilly Media.
one that allows only reading property values and the other one for read and
open in browser PRO version
pdfcrowd.com
writing (changing the values). For example, if you need a String property,
use either ReadOnlyStringWrapper or SimpleStringProperty .
Similarly named classes exist for other data types and some collections too.
As we always do in this book, lets learn by coding. Ill continue adding
features to our Sign In application. This time Ill add a Label component
with fx:id="errMsg" to the view in FXML file to display sign in error
messages, if any. In the controller class Ill add the corresponding variable
errMsg and will inject a reference to the Label into this variable.
Finally, Ill bind the label to the variable to insure that an error message is
immediately displayed on the screen as soon as its value changes.
Lets place an additional Label component at the bottom of the Sign In
window. Ill add another row to the GridPane and place a Label there that
will span two columns. This label will have fx:id="errMsg" and initially
wont have any text - itll be invisible. The <children> section of the
open in browser PRO version
pdfcrowd.com
Injecting a reference of the new label into controller and declaring a property
to store the error message will look like this:
@FXML private Label errMsg;
open in browser PRO version
pdfcrowd.com
The next question is when and where do the binding? If Id been creating an
instance of the Controller with the new operator I could have done it in
the class constructor after the GUI component was created. But JavaFX
runtime instantiates the Controller for us, so how can we catch the
moment when the GUI components are ready?
In JavaFX if youll add to the controller the method initialize annotated
with @FXML , FXMLLoader will invoke it after all GUI components are
constructed.
@FXML public void initialize() {
errMsg.textProperty().bind(signinError);
}
JavaFX properties are observables. So you can read the above code as follows:
"I want the text property of the label errMsg to be the observer (a.k.a.
listener) to the property signinError (observable). So whenever
signinError changes, the text property of the label will get the latest
open in browser PRO version
pdfcrowd.com
value."
To complete the Sign In example with the binding, the event handler for the
Sign In button should not only paint the wrong ID in light pink, but also
modify the value of the signinError property. The complete code of the
class BindableController is shown next.
public class BindingController {
@FXML
private TextField id;
@FXML
private PasswordField pwd;
@FXML private Label errMsg;
SimpleStringProperty signinError = new
SimpleStringProperty();
@FXML public void initialize() {
System.out.println("Controller's ready. Let's bind
some components");
errMsg.textProperty().bind(signinError);
open in browser PRO version
pdfcrowd.com
}
public void signInClicked(ActionEvent evt){
String userID = id.getText();
String password = pwd.getText();
if (!"Yakov".equals(userID)){
id.setStyle("-fx-background-color:
lightpink;");
signinError.set("Wrong id:" + userID);
} else{
id.setStyle("-fx-background-color: white;");
signinError.set("");
}
System.out.println("got id:" + userID + ", got
password: " + password);
System.out.println("Hello from signInClicked method
in controller");
}
}
Note that in the if statement I set the error message when the ID is wrong, and
reset the signinError to an empty string when the ID is correct. To test the
open in browser PRO version
pdfcrowd.com
program Ive entered Alex as the user ID and clicked the button Sign In.My
window looked like this:
Enter the right user ID, click on Sign In again, and the binding mechanism will
remove the error message from the window.
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
This code snippet has so-called try-catch block, which is required in some
cases for error handling. The next chapter explains the error processing subject
in details. But at this point lets just focus on the code located inside the curly
braces after the keyword try .
The method sleep of class Thread takes one argument - the sleeping time
open in browser PRO version
pdfcrowd.com
in milliseconds. There are 1000 milliseconds in one second, so the above code
snippet will place the current thread to sleep for 10 seconds.
Remember, the controller class has an event handler for the Sign In button? It
executes in the JavaFX application thread. Ill add the 10-second sleeping code
to the application thread to emulate the process that would perform the actual
sign in. Actually, this is wrong - you should execute the application logic in a
separate thread. But I do this on purpose to demonstrate the frozen effect.
The following code fragment from the new controller class shows how the
event handler signInClicked invokes the method named
wrongStartOfLongRunningProcess , which sleeps for 10 seconds and
pdfcrowd.com
}
private void wrongStartOfLongRunningProcess(String uID) {
try {
Thread.sleep(10000); // Sleep for 10 sec
} catch (InterruptedException interExp) {
interExp.printStackTrace();
}
if (!"Yakov".equals(uID)){
id.setStyle("-fx-background-color: lightpink;");
} else{
id.setStyle("-fx-background-color: white;");
}
}
When the user clicks on the Sign In button, the application thread will become
busy for 10 seconds, and only then checks the user ID and set the background
color of the TextField on the screen. If youll run the Sign In sample with
such event handler, the application window becomes frozen and unresponsive
for 10 seconds. If the user will try to reenter the ID, hell see a wait cursor. On
MAC OS computers such a cursor looks as a spinning wheel of death as shown
on Figure 8-7.
open in browser PRO version
pdfcrowd.com
Ten seconds later the application thread wakes up, and the GUI becomes
responsive again. Lets fix this code and create a separate thread emulating the
open in browser PRO version
pdfcrowd.com
long running process so that the application thread can continue working with
GUI. The following code listing shows the complete code of the class
ControllerLongRunningThread , which doesnt freeze the window.
public class ControllerLongRunningThread {
@FXML private TextField id;
@FXML private PasswordField pwd;
public void signInClicked(ActionEvent evt){
String userID = id.getText();
String password = pwd.getText();
rightStartOfLongRunningProcess(userID);
System.out.println("got id:" + userID +
", got password: " + password);
}
private void rightStartOfLongRunningProcess(String uID)
{
Runnable loginTask = () -> {
open in browser PRO version
pdfcrowd.com
(1)
try {
Thread.sleep(10000);
(2)
Platform.runLater(() -> {
(3)
if (!"Yakov".equals(uID)){
id.setStyle("-fx-background-color:
lightpink;");
} else{
id.setStyle("-fx-background-color: white;");
}
});
} catch (InterruptedException interExp) {
interExp.printStackTrace();
}
};
(4)
(5)
(6)
}
}
pdfcrowd.com
to the application thread to update the GUI. For that, JavaFX has a special
method runLater in the class Platform . The method runLater
will place the request to update the GUI into a special event queue of the
application thread.
4. End of the lambda expression declaration
5. Now we create the instance of the worker thread passing the lambda
expression to it.
6. The method start of the class Thread starts the execution of the
pdfcrowd.com
will be responsible for displaying the ping-pong table, while the other will
calculate coordinates of the ball and paddles.
this script. But what if everyone in your school wants to have your program
installed on their computers? Now if becomes a time-consuming task.
But the best way to prepare your JavaFX application for distribution is to
create a self-contain file signin.exe for Windows or signin.dmg for
MAC OS. This file will contain both the Java runtime and your application
code. This process is described in details in Oracles tutorial titled "Selfopen in browser PRO version
pdfcrowd.com
Contained Application Packaging. Im not going to repeat this tutorial here, but
will leave it for you as a self-study project.
Im sure many of you want to know if its possible to use JavaFX for writing
applications for smart phones. Oracle doesnt offer the JavaFX libraries for
mobile platforms, but its still possible.
To develop JavaFX applications for iOS, youd need to install and learn on
your own some additional software, namely RoboVM, which is an SDK for
converting Java bytecode into a native device code as if it was written in the C
programming language, which makes it deployable on iOS devices.
There is also a community site JavaFX Ports[ http://javafxports.org/page/home]
where people are working on the deployment of JavaFX applications on iOS
and Android devices.
pdfcrowd.com
you to integrate audio and video in your application, create special effects and
transitions to make your programs as cool and entertaining as you want them
to be. You may find some interesting capabilities by researching classes located
in the package javafx.animation .
Pick up a book on JavaFX 8 or later and experiment on your own. One of the
better books on the subject is "Pro JavaFX 8: A Definite Guide to Building
Desktop, Mobile, and Embedded Java Clients" published by Apress.
pdfcrowd.com
name of the class with the application logic. Use the code of
signing.fxml from this chapter as reference.
3. Create two separate event handler methods in the class
CalculatorController . Name the first method
digitClickedHandler - it will contain the code to process clicks on
handler method for each button using the attribute onAction as we did
in the Sign In example.
5. In each handler method add the code to recognize which button has been
clicked. You can do the label of the clicked button by querying the
ActionEvent object that will be provided for each event handler
pdfcrowd.com
6. If the user clicks the digit button, get the current value from the
calculators display field, concatenate the buttons label and assign the new
value back to the display field.
7. You need to declare a variable, say valueOne in the controller to store
the current value of the display field when the user clicks on the operation
button. For example, if the user clicked on the button with the label + , - ,
/ , or * , its a signal that the user finished entering the first number. Store
it in the variable valueOne and clear the display field so the user can
start entering the second number.
8. Declare a variable, say operation , to remember the operation that the
from the display field and perform the operation according to the value in
operation . Use the switch statement to perform different
operations.
10. After the operation is complete, assign the result to the display field by
pdfcrowd.com
pdfcrowd.com
For example, a Java class reads a file with the game scores. Whats going to
happen if someone will delete this file? Will the program crash with a scary
error message, or will it stay alive displaying a user friendly message like this
one: Dear friend, for some reason I could not read the file scores.txt. Please
make sure that the file exists? This is an example of a situation when Java
compiler wont be able to help - the Java syntax was written properly.
You should make your programs ready for unexpected situations. you should
foresee what might go wrong when the program will be running, and what to
do if something went wrong. In many programming languages the programmer
decides if he wants to add error processing code to a program. But in many
cases Java forces you to include error processing code, otherwise the programs
will not even compile.
Runtime errors in Java are called exceptions, and error processing is called
exception handling. You have to place code that may produce errors in socalled try/catch block. Its as if youre saying to JVM the following: Try
to read the file with scores, but if something happens, catch the error and
execute the code that will deal with it:
pdfcrowd.com
try{
fileScores.read();
}
catch (IOException ioe){
System.out.println(
"Dear friend,I could not read the file scores.txt"
+
ioe.getMessage());
}
The ioe in the above code fragment is a variable that represents the
IOException object given to the catch block by the Java runtime. You can
give this variable any name you like. The getMessage will return the text
describing what happened during the file read.
Well learn how to work with files in Chapter 11, but at this point Id like to
introduce a new term I/O or input/output. Read and write operations (from/to
disk or other device) are also known as I/O operations, and the class
IOException is a class that contains information about input/output errors.
pdfcrowd.com
and the program will jump into the catch block to execute the code located
there. The program will stay alive, and this exception is considered to be taken
care of.
The print statement from the code above will be executed only in case of a file
read error.
pdfcrowd.com
4
divideByZero();
5
}
6
7 int divideByZero()
8
{
9
return 25/0;
10 }
11
12 static void main(String[] args)
13 {
14
new TestStackTrace();
15 }
16 }
The output of this program shows the sequence of method calls that were made
up to the moment when the run-time error had happened. Start reading this
output from the last line going up.
Exception in thread "main"
java.lang.ArithmeticException: / by zero
at TestStackTrace.divideByZero(TestStackTrace.java:9)
at TestStackTrace.<init>(TestStackTrace.java:4)
at TestStackTrace.main(TestStackTrace.java:14)
pdfcrowd.com
This means that the program started in the method main , then went to
init , which is a constructor, and then called the method divideByZero .
The numbers 14, 4 and 9 show the program line numbers where these methods
were called. After that, an exception (an error) ArithmeticException
was thrown the line number nine tried to divide by zero.
pdfcrowd.com
pdfcrowd.com
Subclasses of the class Exception are called checked exceptions and you
must process them in your code.
Subclasses of the class Error are fatal JVM errors and the running program
cant handle them.
The TooManyBikesException is an example of an exception that can be
created by a programmer.
How is a programmer supposed to know in advance if some Java method may
throw an exception and that a try/catch block should be used? Not to
worry, if you call a method that may throw an exception, Java compiler will
print an error message similar to this one:
"ScoreReader.java": unreported exception:
java.io.IOException; must be caught or declared to be
thrown at line 57
pdfcrowd.com
After one try block you may put several catch blocks, if you believe that
more than one error may happen. For example, when a program tries to read a
file, the file may not be there, and youll get the
FileNotFoundException , or the file is there, but the code keeps reading
the file after reaching the end of file this generates EOFException . The
next code fragment will print messages in plain English if the program cant
find a file with game scores or reached the end of the file. For any other read
errors itll print the message Problem reading file and a technical description
of the error.
public void getScores(){
try{
fileScores.read();
System.out.println(Scores loaded successfully);
}catch(FileNotFoundException e){
System.out.println(Can not find file Scores);
}catch(EOFException e1){
open in browser PRO version
pdfcrowd.com
If the method read fails, the program jumps over the line println and
tries to land in the catch block that matches the error. If it finds such block,
the appropriate method println will be executed, but if the matching catch
block is not found, the method getScores will re-throw this exception to its
caller.
If you write several catch blocks, you may need to place them in a
particular order if these exceptions are inherited from each other. For example,
since the EOFException is a subclass of the IOException , you have to
put the catch block for the subclass first. If you would put the catch for
IOException first, the program would never reach the FileNotFound
pdfcrowd.com
file +
e.getMessage());
}
}
This is an example of a bad style of Java coding. When you write a program,
always remember that someone else may read it, and you dont want to be
ashamed of your code.
Catch blocks receive an instance of the object Exception that contains a
short explanation of a problem, and its method getMessage will return this
info. Sometimes, if the description of an error is not clear, try the method
toString instead:
catch(Exception e){
System.out.println(Problem reading file +
e.toString());
}
pdfcrowd.com
If you need more detailed information about the exception, use the method
printStackTrace . It will print the sequence of method calls that lead to
this exception similar to an example from the section Reading Stack Trace.
pdfcrowd.com
Imagine that the MySuperGame program invokes multiple methods that read
or write files and get some data from a remote server. We may want to process
all possible exceptions in one place the main method. In this case there is no
need to handle exceptions inside these methods (e.g. getAllScores ). We
could rather declare that these methods may throw exceptions. Since we are not
even trying to catch exceptions in getAllScores , the IOException
will be propagated from the getAllScores to its caller - the method
main . Now the main method has to handle this exception.
open in browser PRO version
pdfcrowd.com
The code in the try block throws an exception and control goes to the
matching catch block, which either handles the error and the method
execution continues, or it re-throws the exception to the caller of this
method.
If there is a piece of code that must be executed no matter what, put it under
open in browser PRO version
pdfcrowd.com
The code above has to close the file regardless of success or failure of the read
operation. Usually, you can find the code that releases some computer
resources in the block finally , for example, disconnection from a network
or file closing.
If you are not planning to handle exceptions in the current method, they will be
propagated to the caller. In this case, you can use the finally even without
a catch block:
void myMethod() throws IOException{
try{
// your code that reads a file goes here
open in browser PRO version
pdfcrowd.com
}
finally{
// your code that closes the file
}
goes here
pdfcrowd.com
invalid characters);
The constructor of any exception should get a message that describes the error
as an argument. When youll be invoking the getMessage method on the
exception object in the catch block, itll print the message that was given to the
constructor in the code that has thrown the exception.
pdfcrowd.com
In the next section Ill show you how create your own exception classes and
throw them with the throw keyword.
pdfcrowd.com
This class has only a constructor that takes the message describing this error
and passes it to the superclass of TooManyBikesException for reporting
the same way as Java runtime reports any other exception. When some
catch block receives this exception it can extract the message describing
Visualize a JavaFX GUI where the user selects several bicycles of some model
open in browser PRO version
pdfcrowd.com
and hits the button Place Order. As you know from Chapter 8, this action will
result in the call to the event handler method (e.g. placeOrder ) assigned to
the onAction property of the button. The event handler can apply some
business logic (e.g. call a method validateOrder ) to check if the order
can be delivered.
The next code fragment shows how the method placeOrder invokes
validateOrder , which can throw TooManyBikesException .
@FXML private ComboBox model;
@FXML private TextField quantity;
@FXML private Label txtFieldOrderConfirmation;
public void validateOrder(ActionEvent evt){
String selectedModel = model.getSelectionModel()
.getSelectedItem();
String selectedQuantity =
txtFieldQuantity.getText();
int quantity = Integer.parseInt(selectedQuantity);
try{
validateOrder(selectedModel, quantity);
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
If the order wont fit in the truck, the method validateOrder throws the
exception, the catch block in placeOrder intercepts it and displays an
error message in a text field on the window. When you throw custom
exceptions, provide a user-friendly message that clearly describes the error.
pdfcrowd.com
pdfcrowd.com
store. It should have GUI that allows the user to select a bicycle model (do a
little research and learn on your own how to use the JavaFX ComboBox for
this). You can find the description of the ComboBox component in Oracle
tutorial.
Use a TextField control for entering the quantity, a Button for placing
an order, and a Label to display either order confirmation or an error
message.
In the controller class use the code fragment from the section "Creating
Custom Exceptions".:toc-placement!::imagesdir: .
pdfcrowd.com
pdfcrowd.com
The content of this chapter is based on the materials covered in Chapter 7 and
8. While developing the game youll learn how to add menus, dynamically
change styling of GUI components and apply an animation effect.
pdfcrowd.com
pdfcrowd.com
}
}
Rename the generated package from sample into mygame. Inside the
tictactoe.fxml change the reference to controller to be
fx:controller="mygame.Controller" . Now youre ready to design
pdfcrowd.com
components to be located on the top of the window. Our game will have a
menu on top and a 3x3 grid of squares in the center of the window.
Lets delete the GridPane from the Hierarchy panel at the bottom left and
drag-drop the BorderPane there. The Scene Builders Window should look
like this:
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
the MenuBar component from the Controls panel onto Insert TOP line in
the BorderPane at the bottom left panel. Press a little plus sign to expand
the MenuBar in the Hierarchy panel. Youll see that itll have the default
menus named File, Edit and Help.
Were not going to edit anything in the TicTacToe game, so right-click on Edit
and select Delete option. Rename the menu File into Actions using the
open in browser PRO version
pdfcrowd.com
Properties panel of Scene Builder.The Menu File was created with the
MenuItem Close - rename it into Quit.
Now well add menu items to the menus Actions and Help. Drop a
MenuItem component from the panel Menu onto the menu Actions in the
pdfcrowd.com
Figure 83. The menu bar with 2 menus and 4 menu items
open in browser PRO version
pdfcrowd.com
Now drop a GridPane from the Containers panel onto the center of the
BorderPane. By default, Scene Builder creates a 2x3 grid. Right-click at the
column tab "1" and add a column to change the grid dimensions to be 3x3.
Change the preferred height of each row to 100 by selecting each row and
entering 100 in the Pref Height field on the right panel named Layout:
RowConstraints. This is what weve got so far:
Figure 84. The menu bar on top and the grid in center
pdfcrowd.com
Save this layout in Scene Builder and run the TicTacToe class in IDEA. Youll
see a window with a menu on top. The grid wont be visible yet, because it has
no content. Click on the menu Actions, and the window will look like this:
pdfcrowd.com
The grid has 9 cells and we want to add 9 buttons - each button will represent
a square on the Tic-Tac-Toe board. You can add the buttons to the grid in Scene
Builder as we did in the Calculator in Chapter 7. But itll be faster to do it
manually by editing the content of the file tictactoe.fxml in IDEAs editor.
Modify the content of this file to look as follows:
<?xml version="1.0" encoding="UTF-8"?>
<?import
<?import
<?import
<?import
java.lang.*?>
javafx.scene.control.*?>
javafx.scene.layout.*?>
javafx.scene.layout.BorderPane?>
<BorderPane xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="mygame.TicTacToeController">
<top>
<MenuBar BorderPane.alignment="CENTER">
open in browser PRO version
pdfcrowd.com
<menus>
<Menu text="Actions">
<items>
<MenuItem text="Play" />
<MenuItem text="Quit" />
</items>
</Menu>
<Menu text="Help">
<items>
<MenuItem text="About" />
<MenuItem text="How to play" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
<center>
<GridPane fx:id ="gameBoard"
BorderPane.alignment="CENTER">
<children>
<Button fx:id="b1" prefHeight="100.0"
prefWidth="100.0" />
<Button fx:id="b2" prefHeight="100.0"
prefWidth="100.0" GridPane.columnIndex="1" />
<Button fx:id="b3" prefHeight="100.0"
prefWidth="100.0" GridPane.columnIndex="2" />
<Button fx:id="b4" prefHeight="100.0"
open in browser PRO version
pdfcrowd.com
Note that each button has an id. Well need them while processing button
clicks in the controller class. Run the TicTacToe class and the window will
look pretty close to the final version of our Tic-Tac-Toe game.
pdfcrowd.com
pdfcrowd.com
Do yo see this thin border around the top left square? It occurs because by
default the firs grid cell has a focus, which means that this particular GUI
component is ready to receive input. But we dont want to suggest the player
starting the game from the top left corner, do we? We want to remove this little
border, and its time to create a special style for a button that will not show the
focus.
Lets create a new file named tictactoe.css. In IDEA, right click on the package
name mygame and use the menu File | New | File. Itll create an empty file.
Type the following in there:
.button{
-fx-focus-color: transparent;
-fx-background-insets: -1, 0, 1, 1;
}
From Chapter 7 you may remember that this means that every button in our
application will have these attributes. Web designers call the styles created for
certain types of GUI element type selectors. Hence the attributes defined in the
.button section of CSS will apply only for buttons. If we wanted to style
menus, wed need to add a section .menu to the CSS file. Labels would be
open in browser PRO version
pdfcrowd.com
that not everything works by the book. By doing a little more online research I
figured out that adding -fx-background-insets: -1, 0, 1, 1; is
needed too.
Dont be scared that not everything works as it should the first time around.
Luckily, each programming language has an online community of people who
are willing to share their findings and answer the questions of the rookies. One
of the best resources for asking questions and getting help is the Web site
StackOverflow.
Now we need to add a line to the main method of the TicTacToe class to load
the file tictactoe.css . We did something like this in Chapter 7 while
styling the Sign In application. Well also need to do small changes in the
main method to store the reference to a scene in a separate variable. We
also want to set fix the size of the game board by invoking setResizable(false);
on the stage object. After these modifications, the class TicTacToe will look
like this:
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
The GUI is ready. The name of the Java class that will play the role of the
controller was specified in the file tictactoe.fxml as
fx:controller="mygame.Controller" . Now lets program the
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
Great,the View communicates with the Controller! But the Xs and Os look
unproportionally small in these large squares. Besides, the gray color does not
look too exciting. Its time to add some styling to our GUI components.
pdfcrowd.com
If you run the TicTacToe program now and start clicking on buttons, the
game board will look like this:
pdfcrowd.com
pdfcrowd.com
As you can see, my artistic abilities are limited, but if you spend some time
learning CSS, you may come up with a much fancier game board than mine.
All JavaFX components are pre-styled, and the combination of the styles is
called theme. The default theme of all JavaFX components is called caspian.
By defining your own CSS rules you can override the defaults. Scene Builder
has a menu View | Show CSS analyzer, which allows you to see the default
styles of your GUI components. If youre interesting in learning more about
styling with Scene Builder, watch the video titled "In-Depth Layout and
Styling with the JavaFX Scene Builder".
pdfcrowd.com
Button
Button
Button
Button
Button
Button
Button
Button
b1;
b2;
b3;
b4;
b5;
b6;
b7;
b8;
pdfcrowd.com
Now lets write the method find3InARow that will methodically compare
the non-blank labels of the buttons in each row, column, and both diagonals. If
three labels are the same, the code should highlight the winning combination.
This is how the code in the method find3InARow will look:
private boolean find3InARow(){
//Row 1
if (""!=b1.getText() && b1.getText() ==
b2.getText()
&& b2.getText() == b3.getText()){
highlightWinningCombo(b1,b2,b3);
return true;
}
//Row 2
if (""!=b4.getText() && b4.getText() ==
b5.getText()
&& b5.getText() == b6.getText()){
highlightWinningCombo(b4,b5,b6);
return true;
}
open in browser PRO version
pdfcrowd.com
//Row 3
if (""!=b7.getText() && b7.getText() ==
b8.getText()
&& b8.getText() == b9.getText()){
highlightWinningCombo(b7,b8,b9);
return true;
}
//Column 1
if (""!=b1.getText() && b1.getText() ==
b4.getText()
&& b4.getText() == b7.getText()){
highlightWinningCombo(b1,b4,b7);
return true;
}
//Column 2
if (""!=b2.getText() && b2.getText() ==
b5.getText()
&& b5.getText() == b8.getText()){
highlightWinningCombo(b2,b5,b8);
return true;
}
//Column 3
if (""!=b3.getText() && b3.getText() ==
b6.getText()
&& b6.getText() == b9.getText()){
highlightWinningCombo(b3,b6,b9);
return true;
open in browser PRO version
pdfcrowd.com
}
//Diagonal 1
if (""!=b1.getText() && b1.getText() ==
b5.getText()
&& b5.getText() == b9.getText()){
highlightWinningCombo(b1,b5,b9);
return true;
}
//Diagonal 2
if (""!=b3.getText() && b3.getText() ==
b5.getText()
&& b5.getText() == b7.getText()){
highlightWinningCombo(b3,b5,b7);
return true;
}
return false;
}
If youll check the fx:id of each button in the file tictactoe.fxml, youll see
that the first row is represented by the buttons b1 , b2 , and b3 . The first
column is represented by the buttons b1 , b4 , and b7 . One diagonal
consists of the buttons b1 , b5 , and b9 . It should be pretty easy to read and
understand the code of the method find3InARow , isnt it? The method
highlightWinningCombo will get the references to the three winning
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
But embedding CSS rules in your Java program is not a good idea. What if
you decide to change the styling (e.g. to change the color from red to pink)?
You dont want to search for all the places in your Java code where this style
was used. Besides, changing the styles in the code would require to recompile
your Java program. Its much better to keep the style definitions in the CSS
file.
So far weve been using CSS type selectors that can change the style of the
specified component types. But CSS allows you to define and name a style
thats not intended for a specific component type and can be applied by name
to various components. In CSS such styles are called class selectors. Lets add
a style selector called .winning-square to the file tictactoe.css .
.winning-square {
-fx-text-fill: red;
-fx-background-color: radial-gradient( radius 100%,
white, lightyellow, lawngreen);
}
open in browser PRO version
pdfcrowd.com
The style selector .winning-square includes two style rules: one for
setting the buttons text color to red, and another to set the buttons background
color to radial gradient. Our Java program has to get a reference to the existing
styles of the button and add a .winning-square , which will override both
the text and the background color of the button.The method
highlightWinningCombo will look like this:
private void highlightWinningCombo(Button first, Button
second, Button third){
first.getStyleClass().add("winning-square");
second.getStyleClass().add("winning-square");
third.getStyleClass().add("winning-square");
}
Try playing the game after adding the methods find3InARow and
highlightWinningCombo to the class Controller . The winning
pdfcrowd.com
pdfcrowd.com
JavaFX includes various visual effects and transition based animations that can
make your GUI more fun to use.
To use the effect or animation you need to pick one from the package
javafx.scene.effect or javafx.animation respectively. Ill show
pdfcrowd.com
cycle, then reverses on the second cycle, and so on. The method play starts
the animation. Adding the following three lines to the method
highlightWinningCombo will play the animation on the
winningButton component.
applyFadeTransition(first);
applyFadeTransition(second);
applyFadeTransition(third);
The screen shot shown on Figure 10-12 should give you an idea of how the
end of the animation cycle will look like.
pdfcrowd.com
pdfcrowd.com
Compare this image with Figure 10-11, or better run the code that comes with
the book to see the animation in action.
When the user clicks on the menu Play, the controller needs to reset buttons'
labels to blank and remove styling from the winning buttons. Well do this by
getting a hold of all children of our GridPane and invoking the method
forEach passing a short lambda expression to it. This is what the method
menuClickHandler will look like:
open in browser PRO version
pdfcrowd.com
(1)
(2)
(3)
btn.getStyleClass().remove("winning-square");
(4)
});
isFirstPlayer = true;
(5)
}
}
1. This code processes just the clicks on the menu Play, but I included the if
statement to check the menu label in case you decided to implement other
menus too.
2. Were getting references to all children of the grid (the buttons) in one
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
place an O in the middle of the board. If the middle square is occupied, place a
O on the first blank button.
The method goComputer should be called from the method
buttonClickHandler right after the line that invokes the method
find3InARow .
pdfcrowd.com
pdfcrowd.com
All classes that can work with file streams are located in packages java.io
and java.nio . Classes from the java.io implement blocking I/O: When
bytes are being read/written, they become unavailable for other threads of
execution. This may not be an issue with small files like a history of game
scores, but may become an issue with large files that contain a gigabyte or
more. The package java.nio offers a set of classes with improved
performance as well as some useful utility classes.
Ill start with explaining the basics of working with streams of bytes using
classes from the java.io package, and then give you some examples of
working with classes from java.nio .
pdfcrowd.com
Open a stream that points at some data store e.g. a local or remote file.
Read or write data from/to this stream.
Close the stream (Java can do it automatically).
In the real world people use different types of pipes for carrying different
content (e.g. gas, oil, milkshakes). Similarly, Java programmers use different
classes depending on the type of data they need to carry over a stream. Some
streams are used for carrying text, some for bytes, et al.
pdfcrowd.com
time. If your program has to work only with text files, you could use the
classes Reader and Writer , which are specifically meant for reading
character streams.
After selecting, say FileInputStream youd be invoking one of its
methods to read the file data. For example the online documentation of the
class FileInputStream includes the method read having the following
signature:
public int read() throws IOException
This should tell you that the method read returns an integer value and may
throw the IOException , which is an error that may happen if the file is
corrupted or deleted, a device failure happened et al. Hence, you must enclose
the invocation of the method read into a try-catch block as explained in
Chapter 9. To get a specific reason for this exception youll call the method
getMessage on the exception object.
pdfcrowd.com
The next example shows how to use the class FileInputStream to read
the bytes from a file named abc.dat. This little program wont interpret the
meaning of each byte - itll just print their code values.
Ill start with creating a new Java project Chapter11 in IDEA. Then Ill create a
new empty file abc.dat in the root folder of the project (right-click on the
project name and select the menu New | File). Finally, Ill type the following
text in abc.dat:
This is a test file
Then Ill create a new Java class MyByteReader that will read and print the
content of the file abc.dat. But lets pretend that we dont know that the content
of this file is text - I want to read it byte by byte and print each bytes code
(not a letter) separated by a space character. The class MyByteReader will
look like this:
import java.io.FileInputStream;
import java.io.IOException;
public class MyByteReader {
public static void main(String[] args) {
open in browser PRO version
pdfcrowd.com
(3)
}
} catch (IOException ioe) {
(4)
System.out.println("Could not read file: " +
ioe.getMessage());
}
}
}
1. First we open the file for reading (using a default character set) by creating
pdfcrowd.com
This spares you from writing a finally block containing the code for
closing resources.
2. This line starts a while loop that calls the method read() , which
reads one byte, assigns its value to the variable byteCode , and
compares it with -1 (the end of file indicator).
3. If the value in the current byte is not equal to -1 , we print it followed by
Running this program prints the following numbers that represent encoding of
the text "This is a test file":
84 104 105 115 32 105 115 32 97 32 116 101 115 116 32 102
105 108 101
Writing bytes into a file works similarly, but youd use the class
FileOutputStream and its method write() as shown in the program
MyByteWriter below.
import java.io.FileOutputStream;
open in browser PRO version
pdfcrowd.com
import java.io.IOException;
public class MyByteWriter {
public static void main(String[] args) {
// Some byte values represented by integer codes
int someData[]= {56,230,123,43,11,37};
(1)
try (FileOutputStream myFile = new
FileOutputStream("xyz.dat")){
(2)
pdfcrowd.com
pdfcrowd.com
file into memory (a buffer) in one shot, and the FileInputStream object
then reads single bytes from there, which are fast memory-to-memory
operations. BufferedOutputStream works similarly with the class
FileOutputStream .
The main idea here is to minimize disk access.Buffered streams are not
changing the type of the original streams they just make reading more
efficient. A program performs stream chaining (or stream piping) to connect
streams, just as pipes are connected in plumbing.
open in browser PRO version
pdfcrowd.com
(1)
int byteValue;
while ((byteValue = buff.read()) != -1) { (2)
System.out.print(byteValue + " ");
}
} catch (IOException e) {
open in browser PRO version
pdfcrowd.com
e.printStackTrace();
}
}
}
argument. This is how we connect to fragments of the pipe that uses the
file abc.dat as the source of data.
2. Under the hood the BufferedInputReader reads bytes from the disk
in chunks into a memory buffer, and then the method read reads one
byte at time from memory.
The program MyBufferedByteReader produces the same output as
MyByteReader , but will work just a little bit faster.
pdfcrowd.com
and Japanese should use different character encodings. The names of some of
the standard character sets for English-speaking people are US-ASCII, UTF-8,
and UTF-16.
Each JVM has a default character set, which could be changed during the JVM
startup. You can also find out whats the default character in your Java
installation by invoking the method defaultCharset on the class
Charset , and Ill show you how to do it in the section "Reading Text Files".
only with default character encoding and dont handle localization properly.
For efficiency, the reading can be piped with the BufferedReader or
BufferedWriter , which read or write from/to the stream buffering
characters. Ill show you examples of working with text files in the next
section.
pdfcrowd.com
But first Id like to introduce the classes Path and Paths that will
represent a file youre planning to work with.
pdfcrowd.com
methods, and in particular, can build the Path object for you. For example,
you can invoke the method get passing the name of the file as the argument:
Path path = Paths.get("abc.dat");
Since we specified just the file name without a directory, the program will look
for the file in the current directory, which in IDEA is the directory of your
project (e.g. Chapter11). Outside of the IDE, the current directory is the one
where the program was started from.
But if we were to create a directory data at the root of our project and move
the file abc.dat there, then the relative path to the file starting from the project
root would look as "data/abc.dat" on Mac OS or
"data\\abc.dat" on Windows. Two backslashes in a Java string
pdfcrowd.com
or
/Users/mary/practicalJava/chapter11/data/abc.dat
If the file contains text, you can read the file into a String variable like this:
String myFileText = new
open in browser PRO version
pdfcrowd.com
String(Files.readAllBytes(Paths.get("abc.dat")));
If you want to read a text file into a collection, where each element contains
one line from the file use the method readAllLines .
List<String> myFileLines =
Files.readAllLines(Paths.get("abc.dat"));
efficient reading. Here I used the same file abc.dat located in the root directory
of our IDEA project Chapter11.
package niosamples;
import
import
import
import
import
open in browser PRO version
java.io.BufferedReader;
java.io.IOException;
java.nio.charset.Charset;
java.nio.charset.StandardCharsets;
java.nio.file.Files;
pdfcrowd.com
import java.nio.file.Path;
import java.nio.file.Paths;
public class MyTextFileReader {
public static void main(String[] args){
Path path = Paths.get("abc.dat");
(1)
System.out.println("The absolute path is " +
path.toAbsolutePath());
try {
if ( Files.exists(path)){
(2)
System.out.println("The file size is " +
Files.size(path));
}
BufferedReader bufferedReader=
(3)
Files.newBufferedReader(path,
StandardCharsets.UTF_8);
String currentLine;
while ((currentLine =
(4)
bufferedReader.readLine()) != null){
System.out.println(currentLine);
open in browser PRO version
pdfcrowd.com
}
} catch (IOException ioe) {
System.out.println("Can't read file: " +
ioe.getMessage());
}
System.out.println(
(5)
"Your default character encoding is " +
Charset.defaultCharset());
}
}
1. The program starts with creating a Path object from abc.dat and printing
bytes.
3. Here were opening the buffered reader capable of reading text encoded
pdfcrowd.com
Now experiment to see if the IOException is thrown if the file is not found
where it is expected to be. Just move the file abc.dat into a different directory
and re-run MyTextFileReader . Now the console output looks different:
Can't read file: abc.dat
Your default character encoding is UTF-8
pdfcrowd.com
the Path object. If you want to write bytes, create a byte array, populate it
with data and call the method write on the class Files . If you want to
write some text into a file, just convert the text from a String into a byte
array and then call the method write , for example:
Path path = Paths.get("data/scores.txt");
Files.write(path, myScore.getBytes(),
StandardOpenOption.APPEND);
When your program opens a file for writing, you need to consider different
options. For example, you may want to append text to an existing file, hence
the above code snippet passes the argument
StandardOpenOption.APPEND to method write . If you want to
create a file from scratch every time you run the program, use the option
StandardOpenOption.CREATE .
pdfcrowd.com
import
import
import
import
import
import
java.io.IOException;
java.nio.file.Files;
java.nio.file.Path;
java.nio.file.Paths;
java.nio.file.StandardOpenOption;
java.time.LocalDateTime;
pdfcrowd.com
StandardOpenOption.CREATE);
}
System.out.println("The game score was saved at "
+ path.toAbsolutePath());
} catch (IOException ioe) {
System.out.println("Can't write file: "
+ ioe.getMessage());
}
}
}
1. For illustration purposes I want the program to print its current directory,
concatenate the current date and time followed by \n , which is the end of
line marker.
3. Creating a Path object pointing at the file score.txt .
4. Check if the file score.txt already exists, append the new content to
it. If the file doesnt exists create it and write the content there.
The program MyTextFileWriter printed the following on my console:
open in browser PRO version
pdfcrowd.com
Each time the program saved the same score of 28000attaching the system date
and time. Of course, you could calculate and write the real score of a game.
This is a simple way of printing the local date and time. The time portion goes
after the letter "T" and shows hours, minutes, seconds, and nanoseconds. In the
Java package java.time you can find multiple classes and methods
providing formatting date and time for pretty printing. Go through Oracles
tutorial on working with Date and Time API if youre interested.
For writing small files like scores.txt you dont need to use buffered streams.
For large files though, use BufferedWriter, for example:
open in browser PRO version
pdfcrowd.com
java.io.BufferedWriter;
java.io.IOException;
java.nio.charset.StandardCharsets;
java.nio.file.Files;
java.nio.file.Path;
java.nio.file.Paths;
java.nio.file.StandardOpenOption;
java.time.LocalDateTime;
pdfcrowd.com
pdfcrowd.com
return Files.newBufferedWriter(path,
StandardOpenOption.CREATE);
}
}
}
In this class Ive moved the code that checks if the file exists into a separate
method getBufferedWriter . I did it to illustrate so-called factory design
pattern. A factory can build different objects, right? The method
getBufferedWriter also builds different instances of a
BufferedReader depending on the existence of the file referred by
path . In programmers jargon, the methods that create and return different
pdfcrowd.com
So far all of the code examples had the file names stored right in the code, or
as programmers say, hard-coded in the program. This means that to create a
program that reads a file with a different name youd have to modify the code
and recompile the program, which is not nice. You should create universal
programs that can take parameters (e.g.the name of the file) from a command
line during the program launch.
In the first lesson of this book youve been running the program HelloWorld
from a command window:
java HelloWorld
But youre allowed to add command-line arguments right after the name of the
program, for example,
java HelloWorld Mary Smith
In this case, the program HelloWorld would get two command line
parameters: Mary and Smith. If you remember, we always write the method
main with a String array as an argument:
open in browser PRO version
pdfcrowd.com
The JVM passes the String array to the main method, and if you start a
program without any command line arguments, this array remains empty.
Otherwise, this array will have exactly as many elements as the number of
command-line arguments passed to the program.
Lets see how we can use these command line arguments in a very simple class
that will just print them:
public class PrintArguments {
public static void main(String[] args) {
// How many arguments we've got?
int numberOfArgs = args.length;
for (int i=0; i<numberOfArgs; i++){
System.out.println("I've got " + args[i]);
}
}
}
pdfcrowd.com
This program loops through the array args and prints the arguments received
from the command line, if any. Run this program from the Command (or
Terminal) Window as follows:
java PrintArguments Mary Smith 123.5
The JVM placed Mary into the array element args[0] , Smith into
args[1] , and 123 into args[2] .
pdfcrowd.com
Its always a good idea to check if the command line contains the correct
number of arguments. Check this right in the beginning of the method main .
If the program doesnt receive expected arguments, it should print a brief
message about it and immediately stop by using a special method exit of the
class System :
public static void main(String[] args) {
if (args.length != 3){
System.out.println(
"Please provide arguments, for example:");
System.out.println("java PrintArguments Mary Smith
123");
// Exit the program
System.exit(0);
}
}
You can test your programs that take command-line arguments without leaving
IntelliJ IDEA. Just open the menu Run, select Edit Configurations and enter the
values in the field Program arguments as shown below:
pdfcrowd.com
Now lets write a program to copy files. To make this program working with
any files, the names of the original and destination files have to be passed to
this program as command-line arguments.
import
import
import
import
open in browser PRO version
java.io.IOException;
java.nio.file.Files;
java.nio.file.Path;
java.nio.file.Paths;
pdfcrowd.com
pdfcrowd.com
The file copy is done by calling the method copy on the class Files . This
program will work fine as long as the destination file doesnt exist. You can
check for the files existence in the program by using the method exists of
the class Files as it was done in the class MyTextFileReader earlier.
pdfcrowd.com
the player launches the game again, the program should load the saved state
and recreate the situation on the board. Creating a Java class with fields like
player name, level, score, and lives can be a good way to represent a state of
the game.
class GameState {
String playerName;
int level;
int score;
int remainingLives;
// other fields go here
}
When the user selects the menu option Save Game State, the program has to
create an instance of the object GameState , assign the values to its fields
and save these values in a file. But which format to save these values in?
Create a String variable, and concatenate all these values into it separating
the values with commas? Its a lot of work. Also, youd need to remember the
order of these concatenated values so that when you need to read them you
know which fields of the object GameState to assign them to.
pdfcrowd.com
Luckily, Java greatly simplifies this process. You can create an instance of the
Java object, populate it with the values, and then serialize this instance into a
bunch of bytes in a special format that remembers the structure of the class
GameState . Accordingly, when you need to re-create the instance of the
GameState for these bytes, you can deserialize the object in one shot with
(1)
(2)
pdfcrowd.com
(3)
1. The GameState class has four fields that describe the current state of
the game.
2. The class constructor populates these fields with the values passed as
arguments.
3. We override the method toString to be able to print the content of the
pdfcrowd.com
method writeObject .
To deserialize (to read back) a Java object you need to create an instance of
InputStream , pipe it with ObjectInputStream , and invoke a method
readObject .
pdfcrowd.com
java.io.IOException;
java.io.ObjectInputStream;
java.io.ObjectOutputStream;
java.nio.file.Files;
java.nio.file.Path;
java.nio.file.Paths;
java.nio.file.StandardOpenOption;
(3)
(4)
pdfcrowd.com
loadGameState(path);
System.out.println("Deserialized game state; " +
deserializedGameState);
}
// Serialize the gameState into a file
private static void saveGameState(Path path,
(5)
GameState gameState) {
try (ObjectOutputStream whereToWrite =
(6)
new ObjectOutputStream(Files.newOutputStream(
path, StandardOpenOption.CREATE))){
whereToWrite.writeObject(gameState);
(7)
(8)
pdfcrowd.com
new
ObjectInputStream(Files.newInputStream(path))){
loadedGameState= (GameState)
whereToReadFrom.readObject();
(9)
} catch (ClassNotFoundException cnfe) {
System.out.println("Can't find the declaration
of GameState: " + cnfe.getMessage());
} catch (IOException ioe) {
System.out.println("Can't deserialize file: " +
ioe.getMessage());
}
return loadedGameState;
}
}
1. The program starts with creating and populating the game state object. In
this example I used hard-coded values, but in a real game they should be
taken from the variables that reflect the actual game status.
2. The serialized files name is gamestate.ser and itll be represented
pdfcrowd.com
takes two parameters - the path to the file and the reference to the object
that has to be serialized.
6. Now were opening the files OutputStream and pipe it up with the
ObjectOutputStream .
7. It takes just one line of code to serialize the GameState object into the
format and order as it was written. So if you change the declaration of the
class GameState between serialization and deserialization, Java will
throw InvalidClassException .
9. It takes just one line of code to deserialize the file into a GameState
object using the method read . In this example the same program
open in browser PRO version
pdfcrowd.com
serializes and deserializes the game state, but this may not be the case. You
can send the serialized object to another computer on the network, and
another program may deserialize the GameState . Hence its important
that the declaration of the GameState is available on both computers.
The exception ClassNotFoundException will be thrown if the
declaration of the class GameState is not available.
Run the program GameStateManager , and youll see that it creates a new
file gamestate.ser . Open this file in a text editor, and youll see some
gibberish. Java serializes objects in its internal format, which is not meant to
be read by people. The console output will look like this:
The GameStateObject is serialized
Deserialized the game state
Deserialized game state object; PlayerName: Mary,
level:0, score: 28000, remainingLives: 3
pdfcrowd.com
Note how IDEA conveniently shows the values of the variables not only in the
debuggers view at the bottom but in the source code of the program in grayed
out font.
pdfcrowd.com
While comparing two numbers is easy, Java objects may include multiple
fields and you need to decide which fields of the object should be compared to
place objects in a certain order. In this assignment youll be ordering objects
Score so the objects with larger value of the field score should come
first. In other words, youll need to sort the objects Score in the descending
order of the field score .
1. Create a serializable class Score to represent a game score.
import java.io.Serializable;
import java.time.LocalDateTime;
class Score implements Serializable {
String name;
int score;
LocalDateTime dateTime;
Score(String name, int score, LocalDateTime
dateTime){
this.name=name;
this.score=score;
this.dateTime=dateTime;
}
public String toString(){
open in browser PRO version
pdfcrowd.com
The class ArrayList is one of the Java collections that implements the
List interface, so declaring this variable of type List is valid.
3. Add the methods saveScores and loadScores to the class
ScoreManager :
private static void saveScores(Path path, List<Score>
gameScores) {}
private static List<Score> loadScores(Path path){}
open in browser PRO version
pdfcrowd.com
serialize not one object instance, but a collection of objects, for example:
try (ObjectOutputStream whereToWrite = new
ObjectOutputStream(
Files.newOutputStream(path,
StandardOpenOption.CREATE))){
whereToWrite.writeObject(gameScores);
} catch (IOException ioe) {
System.out.println("Can't serialize scores: " +
ioe.getMessage());
}
5. Write the code in the method loadScores to deserialize the data from
pdfcrowd.com
ObjectInputStream(Files.newInputStream(path))){
loadedScores=
(List<Score>) whereToReadFrom.readObject();
} catch (ClassNotFoundException cnfe) {
System.out.println("Can't find the declaration of
Score: " + cnfe.getMessage());
} catch (IOException ioe) {
System.out.println("Can't deserialize file: " +
ioe.getMessage());
}
return loadedScores;
6. Starting from this step all coding should be done in the main method of
ScoreManager . If the file scores.ser already exists, load the collection
pdfcrowd.com
8. Print all the scores and invoke the method saveScore to serialize all
scores into the file.
System.out.println("All scores:");
scores.forEach(s -> System.out.println(s));
saveScores(path, scores);
pdfcrowd.com
9. Sort and print the collection to show the highest score on top. Use the class
Comarator to specify that sorting should be done by the field score .
10. Run the program ScoreManager and observe that all scores are printed
in descending order.:toc-placement!::imagesdir: .
pdfcrowd.com
pdfcrowd.com
response headers can add several hundred bytes to the actual data being sent.
Some other popular networking protocols are TCP/IP, FTP, WebSocket. In this
chapter youll learn how to write Java programs that can connect to remote
servers and download data using HTTP protocol.
This URL tells me that the host (the server) nick.com has the file called
nickelodeon-football-stars.html located in the folder games. The port number
plays the same role as an apartment number in a building.
open in browser PRO version
pdfcrowd.com
The server nick.com can run many programs, which serve users' requests, but
we want to enter this server through "the door" number 80. As a matter of fact,
the port number 80 is a default port number for all Web servers that use HTTP.
Thats why if you skip the port number, your Web browser will try to connect
to the Web server via the port 80.
If a URL starts with https, the s stands for "secure". All requests and responses
are automatically encrypted by the browser and the server for additional
security. If the user enters a URL that starts with https and has no port number,
the Web browser sends an HTTPS request to the servers port 443.
Now lets dissect another URL from Nickelodeon.
There is no file name here. What does video stand for in this URL? Its not a
file, and its not a folder on the host either. Its just an ID that represents some
resources at nick.com. There is a program running at nick.com that understands
what this ID means and redirects the request to the application that serves the
open in browser PRO version
pdfcrowd.com
Often the content that corresponds to a resource ID is not stored in a file, but is
generated on the fly by a server-side program and can change daily, hourly,
every minute or every second. Most likely by the time you enter
http://www.nick.com/videos in your browser the content will be different.
pdfcrowd.com
The name of the server (the host name) must be unique, and when a person or
an organization registers a Web site, a unique number is assigned to this
physical server. This number is called an IP address. The IP address is either a
group of four numbers (e.g. 122.65.98.11) or up to eight hexadecimal numbers
(e.g. 2001:cdba:0000:0000:0000:0000:3257:9652). Remembering these long
numbers would be difficult for people hence why were using domain names
that are easier to remember (e.g. nick.com or google.com).
When youre entering a domain name in the browser, your Internet service
provider uses special software to find the IP address that corresponds to the
entered domain name. If found, your browser receives the requested Web page,
which is a document in HTML format. If not found, youll get an error
message that your search didnt match any documents.
You can say,"But entering nick.com shows a lot of content even without
providing any document name!" This happens because Web sites creators
configure their servers to serve a certain HTML file if the user doesnt specify
any. Often they name the file with the home page content index.html, but it can
be any other file too.
Most people connected to the Internet are getting dynamic (temporary) IP
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
While writing code for reading streams over the network, youll have to handle
possible I/O exceptions the same way you did while reading the local files in
Chapter 11.The following program WebSiteReader reads and prints the
code of google.com page.
import
import
import
import
import
import
java.io.BufferedReader;
java.io.IOException;
java.io.InputStreamReader;
java.net.MalformedURLException;
java.net.URL;
java.net.URLConnection;
= new URL("http://www.google.com" );
urlConn = url.openConnection();
open in browser PRO version
(1)
(2)
pdfcrowd.com
pdfcrowd.com
"+
ioe.toString());
}
}
}
Make sure your computer is connected to the Internet before you run the
WebSiteReader program. Actually, I was writing this program while
sitting on the plane without the Internet connection. This is what the program
printed up in the sky:
Can't read from the Internet:
java.net.UnknownHostException: www.google.com
open in browser PRO version
pdfcrowd.com
When my computer got the Internet connection the output was different. Heres
a fragment of what you can expect to see on the console after running
WebSiteReader :
<!doctype html><html itemscope=""
itemtype="http://schema.org/WebPage"
lang="fr"><head><meta content="/logos/doodles/2015/110thanniversary-of-first-publication-of-becassine5701649318281216-hp.jpg"
itemprop="image"><title>Google</title><script>(function()
{window.google={kEI:'5OzPVMyJM4ukygPRz4CoBQ',kEXPI:'40115
59,4013606,4020347,4020562,4021598,4022545,4023678,402459
9,4024626,4025090,4027899,4027921,4028062,4028128,4028367
,4028508,4028634,4028706,4028717,8300111,8500393,8500852,
8501081,8501084,10200083,10200903,10200904',authuser:0,kS
ID:'5OzPVMyJM4ukygPRz4CoBQ'};google.kHL='us';})();(functi
on(){google.lc=[];google.li=0;google.getEI=function(a){fo
r(var
b;a&&(!a.getAttribute||!(b=a.getAttribute("eid")));)a=a.p
arentNode;return b
pdfcrowd.com
The reason you may want use the URLConnection class is that it could
give you some additional control over the I/O process. For example, by calling
its method setDoOutput with the argument true you enable
WebSiteReader to write to the remote URL . In this case youd need to get
you could have saved the data in the local file as well. Its time to add the code
that writes into a file. The goal is to write a program that can download any
open in browser PRO version
pdfcrowd.com
unprotected file (such as images, music, and binary files) available on the Web.
pdfcrowd.com
java.io.OutputStream;
java.io.IOException;
java.io.InputStream;
java.net.URL;
java.net.URLConnection;
java.nio.file.Path;
java.nio.file.Paths;
class FileDownload{
public static void main(String args[]){
if (args.length != 2){
(1)
System.out.println(
"Proper Usage: java FileDownload FileURL
DestinationFileName");
System.out.println(
"For example: java FileDownload
http://myflex.org/yf/nyc.jpg nyc.jpg");
System.exit(-1);
}
pdfcrowd.com
URLConnection fileStream=null;
try{
URL remoteFile=new URL(args[0]);
(2)
fileStream=remoteFile.openConnection(); (3)
} catch (IOException ioe){
ioe.printStackTrace();
}
Path path = Paths.get(args[1]);
(4)
try(OutputStream fOut=Files.newOutputStream(path);
(5)
InputStream in = fileStream.getInputStream();){ (6)
System.out.println("Downloading from " + args[0] +
". Please wait...");
// Read a remote file and save it in the local one
int data;
while((data=in.read())!=-1){
fOut.write(data);
open in browser PRO version
(7)
(8)
pdfcrowd.com
}
System.out.println("Finished downloading the file.
It's located at "+path.toAbsolutePath());
} catch (Exception e){
e.printStackTrace();
}
}
}
provided. If not, it prints the message showing the right way to start
FileDownload and exits the program by invoking the method exit
pdfcrowd.com
The FileDowload program has downloaded the photo and saved it the file
nyc.jpg.This program has no knowledge of what type of data it has
downloaded - it was simply reading and writing the data byte after byte. In this
case it was an image, but the same program can be used for downloading audio
and other files thats has open access to the public.
open in browser PRO version
pdfcrowd.com
If youll open the downloaded file with a program that can show images, youll
see the following photo:
pdfcrowd.com
In this chapter Ive shown you how to download a file using HTTP.
Professional Java developers use various techniques, technologies, and
protocols for working with remote content. If youre interested in exploring
these advanced topics on your own, the Java EE Tutorial is a good start. Maybe
one day Ill write a book about the server side programming for kids.
pdfcrowd.com
pick an MP3 you like. At the time of this writing the Last.FM Web page
looked as follows:
pdfcrowd.com
2. Right-click on the blue button "Free MP3", and youll see a browsers
popup menu. Select the menu item that allows you to copy the link
open in browser PRO version
pdfcrowd.com
3. In IDEA, select the menu Run | Edit Configuration and paste this link into
the Program arguments field for the FileDownload program. This link
will be the first command-line argument.
pdfcrowd.com
4. Move the cursor to the very end of the Program arguments field and add a
space followed by the name of the local file, where you want to save the
song. Ive entered song1.mp3. Then press the button OK.
5. Run the program FileDownload . The MP3 file will be downloaded
into the local file song1.mp3. Heres the console output Ive got:
Downloading from
http://freedownloads.last.fm/download/59565166/From%2B
Embrace%2BTo%2BEmbrace.mp3. Please wait...
Finished downloading the file. It's located at
/Users/yfain11/IdeaProjects/jfk/Chapter12/song1.mp3
6. Open this file in your MP3 player and enjoy the music!
7. Close IDEA and repeat the same exercise from the command line. Youll
pdfcrowd.com
on/Chapter12
8. Run the FileDownload program providing the URL and the name of
the local file as command-line arguments. It should download the file the
same way as it did in the IDEA IDE.
pdfcrowd.com
should be painted green, and the left paddle should be painted blue - itll
be controlled by the Computer. The right paddle should be yellow - itll be
controlled by the Kid. Initially the red ball should be located in the center
of the table.
2. A new game starts when a player presses the N-key on the keyboard,
pressing Q will end the game, and the S-key will serve the ball. Only the
kid can serve the ball.
3. The Kids paddle movements should be controlled by the Up and Down
arrow keys. Pressing the key once should move the paddle vertically by the
preset number of pixels up or down. The paddle shouldnt cross the table
borders.
4. The Kid can move the right paddle and press the S-key. This should serve
the ball from the position where the right paddle is located. The ball can
move at an angle, which means that its x and y coordinates should change
while moving. If the ball crosses the top or bottom borders of the table, the
open in browser PRO version
pdfcrowd.com
right. When the Computer bounces the ball, it can move only horizontally
to the right.
7. If the ball contacts the Kids paddle in the upper half of the table, the ball
should be moving in the up-and-left direction. If the ball was located in the
bottom part of the table, it should move in the down-and-left direction.The
game lasts until one of the players reaches the score of 21. Since the
computer cant serve the ball, the Kid should score a point if the ball
crosses the left border of the table. If the ball crosses the top orbottom table
borders the point is given to the computer.The computer can also earn the
point if it bounces the ball and it crosses the right border of the table.
These rules are not the same as in a real Ping-Pong game, but they are
good enough for our game.
8. The game score should be displayed in the bottom left corner of the table.
pdfcrowd.com
to break the complicated problem into a set of smaller and simpler tasks. The
ability to do so is called analytical thinking, and it helps not only in
programming, but everywhere in your life. Do not get frustrated if you cant
achieve a big goal, split it in a set of the smaller ones and reach them one at
time!
Lets start breaking our complex task. Try to visualize a ping-pong table. Can
you write a program that will draw a green rectangle? Thats our first goal to
achieve. Then well add the paddle. Then well see how to draw the ball.
Learning how to move the ball will be the next task. Writing the keyboard
event handlers shouldnt be too difficult.
Now lets implement each step from the game strategy, one step at a time.
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
Im not going to use any layouts in the PingPong game. The game will consist
of a number of shapes that Ill keep in the Group container. We havent use it
yet - the Group is used just to keep several child components together.
Grouping components in a container can come in handy if you need to assign
one event handler to all child components or auto-resize all of them as a group.
In Scene Builder delete the GridBag container and drag/drop the Group
from the Miscellaneous section down to the Hierarchy panel. Then drag/drop a
Rectangle from the Shapes panel onto the Group . Resize it and pick a
nice green color from the Fill property on the right side. Youll be picking a
color from a dropdown palette, and the corresponding color code will be
automatically inserted as a fill property of the Rectangle . Your Scene
Builder should look like this:
open in browser PRO version
pdfcrowd.com
Open the file pingpong.fxml and youll see the tag <Rectangle> inside the
<Group> generated by Scene Builder. Set the width of the Rectangle to
javafx.scene.shape.*?>
javafx.scene.*?>
java.lang.*?>
javafx.scene.layout.*?>
javafx.geometry.Insets?>
javafx.scene.layout.GridPane?>
pdfcrowd.com
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<Group xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1">
<children>
<Rectangle arcHeight="5.0" arcWidth="5.0"
fill="#31b287" height="250" stroke="BLACK"
strokeType="INSIDE" width="400" />
</children>
</Group>
Every rectangle has the x and y properties that define the coordinates of its
upper left corner inside the container. By default, the values of x and y are
zeros, so this rectangle will be drawn starting from the upper left corner of the
Group container.
If youre interested in learning how different properties change the look of the
rectangle, visit the online documentation for this class. Keep in mind that some
of the properties are defined in the class Shape , the ancestor of the
open in browser PRO version
pdfcrowd.com
Rectangle .
There are a couple of things that I dont like here. First, the corners of the
rectangle are rounded just a little bit. This is caused by the properties
open in browser PRO version
pdfcrowd.com
of corner arcs. Ill delete them from the table rectangle in pingpong.fxml .
Second, the window has a title Hello World set by the auto-generated code in
IntelliJ IDEA. Its easy to change in the class PingPong , but I dont even
want to see a title bar!
This is also an easy fix in JavaFX. Setting the stage style to UNDECORATED
will remove the standard window title and borders. But if Ill remove the title
bar, Ill lose the ability to close the window by clicking on the circle (or a little
cross in Windows). A bit later well write the code to close the window by
pressing the Q-key on the keyboard. At this point the code of the PingPong
class looks like this:
package pong;
import
import
import
import
import
import
javafx.application.Application;
javafx.fxml.FXMLLoader;
javafx.scene.Parent;
javafx.scene.Scene;
javafx.stage.Stage;
javafx.stage.StageStyle;
pdfcrowd.com
This class was generated by IDEA, but Ive removed the Hello World title, set
the size of the scene to 400 by 250 pixels, and added the line
primaryStage.initStyle(StageStyle.UNDECORATED); .
Running the PingPong class will display the following green rectangle:
pdfcrowd.com
Now lets open pingpong.fxml in Scene Builder again and add the paddles and
the ball on top of the table. For paddles, Ill drag/drop two Rectangle
objects from the Shapes section onto the Group container. Our paddles will
have a size of 10 by 50 pixels. The left paddle will be blue, and the right one
will be yellow. Then I drag/drop, resize and color the Circle to set its radius
to 9 pixels, and then will paint it red. My Scene Builder will look like this:
pdfcrowd.com
Now back to IDEA. Since our shapes will need to communicate with the
controller class, we need to assign an fx:id to each of them. Lets assign the
fx:id="theGroup" to the Group container. Our green Rectangle
pdfcrowd.com
Running the PingPong program will display the following ping-pong table:
open in browser PRO version
pdfcrowd.com
The GUI drawing is complete, now we need to take care of the user
interactions, which will be done in the class PingPongController . In
pingpong.fxml we need to assign this class as the fx:controller to the
Group (see Chapter 8 for a refresher):
<Group fx:id="theGroup"
fx:controller="pong.PingPongController"
xmlns="http://javafx.com/javafx/8"
open in browser PRO version
pdfcrowd.com
xmlns:fx="http://javafx.com/fxml/1">
Dear Scene Builder and FXML, youve been very helpful. Now Im happily
going back to Java programming.
keyboard has a special code assigned, and our first goal is to figure out which
key the player pressed.
For processing keyboard events JavaFX components have special event
handler properties onKeyPressed , onKeyReleased , and
onKeyTyped . The first two properties allow you to program different
pdfcrowd.com
IDEA can help you find out which event handlers can be
NOTE
When the user releases a key, the onKeyReleased method handler receives
the KeyEvent object as an argument. The method getCode from the class
KeyEvent returns the KeyCode object that represents the key pressed. For
example, if you press the button Q, the getCode will return Q . If you press
the arrow up, the getCode will return UP .
But the same key can result in displaying more than one character (e.g. Q or q)
The method getText of KeyEvent returns a String that represents the
character typed by the user.
To enable our GUI to react on keyboard events right after the program starts,
we need to set the focus on the GUI. This was not required when we clicked on
the GUI components with the mouse, but now we wont even touch the screen.
To set the focus to the Group container well need to do two things:
1. Enable the Group to receive the focus by useing the attribute
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
starting comment in each class briefly describes what was added in this
version of the controller. To see any of these controllers in action, just specify
its name as fx:controller in the file pingpong.fxml and run the
PingPong program.
In InelliJ IDEA you can easily compare two files to see the
difference. Press CTRL or CMD button and click on the
names of two files youd like to compare (e.g.
NOTE
PingPongController_v1 and
PingPongController_v2 ). Then select the menu View
| Compare Two Files, and youll see the source code of these
files next to each other with highlighted differences.
Lets add to the PingPongControler a method handler for the keyreleased events. The first very simple version of the PingPongControler
is shown next. The goal is to see that the controller receives the keyboard
open in browser PRO version
pdfcrowd.com
The event handler method just extracts the key code from the KeyEvent
object provided by the Java runtime and prints it.For example, after running the
PingPong class and pressing the up and down arrows, n, q, and s keys, the
pdfcrowd.com
You pressed N
You pressed Q
You pressed S
The following class GreetTheDay illustrates the use of the enum Day :
public class GreetTheDay {
pdfcrowd.com
pdfcrowd.com
If youll open the online documentation for KeyCode youll find there the
declarations of all possible keyboard keys.
pdfcrowd.com
break;
case DOWN:
process_key_Down();
break;
case N:
process_key_N();
break;
case Q:
Platform.exit(); // Terminate the app
break;
case S:
process_key_S();
break;
}
}
private void process_key_Up() {
System.out.println("Processing the Up key");
}
private void process_key_Down() {
System.out.println("Processing the Down key");
}
private void process_key_N() {
System.out.println("Processing the N key");
}
open in browser PRO version
pdfcrowd.com
The switch statement checks the value of enum KeyCode and calls the
corresponding method which just prints a hard-coded message. Well
implement them shortly, but the Q-key in the above PingPongController
is fully functional. When the user presses the Q-key, the program invokes the
method exit on the class Platform , which terminates the program.
pdfcrowd.com
Pressing the key once will change the vertical position of the paddle by 7
pixels. Seven is not a magical number, and you can use any other integer here.
The new version of the controller will use the @FXML annotations to inject the
references to the GUI components. To update the position of the kids paddle
on the GUI well use data binding explained in Chapter 8. Well also add the
method initialize that is invoked by the Java runtime once when the
controller object is created. Finally, well write the code in the methods
process_key_Down and process_key_Up to move the kids paddle
vertically.
In JavaFX the x and y coordinates of the top left corner of the stage have zero
values. x-coordinate increases from left to right, and the y-coordinate increases
from top to bottom. The following image shows how x and y coordinates
change if a ping-pong table has the width of 400 pixels and the height of 250:
pdfcrowd.com
In our game the paddles can move only up or down, so depending on the key
pressed well be changing the value of the property layoutY of the right
paddle, which will move it on stage accordingly. Heres how the
PingPongController will look now:
package pong;
import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
open in browser PRO version
pdfcrowd.com
import
import
import
import
import
import
javafx.beans.property.SimpleDoubleProperty;
javafx.fxml.FXML;
javafx.scene.input.KeyCode;
javafx.scene.input.KeyEvent;
javafx.scene.shape.Circle;
javafx.scene.shape.Rectangle;
(1)
double allowedPaddleTopY;
double allowedPaddleBottomY;
(2)
@FXML
@FXML
@FXML
@FXML
(3)
Rectangle table;
Rectangle compPaddle;
Rectangle kidPaddle;
Circle ball;
pdfcrowd.com
pdfcrowd.com
}
private void process_key_Up() {
(6)
(7)
if (currentKidPaddleY.get()< allowedPaddleBottomY) {
currentKidPaddleY.set(currentKidPaddleY.get() +
PADDLE_MOVEMENT_INCREMENT);
}
}
private void process_key_N() {
System.out.println("Processing the N key");
}
private void process_key_S() {
System.out.println("Processing the S key");
}
}
open in browser PRO version
pdfcrowd.com
for the top of the paddle, and the allowedPaddleBottomY will have
the maximum allowed y-coordinate for the bottom of the paddle.
3. Using the @FXML tag we inject the references to the GUI components
component kidPaddle.
5. Here we set the limits for the paddle movements. We set the variable
allowedPaddleTopY=PADDLE_MOVEMENT_INCREMENT to make
sure that if the Kid keeps pressing the Up arrow, the paddle will never
open in browser PRO version
pdfcrowd.com
border of the paddle, and if its far enough from the table top, the code
lowers the value of the property currentKidPaddleY by
PADDLE_MOVEMENT_INCREMENT . Because currentKidPaddleY
Remember, the y-coordinate increases from top down, so the higher ycoordinates means that its physically lower on stage.
7. The method process_key_Down works similarly to
process_key_Up but ensures that the paddle wont cross the bottom
pdfcrowd.com
Lets start implementing step 4 of the game strategy by calculating the starting
position and painting the ball depending on the location of the right paddle.
When the user preses the S-key, we need to serve the ball from the position
where the right paddle is currently located. Initially its located in the middle
of the table, but the user may move it up or down before serving the ball.
The ball is represented by the shape Circle . From school math you should
remember that a circle is represented by the coordinates of the center and the
radius. In JavaFX the corresponding properties of the class Circle are called
centerX , centerY , and radius . When the Circle is placed in a
layout, its center gets the corresponding properties layoutX and layoutY .
By changing the coordinates of the center we can move the ball around the
stage. Our ball is defined in the file pingpong.fxml like this:
<Circle fx:id="ball" fill="#ff1f35" layoutX="191.0"
layoutY="123.0" radius="9.0" stroke="BLACK"
strokeType="INSIDE" />
But why doesnt the above tag <Circle> include centerX and
centerY ? Actually we can and will replace the attributes layoutX and
layoutY with centerX and centerY because we use the Group
open in browser PRO version
pdfcrowd.com
dynamically change sizes and reposition its child components.Hence the x and
y coordinates of a component relative to a layout may not be the same as
coordinates in the scene. For example, the actual x-coordinate of a component
may be calculated by adding the x-coordinate of a container within a scene and
the x-coordinate of the component within a container.
Lets modify the attributes of the tag <Circle> so itll look like this:
<Circle fx:id="ball" fill="#ff1f35" centerX="191.0"
centerY="123.0" radius="9.0" stroke="BLACK"
strokeType="INSIDE" />
pdfcrowd.com
In the method initialize well set the initial values of these properties to
the center coordinates of the ball. Well also bind the above properties to the
center of the Circle , so changing ballCenterX and ballCenterY
will automatically change the location of the ball on the scene:
ballCenterX.set(ball.getCenterX());
ballCenterY.set(ball.getCenterY());
ball.centerXProperty().bind(ballCenterX);
ball.centerYProperty().bind(ballCenterY);
Lets place the ball by the current position of the kids paddle. In the method
process_key_S well adjust the centerY coordinate of the ball. Our
pdfcrowd.com
ballCenterY.set(currentKidPaddleY.doubleValue() +
kidPaddle.getHeight()/2);
ballCenterX.set(kidPaddle.getLayoutX());
}
I ran the PingPong application, moved the paddle up by clicking the arrow
key several times, and then pressed the S-key. The ball obediently moved to
the current position of the right paddle:
pdfcrowd.com
pdfcrowd.com
(1)
//
(4)
(5)
}
open in browser PRO version
pdfcrowd.com
In this example we could have declared the variable timeline inside the
method, but keeping this variable on the class level will allow me to
programatically stop the animation that Ill demonstrate in the next version
of the method moveTheBall .
2. Then well create the KeyValue object to specify which changing value
to display in frames. In this case we want the animation to change the xcoordinate of the ball center from its current value ballCenterX to
zero.
3. We want the KeyFrame to reach the target (change the centerX
preparations.
5. The method play will play the timeline .
open in browser PRO version
pdfcrowd.com
Our ball is not smart enough to notice that there was a left paddle on its way
and went right through it. Well take care of the GUI component collisions a
bit later.
open in browser PRO version
pdfcrowd.com
In the following version of the method moveTheBall well write the code to
advance the ball at the specified increments. Well also use different
constructors of TimeLine and KeyFrame :
final int BALL_MOVEMENT_INCREMENT = 5;
private void moveTheBall(){
KeyFrame keyFrame = new KeyFrame(new Duration(10),
(1)
event -> {
if (ballCenterX.get() > BALL_MOVEMENT_INCREMENT)
open in browser PRO version
pdfcrowd.com
{ (2)
ballCenterX.set(ballCenterX.get() BALL_MOVEMENT_INCREMENT);
(3)
} else {
timeline.stop();
}
(4)
}
);
timeline = new Timeline(keyFrame);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
(5)
1. The first argument of the constructor is the Duration object, but this
pdfcrowd.com
left border and will stay at the 0 coordinates. To make our game more
realistic, well let the ball go off the table in the next version of the
moveTheBall .
3. Decrement the value of the ballCenterX by
BALL_MOVEMENT_INCREMENT . Because of binding, this will move the
pdfcrowd.com
the ball can move either horizontally or upward. To know the y-coordinate of
the table center well declare the double variable centerTableY and set
its value in the method initialize like this:
centerTableY = table.getHeight()/2;
As the ball moves, the modified value of the y-coordinate of the ball center will
be assigned to the property ballCenterY . The following version of the
method moveTheBall implements the random ball servings.
private void moveTheBall(){
Random randomYGenerator = new Random();
double randomYincrement =
randomYGenerator.nextInt(BALL_MOVEMENT_INCREMENT);
(1)
final boolean isServingFromTop =
(ballCenterY.get() <= centerTableY)?true:false;
(2)
pdfcrowd.com
(3)
ballCenterX.set(ballCenterX.get() BALL_MOVEMENT_INCREMENT);
if (isServingFromTop) {
(4)
ballCenterY.set(ballCenterY.get() +
randomYincrement);
} else {
ballCenterY.set(ballCenterY.get() +
randomYincrement);
}
} else {
timeline.stop();
}
});
timeline = new Timeline(keyFrame);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
open in browser PRO version
pdfcrowd.com
the ball on the table when it was reaching the left edge of the table. Now
we will let the ball fall off the table. The -20 is just an arbitrary number we stopped the ball movement after the ball moved 20 pixels past the left
table edge. In the final version of the game well enable the movement for
the left paddle, and sometimes itll bounce the ball back.
4. If isServingFromTop is true, were increasing the y-coordinate of the
pdfcrowd.com
the same amount. Now the ball will be served in an unpredictable manner
and will pretty often fall off the table crossing the top or bottom edge of
the table. I took the following screen shot when the moving ball was about
to cross the bottom edge of the table.
pdfcrowd.com
When the ball is served, the Computer needs to move its paddle in the right
direction to bounce the ball. This is a pretty easy task since the computer
knows that if the Kids paddle served from the top, the ball would move down,
and if the ball was served from the bottom itll move up. So the moment the
ball is served, the computers paddle should also start moving.
First of all, well declare the property currentComputerPaddleY to keep
track of the y-coordinate of the Computers paddle. Well also need to store the
initial y-coordinate of the Computers paddle, because on each ball serving this
paddle should be in the middle of the left side of the table:
DoubleProperty currentComputerPaddleY = new
SimpleDoubleProperty();
double initialComputerPaddleY;
pdfcrowd.com
currentComputerPaddleY.set(initialComputerPaddleY);
compPaddle.layoutYProperty().bind(currentComputerPaddleY)
;
The new version of the method moveTheBall will start the movement of
the Computers paddle in the right direction as soon as the ball is served.
private void moveTheBall(){
Random randomYGenerator = new Random();
double randomYincrement =
randomYGenerator.nextInt(BALL_MOVEMENT_INCREMENT);
final boolean isServingFromTop = (ballCenterY.get() <=
centerTableY)?true:false;
KeyFrame keyFrame = new KeyFrame(new Duration(10),
event -> {
if (ballCenterX.get() >= -20) {
ballCenterX.set(ballCenterX.get() BALL_MOVEMENT_INCREMENT);
if (isServingFromTop) {
open in browser PRO version
pdfcrowd.com
ballCenterY.set(ballCenterY.get() +
randomYincrement);
currentComputerPaddleY.set(
currentComputerPaddleY.get() + 1);
(1)
} else {
ballCenterY.set(ballCenterY.get() randomYincrement);
currentComputerPaddleY.set(currentComputerPaddleY.get() 1);
(2)
}
} else {
timeline.stop();
currentComputerPaddleY.set(initialComputerPaddleY);
}
});
(3)
pdfcrowd.com
1. If the ball was served from the top, move the Computers paddle one pixel
pdfcrowd.com
false if not.
private boolean checkForBallPaddleContact(){
if (ball.intersects(compPaddle.getBoundsInParent())){
return true;
} else {
return false;
}
}
We should call this method from each frame in the timeline that we started in
the method moveTheBall . After this check for contact to the method
moveTheBall itll look like this:
private void moveTheBall(){
Random randomYGenerator = new Random();
double randomYincrement =
open in browser PRO version
pdfcrowd.com
randomYGenerator.nextInt(BALL_MOVEMENT_INCREMENT);
final boolean isServingFromTop = (ballCenterY.get() <=
centerTableY)?true:false;
KeyFrame keyFrame = new KeyFrame(new Duration(10),
event -> {
if (ballCenterX.get() >= -20) {
ballCenterX.set(ballCenterX.get() BALL_MOVEMENT_INCREMENT);
if (isServingFromTop) {
ballCenterY.set(ballCenterY.get() +
randomYincrement);
currentComputerPaddleY.set(
currentComputerPaddleY.get() + 1);
} else {
ballCenterY.set(ballCenterY.get() randomYincrement);
currentComputerPaddleY.set(currentComputerPaddleY.get() 1);
}
open in browser PRO version
pdfcrowd.com
if (checkForBallPaddleContact()){
timeline.stop();
(1)
currentComputerPaddleY.set(initialComputerPaddleY);
bounceTheBall();
};
(2)
} else {
timeline.stop();
currentComputerPaddleY.set(initialComputerPaddleY);
}
});
timeline = new Timeline(keyFrame);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
}
pdfcrowd.com
2. Then well need to call the method bounceTheBall , which well write
next.
According to step 6 in our game strategy, the computer can only serve the ball
horizontally, so writing the bounceTheBall method seems like a pretty
simple thing to do. We already wrote a version of the moveTheBall method
that sends the ball horizontally from right to left, so reversing the ball moving
direction should be easy.
But what if the Kid will move his or her paddle to hit the ball back? OK, then
we need to be checking if the ball contacts the Kids paddle as well. Can we
reuse the method checkForBallPaddleContact for this? Not in its
current form, because its written specifically for the computer paddle. We can
certainly write a similar method for the Kids paddle and have two almost
identical methods, but its better to re-write
checkForBallPaddleContact to work for both paddles.
pdfcrowd.com
Accordingly, the method moveTheBall would check for the contact with
Computers paddle as follows:
checkForBallPaddleContact(compPaddle);
To check for the ball contact with the Kids paddle youd write this line:
checkForBallPaddleContact(kidPaddle);
Now lets write the method bounceTheBall , which should be very similar
to moveTheBall . The ball should move from left to write, if youve been
decreasing the x-coordinate in moveTheBall , youll need to decrease it
open in browser PRO version
pdfcrowd.com
now. If youve been stopping the game where the coordinate of the ball was
less than -20, now it has to be more than the table width plus 20. I could
refactor the method moveTheBall to introduce these values as methods
arguments, but lets keep it as a small project for you. As long as you
understand how the code works, you should be able to do it on your own.
Heres the code of the method bounceTheBall :
private void bounceTheBall() {
double theBallOffTheTableX = table.getWidth() + 20;
(1)
KeyFrame keyFrame = new KeyFrame(new Duration(10),
event -> {
System.out.println(ballCenterX);
if (ballCenterX.get() < theBallOffTheTableX) {
ballCenterX.set(ballCenterX.get() +
BALL_MOVEMENT_INCREMENT);
(2)
if (checkForBallPaddleContact(kidPaddle)){
timeline.stop();
moveTheBall();
open in browser PRO version
(3)
pdfcrowd.com
};
} else {
timeline.stop();
}
});
timeline = new Timeline(keyFrame);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
}
1. The ball should stop its movement when its x-coordinate is 20 pixels to the
arrow keys to stop the ball. If the ball contacts the Kids paddle, we call the
moveTheBall method to start the random movement to the left again.
pdfcrowd.com
The basic functionality of the game is implemented aside from displaying the
game score and starting the new game when one of the players gets 21 points.
Ill leave this part for you to implement on your own.
Ive been showing and explaining various code fragments of the
PingPongController as weve been implementing the game strategy one
step at a time. Now Ill just show how the code of the
PingPongConroller class looks like without any additional explanations.
javafx.animation.KeyFrame;
javafx.animation.Timeline;
javafx.application.Platform;
javafx.beans.property.DoubleProperty;
javafx.beans.property.SimpleDoubleProperty;
javafx.fxml.FXML;
javafx.scene.input.KeyCode;
javafx.scene.input.KeyEvent;
javafx.scene.shape.Circle;
javafx.scene.shape.Rectangle;
javafx.util.Duration;
pdfcrowd.com
import java.util.Random;
pdfcrowd.com
Rectangle table;
@FXML Rectangle compPaddle;
@FXML Rectangle kidPaddle;
@FXML Circle ball;
public void initialize()
{
currentKidPaddleY.set(kidPaddle.getLayoutY());
kidPaddle.layoutYProperty().bind(currentKidPaddleY);
ballCenterX.set(ball.getCenterX());
ballCenterY.set(ball.getCenterY());
ball.centerXProperty().bind(ballCenterX);
ball.centerYProperty().bind(ballCenterY);
initialComputerPaddleY = compPaddle.getLayoutY();
currentComputerPaddleY.set(initialComputerPaddleY);
compPaddle.layoutYProperty().bind(currentComputerPaddleY)
;
allowedPaddleTopY = PADDLE_MOVEMENT_INCREMENT;
allowedPaddleBottomY = table.getHeight() kidPaddle.getHeight() - PADDLE_MOVEMENT_INCREMENT;
open in browser PRO version
pdfcrowd.com
centerTableY = table.getHeight()/2;
}
public void keyReleasedHandler(KeyEvent event){
KeyCode keyCode = event.getCode();
switch (keyCode){
case UP:
process_key_Up();
break;
case DOWN:
process_key_Down();
break;
case N:
process_key_N();
break;
case Q:
Platform.exit(); // Terminate the
application
break;
case S:
process_key_S();
break;
}
}
private void process_key_Up() {
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
pdfcrowd.com
randomYincrement);
currentComputerPaddleY.set(currentComputerPaddleY.get() 1);
}
if (checkForBallPaddleContact(compPaddle)){
timeline.stop();
currentComputerPaddleY.set(initialComputerPaddleY);
bounceTheBall();
};
} else {
timeline.stop();
currentComputerPaddleY.set(initialComputerPaddleY);
}
});
timeline = new Timeline(keyFrame);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
}
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
} else {
timeline.stop();
}
});
timeline = new Timeline(keyFrame);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
}
}
pdfcrowd.com
Youll also need to write a method updateScore and invoke it every time
the timeline stops playing (in both methods: moveTheBall and
bounceTheBall ). The method updateScore can look like this:
pdfcrowd.com
The code that comes with the book has this version of the method
updateScore implemented. Your goal is to display the score in a nice font
on the bottom left corner of the table. you can learn how to work with the
Text and Font classes by studying Oracles tutorial "Working with Text in
open in browser PRO version
pdfcrowd.com
JavaFX Applications".
Dont forget to implement the Start New Game functionality. Youll need to
write a method newGame , where you should reset the scores and place the
paddles and the ball in the starting positions.:toc-placement!::imagesdir: .
pdfcrowd.com
working on the same application? How can you make sure that Joes and
Marys computers have the working copy of the application with the ability to
keep the history of code changes and return to a working version if need be?
Programmers use a special software called Version Control Systems (VCS) that
allows to keep track of different versions of the source code stored in common
source code repositories located on the companys servers. There are also
special web hosting facilities, where Joe and Mary can safely keep their
application code.
Software developers make changes in their local copies of the applications
code, and test them. When the local version of the application works fine, they
commit (save) the latest code changes to the source code repository. If Mary
has committed her changes, Joe can check out the latest code from the shared
repository to his computer. Marys changes will merged with Joes ones on his
computer.
Now Joe has the latest Marys code, but she doesnt have the latest Joes code
changes. When Joe decides to commit his latest code to the shared repository,
Mary can check them out to her computer.
In this chapter Ill introduce you to a popular VCS called Git and to the code
open in browser PRO version
pdfcrowd.com
hosting facility called GitHub. VCSs are used by programmers writing code in
any languages, not only in Java. As a matter of fact you can keep track of any
files using Git and store them in GitHub or other hosts. If your computer gets
lost or stolen you can always recover the code by pulling it from GitHub.
I was using Git as a VCS and GitHub as a shared repository of the drafts of all
chapters of this book, and you can find them on the GitHub at
https://github.com/yfain/Java4Kids.
Understanding how a VCS works is very important - thats why I included this
short Git tutorial in the book about Java.
pdfcrowd.com
If Pete, the new programmer, joins the team, hed need to check out the latest
code from the central repository and start making his code modifications on his
computer. There are many centralized VCS, and some of the most popular are
CVS, SVN, and Perforce.
Distributed VCS store the latest version of the code as well as all historical
files on each programmers computer. Popular distributed VCS are Git,
Mercurial, and Bazaar. Technically, if you work alone, you can install Git on
your computer and have your private VCS without using any remote server as
open in browser PRO version
pdfcrowd.com
a shared repository. But again, having an extra copy of your project files on a
remote server is always a good idea.
Programmers usually work in teams, so the following diagram shows three
computers - one shared repository on the right and two local repositories
(Marys and Joes) on the left.
At any given time each local repository stores the history of all updates made
open in browser PRO version
pdfcrowd.com
by its owner as well as historical updates that the owner pulled from the shared
repository. Lets see how to create a source code repository of your computer
thats managed by Git.
pdfcrowd.com
command name, which may have various options that start with -- or -. To
introduce yourself to Git, use the config command with the --global option.
This is how I did it:
git config --global user.name Yakov Fain"
git config --global user.email "yakovfain@gmail.com"
Later on, when youll be opening a GitHub account youll need to use the same
email as you used with the config command above. Git is ready to manage
your projects. Now lets create a Git repository for a simple project and learn
how to work with it.
pdfcrowd.com
Command window) and will create a new Git repository by entering the
command git init. The content of my gitIntro folder looks as follows:
The git init command has created a hidden directory called .git, which is a Git
repository for my gitIntro project. This directory contains a Git database (a.k.a
the index) that will store all the changes Ill be making to my Java classes
through the life of this project.
You can start using Git with your old projects any time you want. Just open the
directory of any existing project and execute the git init command to create a
new local repository. Of course, it wont know about your prior code
modifications, but from now on you can start tracking them.
pdfcrowd.com
Git has a couple of dozens commands, but knowing just a half dozen of them
may be enough for all of your project activities. Ill show you several
commands that I use daily. Each command may be issued with several options.
Ill just show you the basic commands to quickly get you started with Git. For
more detailed coverage of all Git features and commands youll need to study
online documentation.
Typically, my work with Git-controlled projects consists of the following
activities:
1. Make the changes to some project files.
2. Check the status of the files in my project.
3. Change the status of all or some of the modified files to trackable by
pdfcrowd.com
I always start working with Git by opening my project directory and typing git
status to see which files Ive modified since the last time Ive committed the
changes to Git repository. Lets do it in the directory gitIntro. I havnt
committed any files to my brand new code repository just yet, and Git will
respond with the following status:
Note the first statement indicates that I work with the code branch called
master. Ill explain how and why you may need to create separate code
branches a bit later, but for now I have no other branches. The untracked files
are displayed in red, which means that they are either new to Git or have been
modified after the last commit to the repository. The changes made to the
untracked files are not stored in the Git database.
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
Similarly, you have lots of files in your projects folder(s), but you may want
to add only selected ones to the git repository, for example git add Fish.java.
We call the modified files that must be saved in the Git database trackable. The
modified files that will be ignored by Git are called untracked.
If you want to know which options exist for any Git
NOTE
You can also add all new or modified files in one shot by executing the
command git add --all. After running this command youll get the following
output:
pdfcrowd.com
Now all my Java files are shown in green, which means that these files became
trackable and are ready to be committed to the Git database.
NOTE
You shouldnt store compiled Java classes or JARs in the source code
repositories. You can let Git know which files to ignore by creating a text file
named .gitignore in your project directory. Then open it with a plain text
editor and add the types of files that Git should ignore. For example, if youll
add the following two lines to your .gitigore file, compiled classes and JARS
wont be included in your Git database:
open in browser PRO version
pdfcrowd.com
*.class
*.jar
The -m option allows writing a short message in double quotes describing the
commit.
open in browser PRO version
pdfcrowd.com
The "63 insertions" means that total of 63 lines were inserted in the Git
database.
If you would run the git commit command without any options, Git would open
a text editor where you should enter a detailed description of changes being
committed. Saving this file will store this description in the Git database.
Enter the command git status again, and youll see the "nothing to commit"
message. No wonder, I just committed three files and havent modified them
again just yet.
Now let me make a small change in the file PetMaster.java. Currently it has the
open in browser PRO version
pdfcrowd.com
following content:
public class PetMaster {
public static void main(String[] args) {
String petReaction;
Pet myPet = new Pet();
myPet.eat();
petReaction = myPet.talk("Tweet!! Tweet!!");
System.out.println(petReaction);
myPet.sleep();
}
}
Ill just modify the comment at the top of this file. Ill change the text to
"Created by Yakov on 3/28/15." Running the git status command again will
produce a different output:
pdfcrowd.com
Git has noticed that the file PetMaster.java has been changed, but until I issue
the command add for this file (or all files), Git wont track the changes in
PetMaster.java. In the toy store setup, its a situation when a toy is displayed
on the shelf, you noticed it but have not added it to your shopping cart yet. The
following two commands will save my latest change in the Git database:
git add PetMaster.java
git commit -m "Modified the opening comment in
PetMaster.java"
After committing all the changes git status will tell us again that there is
nothing to commit, and the working directory is clean.
To summarize, we have three Java classes located in the working directory
gitIntro, and the history of modifications and commits is stored in the directory
open in browser PRO version
pdfcrowd.com
.git. Id like to remind you that all the work weve done so far was saved only
in the local code repository.
The reset command will undo the last commit and will open a text editor
containing the description of this reverted commit, which can look as follows:
open in browser PRO version
pdfcrowd.com
You can change this text to better describe what has been done by this reset
command. Git will store the saved message in its history files. The 40character long sequence of digits and letters is a unique code associated with
each commit.
NOTE
So far weve been working with the default branch called master, and now Ill
open in browser PRO version
pdfcrowd.com
pdfcrowd.com
Mary will be running all branching commands in the same directory gitIntro.
First, shell create her own branch called mary:
git branch mary
The new branch mary will be created in the Git database, but Mary remains in
the master branch until she switches to the new branch by executing the
checkout command:
git checkout mary
The git status command is our friend. Mary uses it often to make sure that she
works in the proper branch:
pdfcrowd.com
You can also print the names of all branches that exist in your Git repository
by running the command git branch. The current branch will be shown in
green and marked with an asterisk.
Now Mary adds the following method to the class Fish :
public void surface(){
System.out.println("Going up " + currentDepth + "
feet.");
}
Using the usual sequence of commands status, add, and commit Mary commits
the changes to the branch mary:
open in browser PRO version
pdfcrowd.com
At any given time the working directory will have only one copy of each file
with the content that corresponds to the current branch. Hence the class Fish
from the branch mary has the method surface . Now Mary switches back to
the branch master by running git checkout master and opens the file Fish.java the method surface isnt there! Git seamlessly moved the older version of
Fish.java from its database back to the working directory. It happened really
fast, because in the distributed VCS the complete code repository is located on
the programmers computer and there is no need to do any communication over
the network.
Mary tested the new version of the class Fish and shes ready to include it in
the master branch. Using the VCS terminology, she wants to merge the code
open in browser PRO version
pdfcrowd.com
located in the branch mary into the code in the master branch. From the master
branch Mary runs the following merge command:
git merge mary
In this case Git was able to automatically merge two versions of the file
Fish.java. But sometimes the changes are conflicting with each other and
manual editing is required to resolve the conflicts.
pdfcrowd.com
Since Mary was the only programmer working with the file Fish.java Git just
kept track of all insertions, deletions, and changes and re-applied them to the
older version of the file during the merge. But when more than one
programmer works on the same file they could accidentally modify the same
piece of code in different branches. This may cause merge conflicts, and Git
will mark the code fragments that need to be merged manually.
Ill illustrate this by creating conflicting changes on purpose. First, Ill add
three exclamation marks in the method surface in the master branch:
System.out.println("Diving for " + howDeep + " feet!!!");
Ill commit the changes to the master branch, then switch to the branch mary
and add the question marks there in the same place where exclamations were
placed in master. So in the branch mary this line will look like this:
System.out.println("Diving for " + howDeep + " feet???");
Now Ill switch back to master branch and will try to do a merge. Clearly Git
cant take a responsibility in picking one version over the other. Weve got a
conflict:
open in browser PRO version
pdfcrowd.com
If youll open the file Fish.java youll find some duplicate code marked with
special tags:
public void surface(){
System.out.println("Going up " +
<<<<<<< HEAD
currentDepth + " feet!!!");
=======
currentDepth + " feet???");
>>>>>>> mary
}
pdfcrowd.com
NOTE
pdfcrowd.com
pdfcrowd.com
Press the button titled "Create Repository" and an empty repository is ready.
GitHub will show you the following page with short instructions on how to
upload your code there.
pdfcrowd.com
Note the HTTPS URL of this repository on top. Its used for cloning, which is
described later on.
pdfcrowd.com
gitIntro, well need to go there in the Command or Terminal window and enter
the suggested commands:
git remote add origin
https://github.com/java4kids/gitIntro.git
git push -u origin master (2)
(1)
origin. So the first command adds a URL of the newly created origin to the
configuration of your Git project. The name origin serves as an alias name
to that long GitHub URL.
2. The Git push command uploads the local code to the remote repository. So
you commit changes to a local Git repository, and push them to the remote
one. Accordingly, the second command uploaded my Git-managed
repository to GitHub. The -u option means upstream. Youll use it with the
first push to link your local repository to the the remote one. Subsequent
push commands will be issued without the -u option.
pdfcrowd.com
After running these commands the code and the Git database from my local
directory gitIntro is published on GitHub. Now if you or anyone else will visit
the URL https://github.com/java4kids/gitIntro, theyll see a Web page that
looks similar to this:
pdfcrowd.com
pdfcrowd.com
If you work alone on the project, you wont use the pull command that much,
because no one else is pushing the code changes there. Youll be repeatedly
running the following sequence of git commands:
add - to make the files trackable
open in browser PRO version
pdfcrowd.com
14.5.4. Cloning
Say Peter joins the existing project and Joe and Mary want him to get the latest
code installed. Peter will also use Git and GitHub, so he needs to install Git on
his computer, but Peter doent have to create a new folder and run the git init
command there. Git has a clone command that can take the existing code from
a shared repository and create its copy on Peters computer. The clone
command downloads the latest projects code including the entire Git database
open in browser PRO version
pdfcrowd.com
with all of the history of changes made by Joe and Mary in the past. You can
do cloning either by clicking the button "Clone in Desktop" on GitHub or by
running git clone in the Command window.
While writing this book I stored all its code examples on GitHub at
https://github.com/yfain/Java4Kids_code. You can clone my Git repository
from GitHub and start using, improving, or adding new code samples. Just
visit the above Web page and copy the URL from the box HTTPS clone URL
on the right hand side:
pdfcrowd.com
You can see only a part of this URL, but when you copy it into the clipboard
open in browser PRO version
pdfcrowd.com
Now open the Command (or Terminal) window and run the clone command
using the above URL as parameter:
git clone https://github.com/yfain/Java4Kids_code.git
As a matter of fact you can clone any GitHub open source repository on your
computer and work with the code without even notifying the author of the
open in browser PRO version
pdfcrowd.com
code. But creating a clone doesnt mean that you can push your code changes
back to the authors GitHub repository without his approval. GitHub has
special procedures for this called Forking and Pull Requests.
pdfcrowd.com
This will create a new repository under your GitHub account and will copy my
code there. Then you can clone this project from your repository and work with
it. When youve improved my code or fixed a bug, push it to your forked
project. Then visit my GitHub page and press the button Pull Request there:
pdfcrowd.com
Youll be able to create a pull request and describe the code change that youve
already implemented and committed into the forked repository. Actually, I have
open in browser PRO version
pdfcrowd.com
one pull request at the time of this writing. Lets click on this little circle with
the digit 1 and see whats there:
pdfcrowd.com
The following diagram illustrates the forking and pull request processes:
Not every pull request can be automatically merged, especially if multiple code
changes have been done. In this case youd need to do a manual merge right in
GitHub. I always leave a Thank You comment to people who have helped
make my code better.
open in browser PRO version
pdfcrowd.com
IDEA will ask you to login to GitHub. Use the email and the password that you
used while creating your GitHub account. Then IDEA will ask you for its own
open in browser PRO version
pdfcrowd.com
password database - leave it blank. Now IDEA is ready to clone any public
repository provided that you know the clone URL, which is
https://github.com/yfain/Java4Kids_code.git in our case. You should enter this
URL in the next window that may look similar to this one:
The field with the name of the project directory will be populated
automatically, but you can change it if you want. Press the button Clone and
IDEA will clone all the projects into the specified directory and will ask you if
you want to open a project. Selecting Yes will open one of the IDEA projects
(e.g. Chapter7). Youll also see a warning about unregistered VCS root, which
you can ignore, as you wont be directly pushing any code changes into my
GitHub repository.
If you open the project directory with File Manager (or Finder), youll see that
there are other folders that contain code samples for all of the chapters. You can
open any of these projects in IDEA by selecting the menu File | Open.Note that
open in browser PRO version
pdfcrowd.com
this project directory has a folder named .git, which contains Git database with
the history of all commits that I did while writing code samples for this book.
If you see any compilation errors, open the menu File | Project Structure and
make sure that the project language level is set to "8 - Lambdas, type
annotations etc."
IntelliJ IDEA fully supports Git, so you can run all Git commands without the
need to use the Command window. You can find the description of Git support
in the IDEA documentation.
Epilogue
This book is over. I hope youve enjoyed reading it as much as I enjoyed
writing it. Your process of studying Java is far from being over. If you liked
this book and want to continue your journey, consider reading my other Java
book for adults, which is called "Java 24-Hour Trainer", 2nd Edition, Wiley.
That book comes with videos that illustrate the materials covered in each
chapter. I also explain the server-side programming in Java there.Maybe one
open in browser PRO version
pdfcrowd.com
day Ill write a more advanced Java book for kids too. Thank you for reading
my book, and good luck!
pdfcrowd.com