java console apps made easy - codeproject

Upload: gfgomes

Post on 22-Feb-2018

215 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/24/2019 Java Console Apps Made Easy - CodeProject

    1/8

    Articles Languages Java Beginners

    David MacDermot, 10 Feb 2012 CPOL

    Java Console apps made easy

    This article describes the creation of a Java console type application.

    Download demo - 192 KB

    Download source - 22.4 KB

    Contents

    IntroductionHow to use this Java Console

    How to wire up a console

    Making a custom block caret

    Extra! Extra! The menu system.

    4.88 (16 votes)

    Console apps made easy - CodeProject http://www.codeproject.com/Articles/328417/Java-Console-apps-made...

    8 25/02/2016 14:24

  • 7/24/2019 Java Console Apps Made Easy - CodeProject

    2/8

    Final comments

    History

    Introduction

    The humble console app: I write them all the time creating one off tests to explore new coding ideas. I'll even string up quick,

    menu based, test applications for testing remote device communications and command sets, where the number of commands

    can grow during the product development cycle. The advantage of course, is that to grow the application I only have to add a

    menu item and an event handler in the code. That is far preferable to squeezing more fields onto an already crowded Windows

    Forms application. Sometimes you don't know what you have till it's gone.

    I decided to tackle Java this year and get a feel for the language and tools. I usually take on a new (for me) language by

    translating an application I have written into the new language and stumbling through the thorny issues as I encounter them. I

    was surprised at how many of the things I took for granted in C# turned out to be rather hard to do in Java; case in point, the

    console app.

    The application I chose to port to Java happened to be a console based menu driven application. Porting the menu code was

    fairly straightforward once I figured out how to substitute an interface and nested Java class for a C# delegate in order to obtain

    callback behavior. The real headache lay in the performance of the application's menu code in an actual Windows console

    instance.

    Java applications utilize STDIN, STDOUT, and STDERRstreams but do not own the console instance displaying the streams.Since Java aims at a broad range of Operating Systems, it doesn't include support for clearing the screen. I tried a number of

    work-a-rounds to get my application to function as intended without acceptable results.

    I was about to give up when I took a different track and considered duplicating console functionality in a Java GUI widget. This

    turned out to be more promising. There were quite a few examples of redirecting STDOUTand STDERRto a JtextAreabutI was unable to find one that also successfully copied keyboard input to STDIN. What I did find was quite a bit of chatter fromother developers indicating a desire for such a component.

    I began to test the various code solutions and snippets that I had found and settled on one particularly robust example[^]. I

    then added some code to pipe keyboard characters to STDIN, added a public clear()method, and some properties tocustomize the look and feel of the console. Finally I figured out how to create a custom blinking block cursor for

    JavaConsoleto round things off.

    How to use this Java Console

    Minimally all that is necessary to use this Java Console in your project is to declare an instance of the JavaConsoleclass.

    public static voidmain(String[] args) {

    newJavaConsole();

    scanner = newScanner(System.in);

    System.out.println("Hello World!"); scanner.nextLine();

    System.exit(0);}

    Here is an example of how to customize the look of the Java Console.

    public static voidmain(String[] args){

    Scanner scanner = newScanner(System.in);

    JavaConsole console = newJavaConsole();

    //Customize the console text field

    console.setBackground(Color.WHITE); console.setForeground(Color.BLACK);

    Console apps made easy - CodeProject http://www.codeproject.com/Articles/328417/Java-Console-apps-made...

    8 25/02/2016 14:24

  • 7/24/2019 Java Console Apps Made Easy - CodeProject

    3/8

    console.setFont(newFont ("Ariel", Font.BOLD, 12));

    //Customize the console frame

    console.setTitle("Hello World Program");

    Image im = Toolkit.getDefaultToolkit().getImage("../images/MyIcon.png"); console.setIconImage(im);

    System.out.println("Hello World!"); scanner.nextLine();

    System.exit(0);

    }

    Here is an example using the JavaConsole.clear()method to clear the screen between chunks of text.

    public static voidmain(String[] args){

    Scanner scanner = newScanner(System.in); JavaConsole console = newJavaConsole();

    System.out.println("It was a dark and stormy night; the rain fell in torrents, except at "+"occasional intervals, when it was checked by a violent gust of wind "+"which swept up the streets (for it is in London that our scene lies), "+"rattling along the house-tops, and fiercely agitating the scanty flame "+"of the lamps that struggled against the darkness. Through one of the "+"obscurest quarters of London, and among haunts little loved by the "+"gentlemen of the police, a man, evidently of the lowest orders, was "+"wending his solitary way.");

    scanner.nextLine();

    console.clear(); System.out.println(

    "He stopped twice or thrice at different shops and houses of a description " +"correspondent with the appearance of the quartier in which they were situated, "+

    "and tended inquiry for some article or another which did not seem easily "+"to be met with. All the answers he received were couched in the negative; "+"and as he turned from each door he muttered to himself, in no very elegant "+"phraseology, his disappointment and discontent. At length, at one house, "+"the landlord, a sturdy butcher, after rendering the same reply the inquirer "+"had hitherto received, added, \"But if this vill do as vell, Dummie, it is "+"quite at your sarvice!\"");

    scanner.nextLine();

    System.exit(0);

    }

    Finally, here's a comprehensive list of Java Console custom features.

    console.getBackground();console.getForeground();console.getFont();

    console.setBackground(Color);console.setForeground(Color);console.setFont(Font);

    console.setTitle(title);console.setIconImage(Image);

    console.clear();

    How to wire up a console

    Console apps made easy - CodeProject http://www.codeproject.com/Articles/328417/Java-Console-apps-made...

    8 25/02/2016 14:24

  • 7/24/2019 Java Console Apps Made Easy - CodeProject

    4/8

    The first thing we need to do is to redirect STDOUTand STDERRto our JtextArea. The code class I started with achievedthis in the following manner.

    Establish some Piped Input Streams.1.

    private finalPipedInputStream pin=new PipedInputStream();private finalPipedInputStream pin2=new PipedInputStream();

    Hook the input streams up to the associated output streams.2.

    PipedOutputStream pout=new PipedOutputStream(this.pin);PipedOutputStream pout2=new PipedOutputStream(this.pin2);

    Redirect System STDOUTand STDERRto these output streams.3.

    System.setOut(newPrintStream(pout,true));System.setErr(newPrintStream(pout2,true));

    Spin up some threads to read from the Piped Input Streams.4.

    //Declarations

    privateThread reader;privateThread reader2;

    //In the class constructor

    reader=new Thread(this);reader.setDaemon(true);reader.start();

    reader2=new Thread(this);reader2.setDaemon(true);reader2.start();

    Monitor STDOUTand STDERRappending the text to the JtextArea.5.

    public synchronized voidrun(){

    try {

    while(Thread.currentThread()==reader) {

    try{ this.wait(100);}catch(InterruptedException ie) {}if(pin.available()!=0)

    {Stringinput=this.readLine(pin);

    textArea.append(input); textArea.setCaretPosition(textArea.getDocument().getLength());//DWM

    02-07-2012 }

    if(quit) return; }

    while(Thread.currentThread()==reader2) {

    try{ this.wait(100);}catch(InterruptedException ie) {}if(pin2.available()!=0)

    {Stringinput=this.readLine(pin2);

    textArea.append(input); textArea.setCaretPosition(textArea.getDocument().getLength());//DWM

    02-07-2012 }if(quit) return;

    }} catch(Exception e)

    {

    Console apps made easy - CodeProject http://www.codeproject.com/Articles/328417/Java-Console-apps-made...

    8 25/02/2016 14:24

  • 7/24/2019 Java Console Apps Made Easy - CodeProject

    5/8

    textArea.append("\nConsole reports an Internal error."); textArea.append("The error is: "+e); textArea.setCaretPosition(textArea.getDocument().getLength());//DWM 02-07-2012 }}

    Now that we have STDOUTand STDERRpiped to the JtextArea, we need to monitor keyboard input to the JtextAreaand copy the characters to STDIN. I modified the original code to do so as follows:

    Establish a Piped Output Stream for reading keyboard input.1.

    private finalPipedOutputStream pout3=new PipedOutputStream();

    Hook the output stream to an associated input stream and redirectSTDINto this input stream.2.

    System.setIn(newPipedInputStream(this.pout3));

    Add a KeyListenerand copy out keyboard input as it arrives.3.

    textArea.addKeyListener(newKeyListener() {

    public voidkeyPressed(KeyEvent e) {}

    public voidkeyReleased(KeyEvent e) {}

    public voidkeyTyped(KeyEvent e) {try{ pout3.write(e.getKeyChar()); } catch(IOException ex) {}

    }});

    Making a custom block caret

    The default caret of the JtextAreais a vertical bar but I wanted a prompt that was a bit more prominent. It turns out that thisfeature is customizable and I found some examples on how to do this. Refer to A custom caret class[^] and Fancier custom

    caret class[^] to get an idea of how it's done. Here is the code for my flashing block caret:

    public classBlockCaret extendsDefaultCaret {

    private static final longserialVersionUID = 1L;

    /**

    * @brief Class Constructor

    */

    publicBlockCaret() {

    setBlinkRate(500);// half a second }

    /* (non-Javadoc)

    * @see javax.swing.text.DefaultCaret#damage(java.awt.Rectangle)

    */

    protected synchronized voiddamage(Rectangle r) {if(r == null)

    return;

    // give values to x,y,width,height (inherited from java.awt.Rectangle)

    x = r.x; y = r.y; height = r.height;

    // A value for width was probably set by paint(), which we leave alone.

    // But the first call to damage() precedes the first call to paint(), so

    // in this case we must be prepared to set a valid width, or else

    // paint()

    // will receive a bogus clip area and caret will not get drawn properly.

    Console apps made easy - CodeProject http://www.codeproject.com/Articles/328417/Java-Console-apps-made...

    8 25/02/2016 14:24

  • 7/24/2019 Java Console Apps Made Easy - CodeProject

    6/8

    if(width

  • 7/24/2019 Java Console Apps Made Easy - CodeProject

    7/8

    private static voidHandleItem2{ Console.WriteLine("You chose item 2.\n"); Console.Read();}

    Then I add them to the Menulike so:3.

    menu = newMenu();

    menu.Add("Item 1", newMenuCallback(HandleItem1));menu.Add("Item 2", newMenuCallback(HandleItem2));menu.Show();

    Java does not allow for the passing of function pointers and thus delegates. Instead this behavior is restricted to typed object

    pointers and thus the class interface becomes the Java equivalent of the delegate. Here's how it's done in Java.

    I declare an interface (a typed object pointer):1.

    public interfaceMenuCallback extendsEventListener {public voidInvoke();

    }

    Next I create some event handlers for menu picks:2.

    private static voidHandleItem1 { System.out.println("You chose item 1.\n."); scanner.nextLine();}

    private static voidHandleItem2 { System.out.println("You chose item 2.\n."); scanner.nextLine();}

    Then I add them to the Menulike so:3.

    Menu menu = newMenu(console);menu.add("Item 1", newMenuCallback() { public voidInvoke() { HandleItem1(); } });menu.add("Item 2", newMenuCallback() { public voidInvoke() { HandleItem2(); } });menu.show();

    It's a bit more verbose since we are in effect, having to wrap our function pointer in a class.

    Final commentsThe menu system does not work well in the standard console when used in a Java application. The version of Menuclassincluded here should only be used in this Java Console. This Java Console may be used anytime you want to have a console

    window that is owned by your application. While it features a clear()method for clearing the screen it does not, howeverhandle DOS commands or provide a command prompt.

    History

    Feb 09, 2012: Version 1.0.0.0.

    License

    Console apps made easy - CodeProject http://www.codeproject.com/Articles/328417/Java-Console-apps-made...

    8 25/02/2016 14:24

  • 7/24/2019 Java Console Apps Made Easy - CodeProject

    8/8

    Permalink| Advertise | Privacy| Terms of Use| Mobile

    Web04 | 2.8.160217.1 | Last Updated 10 Feb 2012Selecione o idioma

    Article Copyright 2012 by David MacDermot

    Everything else Copyright CodeProject, 1999-2016

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

    Share

    About the Author

    You may also be interested in...

    Lucene.Net ultra fast search for

    MVC or WebForms site =>

    made easy!

    SharePoint Governance: A

    definitive Guide

    NHibernate Made Simple SAPrefs - Netscape-like

    Preferences Dialog

    Processes and threads made

    easy

    Window Tabs (WndTabs) Add-In

    for DevStudio

    Comments and Discussions

    12 messageshave been posted for this article Visit http://www.codeproject.com/Articles/328417/Java-Console-

    apps-made-easyto post and view comments on this article, or click hereto get a print view with messages.

    No Biography provided

    David MacDermotUnited States

    Console apps made easy - CodeProject http://www.codeproject.com/Articles/328417/Java-Console-apps-made...