Showing posts with label application. Show all posts
Showing posts with label application. Show all posts

Monday, November 17, 2014

Portability of Java Programming Skills

You can program in Java (or are learning to.) That's great! But what else can you do with those skills? Are you trapped with Java?

Not at all. One of the reasons I chose Java as a language for use in the classroom is that Java programming skills translate so well into skills for other languages. Here are some other languages, and a brief look at what your Java programming skills will give you in the way of a head start, and what differences to look out for.

C# (C Sharp)
C# and Java are practically the same. C#'s roots are in Java, as is the concept of its libraries relative to Java's API. The libraries differ, but if you're used to Java's API you'll have no trouble getting right into C#'s libraries to find the classes you're looking for.

The major development tools are very similar, or, in many cases, you can use the same IDEs for C# as for Java. You can also do cross-platform development in C# just as you can with Java thanks to tools like Mono (which I highly recommend as a way of becoming familiar with C#) and the forthcoming cross-platform Visual Studio tools from Microsoft.

C
Java is an object-oriented descendent from the C language. C does not have object-orientation built in, but you should have no trouble understanding much of the code. Imagine writing Java without creating your own classes, or only creating limited classes. This isn't strictly accurate, since it is possible to write object-oriented code in C, it just requires the programmer to do much of the work that Java does in their code. Providing for isolation of data, inheritance, etc. has to be performed through code written explicitly to perform these functions.

Modern versions of C, such as ANSI C/ISO C (C99) provide a version of C which makes it easier to write good code if you're coming from an object-oriented background.

Another major hurdle will be dealing with memory management directly (C has no garbage collection), and learning how to use the various functions of C which are often not as predictable as the Java methods you are familiar with.

The basics of C will already be familiar to you, but you should conduct some formal study of C and use its standard libraries extensively before seeking to start formal projects with it.

C++
C++ is another object-oriented outgrowth of C, like Java, yet it uses a very different approach. You will find that your Java experience can be very misleading with respect to the handling of data and the operation of methods in C++. Also, C++'s libraries tend to be much more platform-specific than those of Java. In Java you have platform-specific libraries, yet it is possible to write good code that does not rely on it, or that relies on it little enough to allow 90% or more of your code to be written in a non-platform-specific fashion.

With C++, however, you'll find that while there are standard cross-platform libraries, most code will be best written to the platform to which it is being compiled.

Python
Python will be very easy to learn once you know Java. Its syntax is quite different, and its approach to what is implicit and what must be explicitly defined is very different to that of Java. Conceptually, however, you will be right at home and will be able to learn the specifics of the language very easily.

Like Java, Python has extensive libraries. Some are part of Python's core distribution, but others are not. You will find that even in the core libraries there is much less cross-platform support than Python seems to promise. Also, you will need platform-specific libraries for any graphics or audio code. Even in cross-platform libraries, you will find that there are significant differences between platforms. If you are writing code that does not rely on the platform for presentation, however, (for example code that uses a browser), Python works very well in a cross-platform environment.

Javascript
Javascript is also very similar to Java in many ways, but not as much as the name of the language might lead you to believe. Java has recently acquired many of the constructs that have been favorites of Javascript programmers for years.

You will find that handling data under Javascript is very different to the means used in Java. You will also find the nomenclature very, very different, despite the similarities in the languages. This will probably be your biggest early hurdle in transitioning from one language to the other.

The best approach is to set yourself to learn the ways that things are best done in Javascript, before trying to write Java code in Javascript syntax. Once you can write solid small programs, enough will become apparent to you that you can begin to take advantage of your programming knowledge from Java to apply it to your Javascript programs. Some programming languages it is your knowledge of Java syntax and structure that will make those languages easy for you. Javascript isn't one of those languages. The payoff comes after you have learned Javascript syntax and structure, the process of designing well-build object oriented software will pay off.

With Javascript, the web browser is almost certain to be your "platform." You will need to learn the Domain Object Model to effectively apply Javascript. If you have already been using the DOM with your Java code (over half of Java code is written for the web), then you are already there. Otherwise, it's something else new you'll have to learn.

Objective-C
The transition from Java to Objective-C is far simpler than to C++. The object-oriented techniques used in Objective-C will make immediate sense to a Java programmer, as will the program structure. Objective-C requires you to do your own memory management, unlike Java, but it provides facilities to do so more simply and effectively than standard C.

The libraries will differ completely from those of Java, and your platform will almost certainly be iOS or Macintosh, so those are the platforms whose libraries you'll learn. Objective-C differs from Java more than C#, but not so much as to make it extremely difficult to transition to. After C#, Objective-C is probably the easiest non-scripting language for you to learn.

Swift
Swift is based on Objective-C, and will be even easier for a Java programmer to learn and use. Most of the changes not only make it easier to produce programs in general, but make it conceptually simpler for a Java programmer to make the transition. You'll be reading the code in the first day, and will be able to produce effective code with only a few hours of work. As with Objective-C, there are new libraries for you to learn tied to Swift's platforms (iOS and Mac), but you will find these even easier to navigate than the Java libraries that suffer from Java's early history of development being encased within them.

PHP
PHP does not have the sort of object-oriented programming facilities that you will be used to from Java, but its syntax will be easy for you to pick up. You will likely feel limited by PHP compared to Java, but PHP has a more limited purpose than Java--it is focused on web programming. While Java is heavily used for server-side web programming, it is much more of a general purpose language than PHP.

You will need to learn the specifics of PHP's syntax and data structures, but after mastering Java, you will not find this difficult.

Summary
These cover the most popular programming languages in use at this time. There are other languages, like Scala, that are specifically designed to be like Java yet address shortcomings perceived in Java, either for some specific use, or to change things that are historically embedded in Java's design. These are very easy for a Java programmer to transition to.

At present, Oracle's support of Java is limiting its market relative to the general use for Java that Sun used to promote. While Java is still widely used, and will continue to be for the foreseeable future, it always behooves a programmer to be competent in multiple languages and to have more than one set of conceptual tools for problem solving at hand. So it is good to know other languages, even if they are scripting languages like Python and Ruby.

Currently, Microsoft is in the process of making a strong play to the cross-platform development market which Java has served. With C# as part of this, and C# plus Mono (a cross-platform version of .Net) already available, it is very easy for a Java programmer to add this to their programming portfolio to gain a greater range of opportunities for work, and a wider range of tools for solving programming problems.

I highly recommend, at least, spending some time with C# under Mono or .Net if you are currently a Java programmer. I think you'll find that you feel right at home.

An advantage of learning .Net is that it will open up Windows-specific programming in C++ to you as well. The C++ language will be new, but you'll already know the libraries that you'll be using. If Microsoft delivers on their recent promises of making their tools fully cross-platform for Mac and Linux, then you'll be able to apply those skills to those platforms as well.

Mobile
Java is the language you'll use on Android, currently the dominant mobile platform in terms of users. Objective-C is the language for iOS, and it's not a huge jump for a Java programmer to make. Swift is a simplified version of Objective-C, and it is even easier for the Java programmer to learn. If you are planning to develop for iOS, it is worth making the effort to transition to a language built for it, and Swift should be your first stop.
StumbleUpon

