Reputation: 1
I recently finished up a GUI where a user can input criteria, and get results adhering to said conditions. The program works result wise, but I'm having trouble getting my textField in my GUI to read my terminal window result. My code for the GUI is as followed:
package project205;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class HouseListGUI extends JFrame
{
//GUI Components
HouseList availableHouses = new HouseList("src/houses.txt");
JLabel cLab = new JLabel("Criteria");
JLabel minLab = new JLabel("Min");
JLabel maxLab = new JLabel("Max");
JLabel pLab = new JLabel("Price");
JLabel aLab = new JLabel("Area");
JLabel bLab = new JLabel("Bedrooms");
JTextField pMin = new JTextField(10);
JTextField pMax = new JTextField(10);
JTextField aMin = new JTextField(10);
JTextField aMax = new JTextField(10);
JTextField bMin = new JTextField(10);
JTextField bMax = new JTextField(10);
JTextArea results = new JTextArea(20, 40);
JButton sButton = new JButton("Search");
JButton qButton = new JButton("Quit");
public HouseListGUI()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400,300);
setVisible(true);
Container c = getContentPane();
c.setLayout(new GridLayout(5,3,10,10));
c.add(cLab);
c.add(minLab);
c.add(maxLab);
c.add(pLab);
c.add(pMin);
c.add(pMax);
c.add(aLab);
c.add(aMin);
c.add(aMax);
c.add(bLab);
c.add(bMin);
c.add(bMax);
c.add(sButton);
c.add(results);
c.add(qButton);
sButton.addActionListener(
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String pmn = pMin.getText();
String pmx = pMax.getText();
String amn = aMin.getText();
String amx = aMax.getText();
String bmn = bMin.getText();
String bmx = bMax.getText();
int pmn1 = Integer.parseInt(pmn);
int pmx1 = Integer.parseInt(pmx);
int amn1 = Integer.parseInt(amn);
int amx1 = Integer.parseInt(amx);
int bmn1 = Integer.parseInt(bmn);
int bmx1 = Integer.parseInt(bmx);
Criteria theCriteria = new Criteria(pmn1, pmx1, amn1, amx1, bmn1, bmx1);
availableHouses.printHouses(theCriteria);
results.setText("");
}
});
qButton.addActionListener(
new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
);
}
public static void main(String[] args)
{
//HouseList availableHouses = new HouseList("src/houses.txt");
HouseListGUI g1 = new HouseListGUI();
g1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
g1.setSize(1000,500);
g1.show();
}
}
I would like the results of the code line availableHouses.printHouses(theCriteria); which returns a type void to be printed in the textArea results
I've tried using type cast to cast the void as a string and putting that into results, ie:
results.setText((String)availableHouses.printHouses(theCriteria);
But Java's not having that.
TL;DR:
How might one take a terminal resulting from a method call of type void, and printing that as a type String into a textArea in the context of a GUI?
for further clarification:
my terminal window looks like this:
https://i.sstatic.net/ZTZFC.jpg
and my GUI looks like this:
https://i.sstatic.net/dCxbZ.jpg
and I want my terminal to be in the middle box in the last row.
Thanks for any advice/tips!
Upvotes: 0
Views: 1061
Reputation: 347314
You can capture and redirect the content sent to System.out
by supplying your own OutputStream
. This is, by no stretch of the imagination, a foolproof solution, as anything printed to the standard out will be captured, but you could turn in on and off as you needed...
I've used this as a debug window in applications that did not have debug statements to a log file as well as filtering and stopping System.out
from generating any output...
In this example I use ...
PrintStream ps = System.out;
System.setOut(new PrintStream(new StreamCapturer(capturePane, ps)));
doSomeProcessing();
System.setOut(ps);
To start and stop capturing the System.out
, you could place a flag in StreamCapturer
that turned the echoing feature on and off, which might be better way to approach the problem...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class RediretStdOutTest {
public static void main(String[] args) {
new RediretStdOutTest();
}
public RediretStdOutTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
final CapturePane capturePane = new CapturePane();
JButton processButton = new JButton("Process");
processButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Look at me, I'm not in your UI");
PrintStream ps = System.out;
System.setOut(new PrintStream(new StreamCapturer(capturePane, ps)));
doSomeProcessing();
System.setOut(ps);
System.out.println("Neither am I");
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(capturePane);
frame.add(processButton, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected void doSomeProcessing() {
for (int index = 0; index < 10; index++) {
System.out.println("--> " + index);
}
}
public class CapturePane extends JPanel implements Consumer {
private JTextArea output;
public CapturePane() {
setLayout(new BorderLayout());
output = new JTextArea(10, 20);
add(new JScrollPane(output));
}
@Override
public void appendText(final String text) {
if (EventQueue.isDispatchThread()) {
output.append(text);
output.setCaretPosition(output.getText().length());
} else {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
appendText(text);
}
});
}
}
}
public interface Consumer {
public void appendText(String text);
}
public class StreamCapturer extends OutputStream {
private StringBuilder buffer;
private Consumer consumer;
private PrintStream old;
public StreamCapturer(Consumer consumer, PrintStream old) {
buffer = new StringBuilder(128);
this.old = old;
this.consumer = consumer;
}
@Override
public void write(int b) throws IOException {
char c = (char) b;
consumer.appendText(Character.toString(c));
old.print(c);
}
}
}
Now, having said all that, I would fix you method so that it returned a result, as it would be cleaner...
Upvotes: 3
Reputation: 285405
I've tried using type cast to cast the void as a string and putting that into results, ie:
results.setText((String)availableHouses.printHouses(theCriteria);
No that will never work, and you're going about it backwards. Much better to have the HouseList's printHouses(...)
method return a String, and then this can easily be displayed in your JTextArea with little or no modification and certainly without an erroneous cast.
Otherwise, if you absolutely must get the standard output from another console program that you cannot change in any way, you'll have to call it in a separate process (and if a Java program, then in a separate JVM that is run as a process) using a ProcessBuilder, and then trap the InputStream from the process, and output that in your JTextArea. It's do-able, but requires use of background threading, of exception trapping, and is not something I'd recommend that a beginner delve into just yet.
Upvotes: 3