Question

I have been modifying a simple Java Swing console, and I decided to add a form of highlighting for keywords (by coloring the area next to flagged lines). I got it to work fine when I throw errors by searching for the keyword "Exception", but when I do a System.out.println with the keyword in it, it highlights everything. I think the string is somehow being combined with all of the strings already entered, which is the cause for this error, but I am having trouble fixing it.

Here's a screenshot:

enter image description here

The text "Hello World 2" and "Lets throw an error on this console" should not be highlighted.

// Edited by Jeff B
// A simple Java Console for your application (Swing version)
// Requires Java 1.1.5 or higher
//
// Disclaimer the use of this source is at your own risk. 
//
// Permision to use and distribute into your own applications
//
// RJHM van den Bergh , rvdb@comweb.nl

import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class textAreaC extends JTextArea {
    int rowCount;
    int rowHeight;
    ArrayList<Point> exPoint = new ArrayList<Point>();

    public textAreaC() {
        rowHeight = this.getRowHeight();
    }

    public void paint(Graphics g) {
        super.paint(g);
        g.setColor(Color.red);
        for (int i = 0; i < exPoint.size(); i++) {
            g.fillRect(3, exPoint.get(i).x * rowHeight, 10, exPoint.get(i).y
                    * rowHeight);
        }
    }

    public void append(String str) {
        int rows = str.split("\r\n|\r|\n").length;
        if (str.contains("Exception")) {
            //System.out.println("This was the string: " + str + "It has " + rows + "rows" + " End String");
            exPoint.add(new Point(rowCount, rows));
        }
        rowCount += rows;
        super.append(str);

    }
}