Tuesday, November 12, 2013

DozCalc: A More Polished Android Application in Java

Since my post on my first Android app, I've done a lot. I went on from that first app to learn how to access a lot more of the device, deal with a wider range of circumstances, and generally get to know Android and the tools for developing for it better.

Specifically, I have posted an app for Android called DozCalc.

DozCalc is a dozenal (base 12) calculator. It doesn't convert back and forth between dozenal and decimal, so be warned. Just like your normal four function calculator that works in base 10 and nothing else, DozCalc works in base 12 and nothing else.

Java

The "programming", like development in many modern GUI environments, was less about the functional code (in this case in Java) and more about the user interface. While Android allows for UI programming in Java, it's typically simpler to implement it in XML. And this is what I did.

The only problem I had was dealing with loss of precision in some calculations. At first, I was going to be very clever and write a proper function using numerical analysis to get the value right to some specified number of fractional digits (note: it's not proper to call them 'decimal digits' when you're working strictly in base 12). However, it was simpler and easier to just add a small value to certain calculations (division, for example) to make all the fractional values come out correct. Far simpler to program, just as effective for this use, and every bit as accurate as the average four function calculator.

Sometimes programming is less about the language, or the algorithm, than about just getting a solution that's accurate enough for the need, then moving forward.

Thanks to object-oriented design, I was able to re-use the code from DozCalc in another graphical calculator. Unfortunately, I got bogged down in the graphical design, so the steampunk styled version of DozCalc (named Mr Wells' Calculator) has yet to be released, and may not be depending on how my schedule of current projects goes.
StumbleUpon

Thursday, October 20, 2011

Mobile Java

One of the nice things about Java is that is supported on more than desktop platforms, and has been for a long time. This means there is not only a large library of existing software, but also well-tuned development systems to use with mobile platforms.

By "mobile platform", I'm referring to smartphones and tablets. There are other mobile platforms, but these are the most common ones. Netbooks may also run a "mobile" operating system, or they may run a normal desktop OS. Those that run a normal desktop OS will run normal Java SE applications. Java SE is "Java, Standard Edition", the version that typically runs on a desktop or laptop computer.

Java ME is Java, Mobile Edition. It runs on most smartphones, and many tablets. It is very similar to the Java SE version covered in most of my articles. In fact, it is possible to write many applications using a subset of Java that will run without change under both Java SE and Java ME.

But normally a Java ME application will use user interface objects and interfaces that are specific to Java ME. In many ways these are more sophisticated than the ones for Java SE. Creating many types of graphical interfaces, such as tiled graphics, is easier in the mobile edition than in standard Java.

I have been writing small, simple applications for my cellphones for about ten years now. It's nice to be able to write your own little application for your own unique needs. I started writing Java applications for my Nokia 3650, called a "feature phone" at the time I got it. It was a Symbian Series 60 phone that ran an early version of Java ME with a very basic library of GUI features.

My next phone was a step up the Java ladder. It was a Sciphone G2, a fake Android phone. I didn't mind that it was "fake", it ran a real version of Java ME with updated GUI capabilities, which made it far easier to write applications for.

My current phone is a Blackberry Curve 8900. It runs Java ME with all the latest bells and whistles, plus a lot of Blackberry add-ons that make it easy to access the phone's features.

With my Nokia, I had a special Java development environment provided by Nokia that included a simulation of my phone, so that I could see how my programs would run before I put them on the phone. With the G2 I was on my own. I ran a standard Java ME development environment from within Eclipse, a great Java integrated development environment. The version linked above is a version specific to Java ME.

Now I'm back to having a development environment provided by my phone's maker. I have a program that simulates my phone on my computer, which again allows me to try out my programs before I put them on the phone (with my G2 I tested them as well as I could, then loaded them on the phone and hoped for the best.) It is build on Eclipse, so it is still very familiar. There is also a slew of information on the Blackberry site (linked above) about Java development.

Unfortunately, the tutorials on the site don't exactly match the actual current version of the software, but it's close enough it's not too hard to figure out. One thing that confused me, however, is the installation instructions. I thought I had to install the version of Eclipse they called for before installing the "Blackberry Java Eclipse Add-On". It's an add-on, right?

Well, it turns out that the "add-on" from Blackberry is actually the entire thing, Eclipse and all. So you just need to do that one download to get the development environment. Then download the simulator for your phone and any others you want to test your software on. Finally, apply for a signature key to make it so that you can "sign" your software to allow it to be installed on the phone through the software manager or Over The Air (OTA) when using the Blackberry-specific libraries.

If you'd rather not do this, you can develop software using a plain-jane version of Java ME, then transfer the software to your phone however you please. I put the software I developed for my Sciphone G2 on the memory card for my Blackberry, and it runs just fine.

Translating applications between Java SE and Java ME can be simple for ones with minimal amounts of graphics, like programs that mainly use text, buttons, and text entry boxes for communication. Things like games, with a more involved use of graphics, take more effort to translate between the two versions of Java. For these, I usually re-use the game logic code without changes, then rewrite the graphical display parts of the program from scratch. Because I use good object-oriented coding practices (most of the time), this isn't too much effort.

Java ME applets are easy to translate, though I write almost all of my Java software as applications now.
StumbleUpon

Friday, May 13, 2011

A Java CSV File Reader

One of the most common types of data file is a CSV (Comma Separated Value) file. They can be exported by many popular applications, notable spreadsheet programs like Excel and Numbers. They are easy to read into your Java programs once you know how.

Reading the file is as simple as reading a text file. The file has to be opened, a BufferedReader object is created to read the data in a line at a time.

Once a line of data has been read, we make sure that it's not null, or empty. If it is, we've hit the end of the file and there's no more data to read. If it isn't, we then use the split() method that's a member of Java's String object. This will split a string into an array of Strings using a delimiter that we give it.

The delimiter for a CSV file is a comma, of course. Once we've split() the string, we have all the element in an Array from which our Java programs can use the data. For this example, I just use a for loop to print out the data, but I could just as well sort on the values of one of the cells, or whatever I need to do with it in my program.

The Steps

  1. Open the file with a BufferedReader object to read it a line at a time.

  2. Check to see if we've got actual data to make sure we haven't finished the file.

  3. Split the line we read into an Array of String using String.split()

  4. Use our data.


The Program
// CSVRead.java
//Reads a Comma Separated Value file and prints its contents.


import java.io.*;
import java.util.Arrays;

public class CSVRead{

public static void main(String[] arg) throws Exception {

BufferedReader CSVFile =
new BufferedReader(new FileReader("Example.csv"));

String dataRow = CSVFile.readLine(); // Read first line.
// The while checks to see if the data is null. If
// it is, we've hit the end of the file. If not,
// process the data.


while (dataRow != null){
String[] dataArray = dataRow.split(",");
for (String item:dataArray) {
System.out.print(item + "\t");
}
System.out.println(); // Print the data line.
dataRow = CSVFile.readLine(); // Read next line of data.
}
// Close the file once all data has been read.
CSVFile.close();

// End the printout with a blank line.
System.out.println();

} //main()
} // CSVRead


Downloads

This program, and an example CSV file to use it with (a section of a spreadsheed I use to keep track of my integrated circuits) are available at my code archive.

Writing to CSV Files with Java

Writing to a CSV file is as simple as writing a text file. In this case, we write a comma between each field, and a newline at the end of each record.

Give it a try, starting with TextSave.java, modify it appropriately, then see what your favorite spreadsheet program thinks of the results.
StumbleUpon

Tuesday, January 25, 2011

Java's File Names and Class Names

Java is picky about the file names you use.

Each source file can contain one public class. The source file's name has to be the name of that class. By convention, the source file uses a .java filename extension (a tail end of a file name that marks the file as being of a particular type of file.)

So, for a class declared as such:

public class HelloWorld{
...

The file it is stored in should be named HelloWorld.java.

The capitalization should be the same in both cases. Some operating systems don't notice whether file names are capitalized or not. It doesn't matter, you should be in the habit of using the correct capitalization in case you work on a system that does care about capitalization.

When you compile your file with javac, you pass the full file name to javac:

javac HelloWorld.java

Let's say we save the file under a different name. We write the following program:

public class HelloThere{
public static void main(String arg[]){
System.out.println("Hello There.");
}
}

Then we save it as HelloWorld.java, and try to compile it:

>javac HelloWorld.java
FileName.java:1: class HelloThere is public, should be declared
in a file named HelloThere.java
public class HelloThere{
^
1 error


Java lets us know that it won't compile until we rename the file appropriately (according to its rules.)

So let's rename the file. Let's call it HelloThere.javasource. Seems a bit more explicit than just .java, right? Let's run the compiler:


>javac HelloThere.javasource
error: Class names, 'HelloThere.javasource', are only accepted
if annotation processing is explicitly requested
1 error

Java's still not happy with us. Annotation processing? That's when we include extra information in the program about the program itself. We're not bothering with that just now. So we should just name the file HelloThere.java, and not get fancy with our file names.

But, under the right circumstances, javac does allow file name extensions other than .java. That's why we always type in the full file name, including .java, when we use javac. We say 'javac HelloThere.java', not just 'javac HelloThere'. Javac can't assume that we mean a .java file, though that's what it will usually be.

The Class File

Once we make javac happy with a proper file name, and a program with no errors, javac produces a new file. This file will have the original file name, but with .java replaced with .class. This is your bytecode file, the file that the Java Virtual Machine can run.

When we run the program with Java, we're running the .class file. In the case of HelloThere, we're running the HelloThere.class file. But we don't type in the full file name. Why?

Unlike javac, java requires a .class file. That's all it will work with. There's no opportunity to have a different extension to the file name. So it assumes the .class part of the file name. But that's not the whole story.

If you add .class yourself, here's what you'll get:

>java HelloThere.class
Exception in thread "main" java.lang.NoClassDefFoundError:
HelloThere/class
Caused by: java.lang.ClassNotFoundException: HelloThere.class
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)

Pretty ugly. What we're actually doing when we type "java HelloThere" is telling Java to run the class HelloThere. Java assumes that it will find this in a file called "HelloThere.class", so that's what it's looking for first.

We're not telling Java to run the file HelloThere.class, we're telling it to run the class HelloThere, which it expects to find in the file HelloThere.class.

But what if we ask for another class that doesn't have its own .class file?

Just for fun, let's change HelloThere.java like this, and see what happens:
public class HelloThere{
public static void main(String[] arg){
System.out.println("Hello.");
}
}

class HelloZoik{
public static void main(String[] arg){
System.out.println("Zoiks!");
}
}

After we edit it, we compile with 'javac HelloThere.java' and hold our breath.

Hurray! No errors!

Now we have a second class, HelloZoik, in the HelloThere.class file. Can Java find it?

Let's try:
 java HelloZoik
Zoiks!

It worked! Java found our class inside HelloThere.class.

This shows it's not the file name that we're calling with the 'java' command, it's the class name.

If Java doesn't find the class inside a file with the same name as the class followed by .class, it'll look in the other .class files available.
StumbleUpon

Tuesday, January 4, 2011

Should I Still Learn Java?

With all the controversy surrounding Java thanks to the purchase of Sun by Oracle, the lawsuits flying back and forth over the Java Community Process, the Apache Foundation, Android, and all the rest, does it still make sense to learn Java?

After all, the demise and abandonment of Java is being predicted practically every day.

I say Yes, now is the time to learn Java. No matter what your programming skill or background, Java is a valuable language to learn, it will be used and useful for a long time to come.

Never a Dull Moment

The Java language has been a-swirl in controversy since its public announcement. It has not become "the" language in many of the areas it originally claimed to be "the" language to use, but yet it has become popular in many other areas. In fact, Java is neck and neck with the language C for being the most popular computer language:

TIOBE Software Community Index (of most popular programming languages.)

langpop.com Programming Language Popularity Rankings.

Devtopics.com Most Popular Programming Languages.

Why Popularity Matters

Why does popularity matter? Because it entrenches a programming language, not just for now, but for many years to come. In fact, every language that has ever become deeply entrenched is still with us, so there's no way of knowing just how long popularity will keep a programming language alive.

When I was first learning to program, the big languages were assembly (the "real" programmer's language of the time), BASIC, FORTRAN, and COBOL. Every single one of those is still a viable language today. Though if you'd asked me then, I would never have thought COBOL would still be with us today. I would never have believed how popular it is, either.

But COBOL was re-invented in the late 80's. And there were a lot of big-money installations running on it. ADA failed to displace it. It's still here, and it's still a valuable part of a programmer's resume for many jobs.

FORTRAN is a language I expected to re-invent itself. It had already done so by the time I learned it (I first programmed in the original FORTRAN, but FORTRAN IV was already in common use.) But with the promulgation of Pascal, Modula-2, and C in the 80's I figured FORTRAN would be pushed into the recesses of obscurity. I was wrong.

Modula-2 was mishandled by the company that owned the rights to it, so it never took off as well as it might have. Pascal took off even though it was never intended to be anything but a classroom language. C took off since it didn't have Modula-2's licensing disadvantages and it had enough of its advantages to become the "next generation language" of its day.

Modula-2 is still with us, but it's insignificant among languages today. Because it never got popular. The others I mentioned got popular, and they're still popular today. Yeah, even Pascal. You could learn Pascal today and do a lot with it (though I don't recommend it unless you want the academic challenge of broadening yourself as a programmer.) I still write software in Pascal, though mostly for my own use, and only for older computer systems.

The key to a programming language's longevity is popularity. Once a language becomes sufficiently popular, for all practical purposes it will never die.

Java is that popular.

The Many Javas

Java has become deeply ingrained into the modern computer infrastructure. Not only does the Java Virtual Machine support a lot more languages than Java itself, but Java has spawned other languages so close to itself that if you know Java you can pick up the other languages without significant effort. C# is the most popular of these spin off languages.

Plus, there are different versions of Java. The Mobile Edition, used on cell phones, smart phones, and PDAs, is a major programming language for these platforms. Each of these platforms has its individual programming suite, and associated language. Their second language, the Esperanto of the portable world, is Java. Programmers that want their software to move easily between platforms often choose to write their code in Java.

The use of Java on servers is rife as well. Java Enterprise Edition became the most popular use of the Java language when Java was still struggling to be used as an applications programming language over a decade ago. Some say that Java on the server saved the Java language. Certainly this is what makes Java a good language to learn for professional reasons.


The Most Important Reason

The most important reason to ignore all the hullabaloo about Java's impending demise and not worry about learning it is that:

  • it is a good language that's fairly easy to learn,

  • expressive enough to do a lot of different things effectively,

  • easy to develop sophisticated modern programs in

  • without too much work for an individual or small group of developers,

  • gives access to all the important parts of the machine (graphics, sound, filesystem, peripherals)

  • and what you learn travels well to other languages when you go on to learn them.



It's not going to go away any time soon. There's too much momentum. There's no need to worry. Ever since the launch of Java I've heard that it's going to be gone or unusable tomorrow. History shows that just doesn't happen to popular programming languages.

If you learn Java now, you may still be using it 20 years from now. Or 30.

When I sat down to a card punch to write my first program 38 years ago as I write this, the computer lab know-it-all came to look over my shoulder.

"FORTRAN!" he said. "Why are you wasting your time with that language? It's a dead, old language. Did you know it's the oldest computer language? If you really want to be a programmer, you should start right out in BAL*! That's what real programmers use, and you're going to be behind if you waste your time on anything else."

FORTRAN doesn't make the "top 10" in programming languages much any more, but it gave me a good start. It's still among the most popular languages, around #20, or just out of the top 10 if you only count general purpose programming languages (that is, not counting scripting languages, query languages, application-specific languages, and so on.)

And learning FORTRAN never kept me from learning structured languages, AI languages, Object Oriented languages, and so on. Even though my first program included the "dreaded" GO TO statement.

There's never been a better time to learn to program. And there's never been a better time to learn Java (the language is in the best shape it's ever been!)

*Basic Assembly Language, a version of assembly language for IBM computers.
StumbleUpon

Thursday, September 2, 2010

Interactive Keyboard Input In Java: KeyListeners

In a console application, you can get keyboard input using the Scanner class, as described in Keyboard Input for Console Apps. In an graphical app, though, you can use one of the classes built to accept text input (e.g. TextArea or JTextField) or add code to your application to respond directly to the keyboard.

Keyboard input in the Java GUI made simple.
Playing with Today's Program

There are two basic ways of doing this. One is to set up Key Bindings, which maps keystrokes to actions in your application similar to accelerator keys or menu keyboard equivalents. The other is to use a Key Listener, similar to the Mouse Listener, which I detailed in Simple Mouse Interaction.

In this example we're going to use Key Listeners. There is less overhead to setting up a KeyListener when you just need to use a few keys. Key Bindings require more overhead to set up, but when you want to bind actions to a lot of different keystrokes, and manage the actions bound to particular keystrokes at a higher level, Key Bindings are better to use than a simple KeyListener.

As its name implies, a KeyListener is an Event Listener. If you're not sure what that is, read my article on Listeners or follow the prior link to Oracle/Sun's description.

Here's a program that demonstrates simple keyboard interaction. It's based on the MousePanel program I presented in Simple Mouse Interaction. It acts as a sort of "Etch-a-Sketch". You can download the KeyPanel program source from my Java code site.

// Import the basic necessary classes.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class KeyPanel extends JPanel implements KeyListener{

public KeyPanel(){
super();
pointX=0;
pointY=0;
oldX=0;
oldY=0;
addKeyListener(this);
}

int pointX, pointY, oldX, oldY;
boolean erase;

public void paintComponent(Graphics g){
// Erase the board if it's been requested.
if (erase) {
g.clearRect(0, 0 , getBounds().width, getBounds().height);
erase = false; // We're done, turn off this flag now.
}

// Draw gray where the pointer was..
g.setColor(Color.GRAY);
g.fillRect(oldX-2, oldY-2, 4, 4);
// Draw "Cursor" at current location in black.
g.setColor(Color.BLACK);
g.fillRect(pointX-2,pointY-2, 4, 4);
}

public void keyPressed(KeyEvent key){

// Copy the last clicked location into the 'old' variables.
oldX=pointX;
oldY=pointY;
// Move the current point depending on which key was pressed.
if (key.getKeyCode() == key.VK_DOWN){
pointY=pointY+5;
if (pointY > getBounds().height){
pointY=getBounds().height;
}
}
if (key.getKeyCode() == key.VK_UP){
pointY=pointY-5;
if (pointY < 0){pointY=0;}
}
if (key.getKeyCode() == key.VK_LEFT){
pointX=pointX-5;
if (pointX < 0){pointX=0;}
}
if (key.getKeyCode() == key.VK_RIGHT){
pointX=pointX+5;
if (pointX > getBounds().width){
pointX=getBounds().width;
}
}

// Set a flag to erase the screen if Space is pressed.
if (key.getKeyCode() == key.VK_SPACE){
erase = true;
}


// Tell the panel that we need to redraw things.
repaint();
}

/* The following methods have to be here to comply
with the MouseListener interface, but we don't
use them, so their code blocks are empty. */
public void keyTyped(KeyEvent key){ }
public void keyReleased(KeyEvent key){ }

public static void main(String arg[]){
JFrame frame = new JFrame("Use Arrows to Draw, Space to Erase.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(640,480);

KeyPanel panel = new KeyPanel();
frame.setContentPane(panel);
frame.setVisible(true);

// We *must* do this to see KeyEvents.
panel.setFocusable(true);


// Initialize the drawing pointer.
panel.oldX=panel.getBounds().width/2;
panel.oldY=panel.getBounds().height/2;
panel.pointX=panel.oldX;
panel.pointY=panel.oldY;

}
}

Using this technique with the Simple Video Game Kernel would be similar. The VGKernel would extend KeyListener, register itself, and implement the KeyListener methods. But in those methods, rather than performing the operations that result from the keypress, as in this program, you would want to simply set a flag to show that the key has been pressed. Then, in your core game logic you would test to see whether the key has been pressed, and perform the appropriate actions.

That way the actions are performed at the appropriate time in your game, and not just whenever the key happens to get pressed. Reacting to a key when it is pressed is appropriate for a turn-based game, but not for a real-time game. In a real-time game the action happens according to the timing of the TimerTask that drives the game, which is why we just note that a key has been pressed, and wait until the TimerTask occurs to actually conduct the action related to that key. This would be similar to what we do with the space key here, which sets a flag to tell paintComponent() to erase the screen.

Give this program a try, see if you can extend it to allow the user to select colors to draw with or change the size of the drawing pen.
StumbleUpon

Thursday, August 26, 2010

Calling System Commands in Java

Let's suppose you want to run another program on your system from within Java. Personally, I first decided I wanted to do this for the sake of a prank. You may have more businesslike purposes in mind, yourself.

It's not too hard to do this since Java 1.5, which added the Process and ProcessBuilder classes.

Here's an example program that starts up Firefox at a particular website:
public class OpenSite{
public static void main(String arg[]){
try { Process p = new ProcessBuilder("firefox",
"http://beginwithjava.blogspot.com/").start(); }
catch(java.io.IOException io){ }
}
}

I've compressed the various parts of the action down to one line here:
Process p = new ProcessBuilder("firefox", "http://beginwithjava.blogspot.com/").start();

I'm creating an "anonymous" ProcessBuilder object, calling its start() method, which returns a Process, which I name simply "p".

The whole thing is wrapped up in a try...catch structure because javac wants to see us deal with any I/O errors that result. In this program, I just ignore them.

So you'll want to make sure that you either catch those errors and deal with them, or that they will be unimportant enough that they don't matter.

Also note that the Java program's process will last as long as the external program you call. So if you don't shut down this instance of the firefox process, you'll have Java still running.

If you want to see something fun you can do with this on Mac, check out my article on my other blog about adding speech to the Simple Video Game Kernel.
StumbleUpon

Wednesday, August 4, 2010

A Simple Java Video Game Kernel

Most video games run continuously, rather than waiting for user input before they do something. The heart of a video game of this sort is called the kernel. The kernel is running in the background, collecting user input and updating the display. It uses logic to determine if the game has been won or lost or otherwise control the state of the game.


A bouncing ball in the simple Java video game kernel program.
This simple kernel sends a ball bouncing around on the screen. Turn it into your own Pong, Breakout, or Tank clone.

To run this way, Threads are usually used to allow more than one thing to be going on at a time in a Java program. We've looked at a simple way of using threads before, the Timer class.

Here's a really, really simple video game kernel. It has all the basic elements of a video game.
/* A simple video game style kernel
   by Mark Graybill, August 2010
   Uses the Timer Class to move a ball on a playfield.
*/

// Import Timer and other useful stuff:
import java.util.*;
// Import the basic graphics classes.
import java.awt.*;
import javax.swing.*;

public class VGKernel extends JPanel{

// Set up the objects and variables we'll want.
public Rectangle screen, ball; // The screen area and ball location/size.
public Rectangle bounds;  // The boundaries of the drawing area.
public JFrame frame; // A JFrame to put the graphics into.
public VGTimerTask vgTask; // The TimerTask that runs the game.
public boolean down, right; // Direction of ball's travel.

// Create a constructor method that initializes things:
  public VGKernel(){
    super();
    screen = new Rectangle(0, 0, 600, 400);
    ball   = new Rectangle(0, 0, 20, 20);
    bounds = new Rectangle(0, 0, 600, 400); // Give some starter values.
    frame = new JFrame("VGKernel");
    vgTask = new VGTimerTask();
}
  // Create an inner TimerTask class that has access to the
  // members of the VGKernel.
  class VGTimerTask extends TimerTask{
    public void run(){
      moveBall();
      frame.repaint();
    }
  }

// Now the instance methods:
  public void paintComponent(Graphics g){
    // Get the drawing area bounds for game logic.
    bounds = g.getClipBounds();
    // Clear the drawing area, then draw the ball.
    g.clearRect(screen.x, screen.y, screen.width, screen.height);
    g.fillRect(ball.x, ball.y, ball.width, ball.height);
  }

  public void moveBall(){
  // Ball should really be its own class with this as a method.
    if (right) ball.x+=ball.width; // If right is true, move ball right,
    else ball.x-=ball.width;       // otherwise move left.
    if (down)  ball.y+=ball.height; // Same for up/down.
    else ball.y-=ball.width;
    if (ball.x > (bounds.width - ball.width)) // Detect edges and bounce.
      { right = false; ball.x = bounds.width -  ball.width; }
    if (ball.y > (bounds.height - ball.height))
      { down  = false; ball.y = bounds.height - ball.height;}
    if (ball.x <= 0) { right = true; ball.x = 0; }
    if (ball.y <= 0) { down  = true; ball.y = 0; }
  }

  public static void main(String arg[]){
    java.util.Timer vgTimer = new java.util.Timer();  // Create a Timer.
    VGKernel panel = new VGKernel(); // Create and instance of our kernel.
    
    // Set the intial ball movement direction.
    panel.down = true;
    panel.right = true;

    // Set up our JFRame
    panel.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    panel.frame.setSize(panel.screen.width, panel.screen.height);
    panel.frame.setContentPane(panel); 
    panel.frame.setVisible(true);

    // Set up a timer to do the vgTask regularly.
    vgTimer.schedule(panel.vgTask, 0, 100);
  }
}

This example can be expanded with methods to get control inputs, additional players on the playfield (like paddles), and logic to determine when someone scores.

The code here is far from perfect, but I've made some compromises to make things as simple as I could while still showing a full working example. Not that any code that runs and does what is supposed to is really bad, but there are other, better ways of doing this. But this works and is fairly easy to understand.

What the program does is create a JPanel that has an inner class (a class defined within itself) of VGTimerTask. The VGTimerTask is a kind of TimerTask, which can be scheduled to occur on a regular basis by a Timer. Since VGTimerTask is an inner class of VGPanel, it has access to all the members of VGPanel. This is critical. Without that, it wouldn't be able to access the ball and redraw the screen easily (it can still be done, but in a more complex way.)

Timer is a decent way of running a simple game, but more complex games should use some other timing mechanism. java.util.Timer is affected by a number of outside events, so to get smoother, more reliable timing you a timer like the one in the Java3D package would work better.

A Simple Improvement

There are many ways of improving on this basic example. One way that is very simple is to smooth the animation. The movement of the ball is pretty jerky. This is caused by both the distance that the ball moves each "turn", and by the time between screen updates. We can smooth out the animation by addressing both of these.

First, let's change moveBall() to shift the ball a smaller distance each time:
public void moveBall(){
  // Ball should really be its own class with this as a method.
    if (right) ball.x+=ball.width/4; // If right is true, move ball right,
    else ball.x-=ball.width/4;       // otherwise move left.
    if (down)  ball.y+=ball.height/4; // Same for up/down.
    else ball.y-=ball.width/4;
    if (ball.x > (bounds.width - ball.width)) // Detect edges and bounce.
      { right = false; ball.x = bounds.width -  ball.width; }
    if (ball.y > (bounds.height - ball.height))
      { down  = false; ball.y = bounds.height - ball.height;}
    if (ball.x <= 0) { right = true; ball.x = 0; }
    if (ball.y <= 0) { down  = true; ball.y = 0; }
  }
Now the ball is being moved only one quarter of its size each turn.

Next, change the Timer schedule to draw the screen every 20 milliseconds instead of every 100 milliseconds:
// Set up a timer to do the vgTask regularly.
    vgTimer.schedule(panel.vgTask, 0, 20);

Now you have a ball that moves a lot smoother.

I'll be expanding on this basic kernel and improving it in future articles, starting with Java Video game Programming: Game Logic
StumbleUpon

Sunday, July 20, 2008

Controlling Java's Graphics: paintComponent() and repaint()

Why do we put all our graphical drawing code into a paintComponent() method? It seems odd, since it would seem we should be able to simply stick some simple graphics commands into our main() method in a Java application and just get the drawing done. Where does paintComponent come from? If we never call it in our code, how does it get executed?

It seems like magic, doesn't it? You just sort of set it up and somehow it happens. Hopefully when and how we want it to. It seems like a vaguely disquieting form of magic, perhaps.

When Java does graphics, suddenly you're not in the strict control of the program that you are with command line applications. With graphics, your program is now interacting with the other parts of your computer's operating system. It's not just running in its own little corner of the machine. Now it's got a window out on that shared resource, the display, and the window has to interact properly with everything else that's on the display.

Think of it this way, if you are just driving around on private property all by yourself you don't have to worry about traffic. Off on your own stretch of road, with an unused parking lot or two to tool around in, you don't have to worry about sharing. You can cross the center line, pull on and off the road without signalling, you don't even need a license so long as you don't go on a public road.

But once you head for the public roads and freeway, you've got to share. The rules matter. It gets more complicated than buzzing around in a go-cart or whatever on private property. And things happen that you don't have any direct control over, like red lights and merging traffic.

When you move your program on to the display in Java, you don't have to do everything on your own as you would have to in a car. Java's graphics system takes care of a lot for you. Unfortunately this means your code starts looking like magic. Methods get called without you doing the calling. But it's OK. All you need to know is what to expect.

The paintComponent() method redraws your graphics area. In our examples so far this has been a JPanel. There are two ways paintComponent() can get called. One is automatic, the other is up to you.

The automatic way is what we've used so far. The computer's window manager automatically calls for your program to redraw its graphics whenever a window it owns appears to need redrawing. The window manager can decide this for any of a number of reasons. Such as when the window initially appears on screen. Or if the window has been covered up in part or in whole by another window on screen, and the covered part has just been uncovered. Maybe the window had been minimized, and has just been restored.

When these sort of things happen, the Java Runtime Environment calls the paint() method for your container. In our examples so far, our container has been a JFrame. It will be a "heavyweight" component (see the JFrames article for a brief discussion on this.) Once the container redraws itself, it'll pass the command down to its children, that is, the lightweight components that live inside it. A lightweight component from the Swing package uses the paintComponent() method to redraw itself. So that's what gets called. Shazam! It's like magic!

This means you want to set up paintComponent() to draw things the way you want them when it gets called. If you're doing drawings that don't change, like the examples we've done to date, then you don't need to look up any information. If you're doing anything animated or that otherwise changes over time, you need to have paintComponent() be able to look things up at the time of drawing to properly reflect conditions in the drawing.

Now, let's say you've changed something in your program and you want to redraw to show the change. You probably don't want to wait until the window manager thinks your window needs redrawing. If nobody is changing things on the screen otherwise, it may not redraw until way too late!

Does that mean you put a call to paintComponent() in your program? No! You would be taking a chance of breaking something if you did. You want to start from the top, like the Java Runtime Environment did. In your case, you want to call repaint(). This will take things from the top. It also handles some possibilities that jumping in and calling paintComponent() on your own will not.

Like, let's say both you and the window manager decide to redraw at the same time. If you bypass repaint() you'll be slowing down your program by making it repaint twice when it really only needs to redraw once. When you call repaint(), Java catches this for you and saves you some computer time by only redrawing once. It'll also catch redraw requests made while the redrawing is going on and deal with them appropriately. Your paintComponent() method will get called in its own turn when you use repaint().

So, if you have new information you want depicted on screen, use repaint().

Put all your drawing inside paintComponent() and let the system take care of knowing when to call it otherwise. Give paintComponent() the ability to get the information it needs to draw things the way you want them now. If you're getting ahead of what I've written here, and aren't sure how to get through the Object Oriented barriers, look up "inner classes" for a start. It gives you a way to get the information where you need it when you need it.
StumbleUpon

Saturday, July 19, 2008

Very Basic Java Graphics: 3 Examples

We're going to build up a graphics app from something so basic it doesn't really work, like the example from Java Graphics--Start with a JFrame and building to something more sophisticated. In the JFrame article and in A Most Basic Graphics App I've avoided the use of comments in the code to keep it shorter. In these examples I'm going to include comments in the code to describe what's happening. So don't be scared of the length of these examples, most of what's there is just comments, which Java ignores. They're there just for humans.
/* BasicFrame.java

This is a really simple graphics program.
It opens a frame on the screen with a single
line drawn across it.

It's not very polished, but it demonstrates
a graphical program as simply as possible.mag-27Apr2008
*/

// Import the basic graphics classes.
import java.awt.*;
import javax.swing.*;

public class BasicFrame extends JFrame{

// Create a constructor method
public BasicFrame(){
// All we do is call JFrame's constructor.
// We don't need anything special for this
// program.
super();
}

// The following methods are instance methods.
/* Create a paint() method to override the one in JFrame.
This is where the drawing happens.
We don't have to call it in our program, it gets called
automatically whenever the frame needs to be redrawn,
like when it it made visible or moved or whatever.*/
public void paint(Graphics g){
g.drawLine(10,10,150,150); // Draw a line from (10,10) to (150,150)
}

public static void main(String arg[]){
// create an identifier named 'window' and
// apply it to a new BasicFrame object
// created using our constructor, above.
BasicFrame frame = new BasicFrame();

// Use the setSize method that our BasicFrame
// object inherited to make the frame
// 200 pixels wide and high.
frame.setSize(200,200);

// Make the window show on the screen.
frame.setVisible(true);
}
}

This example draws a line on the JFrame. The window decorations take up some of our drawing space, so the title bar may cover some of our line. With some JVMs the background area of the JFrame won't be cleared before you draw. Also, when you close the window using the close button, the application doesn't shut down. For many applications on Mac OS X this is normal behavior, but on other OSes, and even many applications under OS X it's normal to expect an application to close down completely if you click the close button on the last open window (for applications that have multiple windows) or the close button on the main window for other applications.

So here's our next example, where we take care of that last problem:
/* CloseFrame.java
This is a really simple graphics program.
It opens a frame on the screen with a single
line drawn across it.

We're starting to add a little bit of polish
here--we make the program close nicely when
the close box is clicked, rather than just
sort of hanging around half-dead.
mag-28Apr2008
*/

// Import the basic graphics classes.
import java.awt.*;
import javax.swing.*;

public class CloseFrame extends JFrame{

// Create a constructor method
public CloseFrame(){
// All we do is call JFrame's constructor.
// We don't need anything special for this.
super();
}

// The following methods are instance methods.

/* Create a paint() method to override the one in JFrame.
This is where the drawing happens.
We don't have to call it in our program,
it gets called automatically whenever the
frame needs to be redrawn, like when it is
made visible or moved or whatever.
*/
public void paint(Graphics g){
g.drawLine(10,10,150,150); // Draw a line from (10,10) to (150,150)
}

public static void main(String arg[]){
BasicFrame frame = new BasicFrame();
// This uses a constant EXIT_ON_CLOSE that's a member of JFrame.
// The constant is passed to the setDefaultCloseOperation method
// of our frame object, which is a CloseFrame object,
// which inherits the method from its parent JFrame.
// It makes the program exit (close completely) when we click
// the close button.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200,200);frame.setVisible(true);
}
}

The magic line that makes the application exit when we click the close button is the one that reads: frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);. We can tell that EXIT_ON_CLOSE is a type of variable called a "constant" because the name follows the convention of being written in all capital letters. So we're not YELLING when we say "EXIT_ON_CLOSE" we're using the value stored in EXIT_ON_CLOSE as part of the JFrame class.
A JFrame has this constant available because it implements the interface WindowConstants. By implementing this interface, in essence, the JFrame class of objects promise to do the right thing if one of these constants is passed to a method that handles it, in this case setDefaultCloseOperation.

Our final example for this entry goes one big step further:
/* BasicJPanel.java
This is a somewhat more sophisticated drawing program.
It uses a new child of JPanel as the drawing surface
for a JFrame, to avoid the problems with drawing
directly on a JFrame.

A custom JPanel child class called BasicJPanel is created
with its own paintComponent method, which contains our
drawing code.

A generic JFrame is then created to hold the BasicJPanel
object, the BasicJPanel is created, made into the JPanel's
content pane, and our paintComponent method is called
automatically. *Whew!*
mag-28Apr2008
*/

// Import the basic graphics classes.
import java.awt.*;
import javax.swing.*;

public class BasicJPanel extends JPanel{

// Create a constructor method
public BasicJPanel(){
super();
}

// The following methods are instance methods.

/* Create a paintComponent() method to override the one in
JPanel.This is where the drawing happens. We don't have
to call it in our program, it gets called automatically
whenever the panel needs to be redrawn, like when it is
made visible or moved or whatever.
*/
public void paintComponent(Graphics g){
g.drawLine(10,10,150,150); // Draw a line from (10,10) to (150,150)
}

public static void main(String arg[]){
JFrame frame = new JFrame("BasicJPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200,200);

// Create a new identifier for a BasicJPanel called "panel",
// then create a new BasicJPanel object for it to refer to.
BasicJPanel panel = new BasicJPanel();

// Make the panel object the content pane of the JFrame.
// This puts it into the drawable area of frame, and now
// we do all our drawing to panel, using paintComponent(), above.
frame.setContentPane(panel);
frame.setVisible(true);
}
}

Here, we've added a JPanel inside the drawable area of our JFrame. This means that if we start drawing at 0,0 we'll actually be drawing somewhere we can see it, it won't be hidden by the window decorations.

The other big change is the change of our drawing method's name from paint() to paintComponent(). This is because we changed from a JFrame to a JPanel. If you take a look at JPanel in the API Specification you'll see that it extends JComponent. This family of objects uses paintComponent() to manage drawing.

This last example is a good starting point for any graphical operation. In future examples, I'll be extending it further to add additional features.
StumbleUpon

Tuesday, July 15, 2008

Drawing Lines

In A Most Basic Graphics App we had the framework of a simple graphics application. We trimmed it down a little, too much really, in Start With a JFrame. The JFrame alone doesn't accomodate graphics as well as we would like. The "window decorations"--the title bar, the frame around the window, close button and so on--all cover part of our drawing area. Likewise, there are other problems that crop up on different JVMs.

So we'll use the BasicPanel.java program from A Most Basic Graphics App to build on now.

We're going to concern ourselves with the part of the program that does the actual drawing:
g.drawLine(10,10,150,150); // Draw a line from (10,10) to (150,150)

In particular, we're going to focus on those four numbers inside the parentheses. What are they? Where do they come from? How can we pick numbers that will let us draw what we want, and what are the limits on what we can put in there?

First, let's look at what our limits are. At the low end, we have the number zero. Computers start counting at zero, and that's the low end number for what we can enter here and expect results. You can put a negative number in here, but unless you do some other things we're not going into here, negative numbers aren't going to do you any good.

For the high number, you can go up to the limits of the type, if you like. In this case we're calling drawLine(int, int, int, int), so we can go up to the limits of an int, or 2147483647, and not cause a problem so far as Java is concerned. We humans like to see our results, though. There's another line of BasicPanel we need to consider. That's this one:
frame.setSize(200,200);
This is setting the size of our JFrame (creatively named "frame") to 200 pixels wide and 200 pixels high. Since the JPanel we're drawing to is inside this JFrame, we know that the highest point we're going to see is less than this. How much less varies. It's based on how wide big the window decorations are on the JFrame, and this varies by operating system, and by the user's settings. But we definitely know that anything over 200 on the high end is going to be invisible. Higher numbers won't affect Java or your computer. You won't have a line that shoots out of its window and across your desktop if you make the numbers too high. You just won't see anything outside the JPanel area on which we're drawing.

We can find out exactly how large our drawing area is by using the getClipBounds() method of the Graphics class. Feel free to experiment with it, but for now let's get back to talking about the four numbers we use with drawLine and what they do. Just saying we have a high limit of 200 on those numbers is good enough for now.

OK, so we can use numbers from 0 to somewhere short of 200 in any of those four locations and expect results.

A Pair of Pairs

The four numbers in drawLine aren't just four numbers, they're two pairs of number. The first two numbers are the first pair, the third and fourth numbers are the second pair. Each pair of numbers is a Cartesian coordinate. If you don't remember or haven't studied this in Geometry class, don't sweat it. We'll suss things out well enough here.
g.drawLine(10,10,150,150); // Draw a line from (10,10) to (150,150)
Notice how in the comment I say we're drawing a line from (10, 10) to (150, 150). Notice the first two numbers in g.drawLine() are 10 and 10, and the second two numbers are 150 and 150. This Means Something. ;)

The first pair marks the starting point for our line, the second pair marks the ending point.

The first number in each pair says how far left or right we want that point. The second number in each pair says how far up or down we want that point.

On left and right, 0 is all the way to the left. The higher the number, the farther over to the right we'll be. In our case, we can go up to 200 (almost.) A number of about 190 will probably take us all the way to the right of our drawing area.

On up and down, 0 is all the way to the top. The higher the number, the lower we'll go. A number of about 185 or so will take us all the way to the bottom of our drawing area.

If we want to draw a line all the way across our drawing area, instead of just partway across, we can replace
g.drawLine(10,10,150,150); // Draw a line from (10,10) to (150,150)
with
g.drawLine(0,0,200,200);
This will actually "go over" the edge of our drawing area, but it won't matter. Open up BasicPanel in your editor, make this change, compile it and run it.

Fine, we've mastered drawing a line from the top left to the bottom right. We're not exactly drawing starships yet, are we?

What if we change the pairs of numbers around? Open up your editor and make this change to the drawLine() statement:
g.drawLine(200,200,0,0);
Once you compile and run, what do you see? It looks the same, right? That's because we drew a line between the same two points, we just drew from bottom right to top left this time. OK, I hear you saying "Borrrringgg!" Let's move on.

Horizontal Lines

If we want a line to be horizontal, both the up-and-down numbers need to be the same. This means the second number in each pair, the second and fourth numbers. Add the following line to BasicPanel right after your other drawLine() statement:
g.drawLine(10,50,200,50);
Compile and run, and now you have a horizontal line. Notice the second and fourth numbers are the same. If you want to move the horizontal line up or down, change the number in the second and fourth position:
g.drawLine(10,20,200,20); // A higher horizontal line
g.drawLine(0,0,200,200); // A lower horizontal line
The higher the number you put in the second and fourth positions the lower the horizontal line will be. Go ahead and add these lines to your program, one at a time, and compile and run.

Vertical Lines

Now let's try vertical lines. For these, the first and third numbers (the left-right numbers) need to be the same:
g.drawLine(50,0,50,200); // A vertical line.
Change the 50s to some other number to move the vertical line left or right.

Starting and Ending

Now we can draw multiple lines to build up objects. By starting and ending the lines at the same points, we can make them meet up, and use the individual lines to build up objects. using our vertical and horizontal lines, we can make up squares and rectangles, or draw pictures that look like they're off an Etch-a-Sketch. ;)

Open up BasicPanel and replace all the existing drawLine() statements with the following:

g.drawLine(50,20,150,20); // Draw a horizontal line from (50,20) to (150,20)
g.drawLine(150,20,150,150); // Draw a vertical line from (150,20) to (150,150)
g.drawLine(150,150,20,150); // Draw a horizontal line from (150,150) to (20,150)
g.drawLine(20,150,50,20); // Draw a vertical line from (20,150) to (50,20)
Notice how the points we use match up (look at the pairs in the comments.) The last point is the same as the first to close the box.

Now, if we just wanted to draw boxes Java actually has a way to do this more efficiently. But what we're focusing on here is coordinates and how to use them.

Play around with different points and see what effect you get. Try drawing a triangle. Try drawing different sloping lines, both ones that slope down from left to right and ones that slope up. Remember, when you slope up the point on the right is going to have a second (up-down) number lower than the point on the left.

Once you play around for a while, you'll get the hang of it. If you want a larger screen area to play with, enlarge the numbers in the setSize() statement. Try this for a start:
frame.setSize(480,480);
This will give you more room to play it. Now you can take numbers up to about 480 before they go out of view. Try using getClipBounds() to find out just how large a number you can get. If you can't get it, don't sweat it, I'll cover it in a future post, or you can do an internet search to find an example in someone else's program, or jump into a Java newbie forum and ask.
StumbleUpon

Wednesday, July 2, 2008

A Most Basic Graphics App

Here's a simple graphics application in Java. It's about as simple as you can get while doing graphics.


// Import the basic graphics classes.
import java.awt.*;
import javax.swing.*;

public class BasicPanel extends JPanel{

// Create a constructor method
public BasicPanel(){
super();
}

public void paintComponent(Graphics g){
g.drawLine(10,10,150,150); // Draw a line from (10,10) to (150,150)
}

public static void main(String arg[]){
JFrame frame = new JFrame("BasicPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200,200);

BasicPanel panel = new BasicPanel();
frame.setContentPane(panel);
frame.setVisible(true);
}
}

Key points to note:
The line that reads g.drawLine(10,10,150,150); // Draw a line from (10,10) to (150,150) is the line that does the actual drawing. If you want to draw something else, or draw more things, replace this line with your own statements or add additional statements after this line. To see what you can do, check out the Graphics class in the Java API reference.

All of the items in blue,BasicPanel, need to match. You can just as well make it Foodle, but all of these need to match since this is the name of your class (and program.) Note that if you change it to Foodle, you need to save it in a file called Foodle.java, just as the file above needs to be saved in a file named BasicPanel.java

If you want to change the size of the window, change the 200,200 in the line reading frame.setSize(200,200); to some other number. Smaller numbers will make a smaller window, bigger numbers make a bigger window. The first number is how many pixels across it will be, the second number is how many pixels high it is.

Enjoy!

Technorati Profile
StumbleUpon

The Basic Program Skeleton

The basic skeleton of a Java application goes as follows:

public class YourProgramName{
public static void main(String arg[]){

Your Program Goes Here

}
}

YourProgramName gets replaced by your actual program's name. The program must be stored in a file named YourProgramName.java

The actual code for your program goes in place of Your Program Goes Here.

More complicated programs have more to them than this. For example, you should have your own classes in their own files that contain most of your program logic if you are writing a long program. But this is the most direct and basic structure for a Java program.

The word arg can be whatever you choose to make it, by the way. If your program needs to get information from the system environment, just make sure that the name is the same as what you use in your program.
StumbleUpon

Thursday, June 19, 2008

main()

There are two basic types of Java programs: applets and applications.* Applets run through a browser or a special program called AppletViewer. Applications are stand-alone programs that run on the same system they're stored on, like most traditional programs. Since there's lots of information elsewhere on applets, we'll concern ourselves mostly with applications.

Every application has a special method called main(). The main() method marks the starting point in the program for the Java Virtual Machine. Here's a short example program:

public class Hello{
public static void main(String arg[]){
System.out.println("Hello");
}
}

When this program is compiled using javac then run with the command
>java Hello
the JVM loads Hello.class and looks in it for the main() method, then starts executing the code inside main()'s code block.

Now, you'll notice there's a bunch of other stuff with main():
public static void main(String arg[]){

Because of how Java works, that stuff has to be there in a Java application. You can't just put "main(){" on the line by itself. The other stuff has a purpose, though it all looks very confusing, and certainly it looks like a lot of extra junk in a short program.

public allows the method to be accessed from outside the class (and its package--we'll get into that later.) If you leave out public, the JVM can't access main() since it's not available outside of Hello.

static says that this is the one and only main() method for this entire class (or program). You can't have multiple main()s for a class. If you leave static out, you'll get an error.

void says that main() doesn't pass back any data. Since the JVM wouldn't know what to do with any data, since it's not set up to accept data from main(), main() has to be of type void, which is to say that it's a method that doesn't pass any data back to the caller. If you leave this out main() won't have a data type, and all methods have to have a data type, even if it's void.

Inside main()'s parentheses is String arg[]. This is a way for the program to accept data from the host system when it's started. It's required that main() be able to accept data from the system when starting. And the data must be in the form of an array of Strings (or a variable-length list of Strings as of Java 5, but that's something we'll save for later.) The name "arg" can be whatever you want to make it. It's just a name I've given the array. It could just as well be:
public static void main(String fred[]){

I'd just have to be sure to use fred whenever I wanted to access the information that the system has passed to my application when it started, instead of arg.

Finally, after the parentheses, comes the open curly brace { that marks the start of main()'s code block.




* There are other types as well, but I'm limiting my discussion to Java SE/client side stuff for now.
StumbleUpon