Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

View RSS Feed

Tjstretch

Windows 7 Console

Rate this Entry
Well I encountered a problem recently that a lot of people were complaining about when I Googled, which is a lot of the time I like to share some basic console programs with only have functional java installed, and on windows 7 the command I used to use to open command prompt [Runnable.getRunnable().exec("exec /k run.bat")] no longer works due to security precautions. So I made a simple class that creates the functional equivalent of console for programs. Possibly the size of the console might need to be tweaked for each program, but that's not tricky. I've only tested this on one program, and here is what I did to convert the program completely out of System.out.

An image:

consoleGui1.jpg

Put the ConsoleGUI inside the package of your class(es) and, if necessary, set it's package.

First - make a private static global variable of type ConsoleGUI.TAScanner and call it whatever your old Scanner was called
private static ConsoleGUI.TAScanner scanner
Second - Make another variable of ConsoleGUI.TAPrintStream. This is your new output stream. (Can't currently use printf)
private static ConsoleGUI.TAPrintStream out
Third - Using your IDE replace all calls to System.out( with out(
Fourth - Remove your old Scanner.

Fifth - In your main method add these lines (Unless you used different variable names)
ConsoleGUI.toGUI();
scanner = ConsoleGUI.getScanner();
out = ConsoleGUI.getStream();
Recompile, and your done!

The class
package me.timothy.consolegui;
 
import java.util.Scanner;
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.PrintStream;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.File;
import java.io.IOException;
import java.util.InputMismatchException;
import javax.swing.text.DefaultCaret;
 
/**
 * Turns a console program into a basic GUI program, useful
 * for Window 7 programs that are unable to open command
 * prompt with a .jar  All a class has to do in order to use 
 * this program is call the static method toGUI(), a special Scanner is
 * acquirable instead of System.in
 * (Attrievable by a call to getScanner(), which is static)
 * By a call to saveSaveText(true),  it will save the calls to out and scanner,
 * however it does not throw any exceptions and may cause lag if
 * there are a lot of System.out calls.
 * 
 * @author Timothy Moore
 */
public class ConsoleGUI extends JFrame
{
  private static volatile boolean saveRun = false;
  /**
   * The ConsoleGUI
   */
  private static ConsoleGUI gui;
  /**
   * The Scanner being used
   */
  private TAScanner scanner;
  /**
   * The stream being used
   */
  private TAPrintStream stream;
  /**
   * The main text area, where calls to System.out go
   */
  private JTextArea txtArea;
  /**
   * Where the user enters information
   */
  private JTextField userField;
  /**
   * The submit button, not actually necessary
   */
  private JButton submit;
  /**
   * The JScrollPane wrapper
   */
  private JScrollPane sPane;
  /**
   * Creates the GUI
   */
  private ConsoleGUI()
  {
    setSize(350, 350);
    setTitle("Console GUI");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setLayout(new BorderLayout());
 
    txtArea = new JTextArea();
    txtArea.setEditable(false);
    sPane = new JScrollPane(txtArea);
    add(sPane, BorderLayout.CENTER);
    userField = new JTextField();
    userField.setEditable(false);
    userField.setActionCommand("submit");
    submit = new JButton("Submit");
    submit.setActionCommand("submit");
    JPanel bot = new JPanel();
    bot.setLayout(new BorderLayout());
    bot.add(userField, BorderLayout.CENTER);
    bot.add(submit, BorderLayout.EAST);
    add(bot, BorderLayout.SOUTH);
  }
  /**
   * Sets the program to use the ConsoleGUI instead of the regular 
   * Console
   */
  public static void toGUI()
  {
    try
    {
      SwingUtilities.invokeAndWait(new Runnable() {
        @Override
        public void run()
        {
          gui = new ConsoleGUI();
          gui.stream = gui.createPrintStream();
          gui.setVisible(true);
        }
      });
    }catch(Exception exc)
    {
      handleException("Failed to convert to gui", exc, saveRun);
    }
 
  }
 
  public static void setConsoleTitle(String tit)
  {
    gui.setTitle(tit);
  }
  /**
   * Creates a TAPrintStream based on the text area
   */
  private TAPrintStream createPrintStream()
  {
    return new TAPrintStream(txtArea);
  }
  /**
   * @return a new TAScanner
   */
  private TAScanner createScanner()
  {
    return new TAScanner(userField, submit);
  }
  /**
   * @return the print stream
   */
  public static TAPrintStream getStream()
  {
    return gui.stream;
  }
  /**
   * Sets if it is saving the text, by default false
   * @param b if it should save text
   */
  public static void setSaveText(boolean b)
  {
    saveRun = b;
  }
  /**
   * @return the scanner to use.  Has most methods of Scanner 
   * @throws NullPointerException if called before toGUI
   */
  public static TAScanner getScanner()
  {
    if(gui.scanner == null)
      gui.scanner = gui.createScanner();
    return gui.scanner;
  }
 
  /**
   * Handles an exception with the specified message and
   * underlying throwable.  This method will handle all
   * exceptions appropriately. 
   * 
   * This method will return normally.
   * 
   * @param msg the message, can be null.
   * @param exc the exception, cannot be null
   * @param saveToFile if file io should be attempted.
   */
  public static void handleException(String msg, Throwable exc, boolean saveToFile)
  {
    try
    {
      TAPrintStream out = getStream();
 
      out.print(msg);
      out.println(" - " + exc.getClass().getSimpleName());
      StackTraceElement[] elements = exc.getStackTrace();
 
      for(StackTraceElement t : elements)
      {
        out.println(t);
      }
    }catch(Exception exce)
    {
      // Not cool.
      exce.printStackTrace();
    }
  }
  /**
   * For testing purposes, shows an example usage of this program
   */
  public static void main(String[] args)
  {
    ConsoleGUI.toGUI();
    //ConsoleGUI.setSaveText(true);
    TAScanner scanner = ConsoleGUI.getScanner();
    TAPrintStream out = ConsoleGUI.getStream();
    out.println("Type a string");
    String str = scanner.nextLine();
    out.println("Type an int");
    int i = scanner.nextInt();
    out.println("You typed "+str+" and "+i);
    out.println("Say something starting with y");
    boolean b = scanner.nextBoolean();
    out.println(b);
    out.println("Say something starting with n");
    b = scanner.nextBoolean("n", true);
    out.println(b);
    out.println("Say banana");
    b = scanner.nextBoolean("banana", false);
    out.println(b);
 
    out.println();
    RuntimeException exc = new RuntimeException();
    handleException("Test", exc, true);
    //for(int i = 0; i < 50; i++) { out.println("Purposeful Spam"); }
  }
  @Override
  public String toString()
  {
    return "initialized";
  }
  /**
   * Short for TextAreaPrintStream, this stream sends all messages
   * to the GUI instead of the regular System.out
   * 
   * @author Timothy Moore
   */
  public class TAPrintStream
  {
    private JTextArea txtArea;
    private BufferedWriter fileWriter;
    private final File file = new File("lastRun.txt");
    /**
     * Create a print stream to the specified text area
     */
    private TAPrintStream(JTextArea txtArea)
    {
      this.txtArea = txtArea;
      DefaultCaret caret = (DefaultCaret)txtArea.getCaret();
      caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
    }
 
    public void print(Object msg)
    {
      txtArea.append(msg.toString());
      if(saveRun)
      {
        if(fileWriter == null)
        {
          //System.out.println("Creating file writer");
          try
          {
 
            file.createNewFile();
            fileWriter = new BufferedWriter(new FileWriter(file));
          }catch(Exception exc)
          {
            saveRun = false;
            handleException("Failed to create file", exc, false);
          }
          Runtime.getRuntime().addShutdownHook(new Thread()
                                                   {
            @Override
            public void run()
            {
              try
              {
                fileWriter.close();
              }catch(IOException e)
              {
                handleException("Failed to close writer", e, false);
              }
            }
          });
        }
        //System.out.println("Saving to filewriter");
        try
        {
          String[] msgs = msg.toString().split("/n");
          for(String s : msgs)
          {
            fileWriter.write(s);
            fileWriter.newLine();
          }
        }catch(Exception e)
        {
          handleException("Failed to write to file", e, false);
          saveRun = false;
        }
      }
 
    }
    public void print(boolean msg)
    {
      print(new StringBuilder().append(msg));
    }
    public void print(int msg)
    {
      print(new StringBuilder().append(msg));
    }
    public void print(long msg)
    {
      print(new StringBuilder().append(msg));
    }
    public void print(double msg)
    {
      print(new StringBuilder().append(msg));
    }
 
    public void println()
    {
      print("\n");
    }
 
    public void println(Object msg)
    {
      print(new StringBuilder().append(msg).append("\n"));
    }
    public void println(int msg)
    {
      println(new StringBuilder().append(msg));
    }
    public void println(long msg)
    {
      println(new StringBuilder().append(msg));
    }
    public void println(boolean msg)
    {
      println(new StringBuilder().append(msg));
    }
    public void println(double msg)
    {
      println(new StringBuilder().append(msg));
    }
  }
  /**
   * Short for TextAreaScanner, this Scanner retrieves messages
   * from the GUI instead of the regular new Scanner(System.in)
   * 
   * @author Timothy Moore
   */
  public class TAScanner implements ActionListener
  {
    private String str;
    private JTextField field;
    private JButton but;
    /**
     * Creates a scanner based on the specified text field
     * and button
     */
    private TAScanner(JTextField field, JButton but)
    {
      this.field = field;
      this.but = but;
      field.addActionListener(this);
      but.addActionListener(this);
    }
    /**
     * Reads one string
     */
    public String readLine()
    {
      field.setEditable(true);
      str = null;
      while(str == null)
      {
        delay(100);
      }
      ConsoleGUI.getStream().println(new StringBuilder("> ").append(str));
      return str;
    }
    /**
     * Same as readLine()
     */
    public String nextLine()
    {
      return readLine();
    }
    /**
     * Same as readInt()
     */
    public int nextInt()
    {
      return readInt();
    }
    /**
     * Same as readBoolean()
     */
    public boolean nextBoolean()
    {
      return readBoolean();
    }
    /**
     * Same as readLong()
     */
    public long nextLong()
    {
      return readLong();
    }
    /**
     * @return an integer from user
     */
    public int readInt()
    {
      try
      {
        return Integer.valueOf(readLine());
      }catch(NumberFormatException exc)
      {
        throw new InputMismatchException(exc.getMessage());
      }
    }
    /**
     * @return a long from user
     */
    public long readLong()
    {
      try
      {
        return Long.valueOf(readLine());
      }catch(NumberFormatException exc)
      {
        throw new InputMismatchException(exc.getMessage());
      }
    }
    /**
     * @return a boolean from user, assuming anything starting with a y is yes
     */
    public boolean readBoolean()
    {
      return readBoolean("Y", true);
    }
    /**
     * This is not case sensitive.
     * @return a boolean from user
     * @param str the string that the response needs to be true
     * @param start if the string has to start with the string or be completely that string
     */
    public boolean readBoolean(String str, boolean start)
    {
      if(start)
      {
        return readLine().toLowerCase().startsWith(str.toLowerCase());
      }else
      {
        return readLine().equalsIgnoreCase(str);
      }
    }
    /**
     * Same as <code>readBoolean(String str, boolean str)</code>
     */
    public boolean nextBoolean(String str, boolean start)
    {
      return readBoolean(str, start);
    }
    @Override
    public void actionPerformed(ActionEvent event)
    {
      str = field.getText();
      field.setText("");
    }
  }
  /**
   * Like thread.sleep but does not throw exceptions. Use with caution
   * @param ms the time in ms
   */
  public static void delay(long ms)
  {
    try
    {
      Thread.sleep(ms);
    }catch(InterruptedException exc)
    {
 
    }
  }
}
Note - If you find any bugs / inefficiencies do talk!

EDIT:
Fixed some inefficiencies and added saveLastRun

Updated June 20th, 2012 at 12:09 PM by Tjstretch (Looked over this code -- Added EDT, println(), handleException)

Categories
Uncategorized

Comments

  1. Tjstretch's Avatar
    permalink
    Alright I see what your saying.. I'll do that right now and update the blog. Thanks for noticing that! I also added many more methods to make it you can do things like
    int i = 0;
    out.println(i);
    and stuff, as well as everything throwing a InputMismatchException rather then NumberFormatException