public class Console extends WindowAdapter implements WindowListener,
        ActionListener, Runnable {
    private JFrame frame;
    private textAreaC textArea;
    private Thread reader;
    private Thread reader2;
    private boolean quit;

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

    Thread errorThrower; // just for testing (Throws an Exception at this Console

    public Console() {
        // create all components and add them
        frame = new JFrame("Java Console");
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frameSize = new Dimension((int) (screenSize.width / 2),
                (int) (screenSize.height / 2));
        int x = (int) (frameSize.width / 2);
        int y = (int) (frameSize.height / 2);
        frame.setBounds(x, y, frameSize.width, frameSize.height);

        textArea = new textAreaC();
        textArea.setEditable(false);
        textArea.setMargin(new Insets(3, 20, 3, 3));
        JButton button = new JButton("clear");
        frame.getContentPane().setLayout(new BorderLayout());
        frame.getContentPane().add(new JScrollPane(textArea),
                BorderLayout.CENTER);
        frame.getContentPane().add(button, BorderLayout.SOUTH);
        frame.setVisible(true);
        frame.addWindowListener(this);
        button.addActionListener(this);

        try {
            PipedOutputStream pout = new PipedOutputStream(this.pin);
            System.setOut(new PrintStream(pout, true));
        } catch (java.io.IOException io) {
            textArea.append("Couldn't redirect STDOUT to this console\n"
                    + io.getMessage());
        } catch (SecurityException se) {
            textArea.append("Couldn't redirect STDOUT to this console\n"
                    + se.getMessage());
        }

        try {
            PipedOutputStream pout2 = new PipedOutputStream(this.pin2);
            System.setErr(new PrintStream(pout2, true));
        } catch (java.io.IOException io) {
            textArea.append("Couldn't redirect STDERR to this console\n"
                    + io.getMessage());
        } catch (SecurityException se) {
            textArea.append("Couldn't redirect STDERR to this console\n"
                    + se.getMessage());
        }

        quit = false; // signals the Threads that they should exit

        // Starting two seperate threads to read from the PipedInputStreams             
        //
        reader = new Thread(this);
        reader.setDaemon(true);
        reader.start();
        //
        reader2 = new Thread(this);
        reader2.setDaemon(true);
        reader2.start();

        // testing part
        // you may omit this part for your application
        // 
        //System.out.println("Test me please Exception\n testing 123");
        System.out.flush();
        System.out.println("Hello World 2");

        System.out.println("\nLets throw an error on this console");
        errorThrower = new Thread(this);
        errorThrower.setDaemon(true);
        errorThrower.start();
    }

    public synchronized void windowClosed(WindowEvent evt) {
        quit = true;
        this.notifyAll(); // stop all threads
        try {
            reader.join(1000);
            pin.close();
        } catch (Exception e) {
        }
        try {
            reader2.join(1000);
            pin2.close();
        } catch (Exception e) {
        }
        System.exit(0);
    }

    public synchronized void windowClosing(WindowEvent evt) {
        frame.setVisible(false); // default behaviour of JFrame 
        frame.dispose();
    }

    public synchronized void actionPerformed(ActionEvent evt) {
        textArea.setText("");
    }

    public synchronized void run() {
        try {
            while (Thread.currentThread() == reader) {
                try {
                    this.wait(100);
                } catch (InterruptedException ie) {
                }
                if (pin.available() != 0) {
                    String input = this.readLine(pin);
                    textArea.append(input);
                    //System.out.println(input.split("\r\n|\r|\n").length);
                }
                if (quit)
                    return;
            }

            while (Thread.currentThread() == reader2) {
                try {
                    this.wait(100);
                } catch (InterruptedException ie) {
                }
                if (pin2.available() != 0) {
                    String input = this.readLine(pin2);
                    textArea.append(input);
                }
                if (quit)
                    return;
            }
        } catch (Exception e) {
            textArea.append("\nConsole reports an Internal error.");
            textArea.append("The error is: " + e);
        }

        // just for testing (Throw a Nullpointer after 1 second)
        if (Thread.currentThread() == errorThrower) {
            try {
                this.wait(1000);
            } catch (InterruptedException ie) {
            }
            throw new NullPointerException(
                    "Application test: throwing an NullPointerException It should arrive at the console");
        }
    }

    public synchronized String readLine(PipedInputStream in) throws IOException {
        String input = "";
        do {
            int available = in.available();
            if (available == 0)
                break;
            byte b[] = new byte[available];
            in.read(b);
            input = input + new String(b, 0, b.length);
        } while (!input.endsWith("\n") && !input.endsWith("\r\n") && !quit);
        return input;
    }

    public static void main(String[] arg) {
        new Console(); // create console with not reference 
    }
}

I have been doing a little testing, take a look at this printout: enter image description here

To replicate this, add a System.out.prinln statement in reader(1) and append the input to the end of the string. This is what my prinlns look like:

System.out.println("There should be a string before me.");
System.out.flush();
System.out.println("Test me please Exception");
System.out.flush();
System.out.println("Test print 2");
System.out.flush();
System.out.println("Test print 3");
System.out.flush();
System.out.println("Test me please Exception 2");
System.out.flush();
System.out.println("Exception here lololol");
System.out.flush();
System.out.println("Hello World 2");
System.out.flush();

And my reader one looks like this:

if (pin.available()!=0)
    {

        String input=this.readLine(pin);
        System.out.println("this was printed by the thread second " + input);
        textArea.append(input);
        //System.out.println(input.split("\r\n|\r|\n").length);
    }
if (quit) return;

It is treating all of those prinlns as a single input, is this something java is doing, or am I missing something?

Was it helpful?

Solution

Use HTML for output, that is easier. Just as first text <html> would do (very loose HTML). Or set the content type. Append lines with <br> and so on.

It is more flexible.


You did two appends of multiline strings. Taking the number of rows would make all lines in the string red. Maybe this suboptimal version is more like what you intended.

@Override
public void append(String str) {
    String[] lines = str.split("\r\n|\r|\n");
    int rows = lines.length;
    for (String line : lines) {
        super.append(line + "\n");
        if (line.contains("Exception")) {
            exPoint.add(new Point(rowCount, 1)); // 1 line
        }
        ++rowCount;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top