简体   繁体   English

在Java中创建独立的GUI控制台,以扩展基于提示的应用程序

[英]Creating a standalone gui console in java that extends prompt based application

I have several little applications which uses the standard console for retrieving user input and for showing messages troughtout System.in and System.out. 我有几个小应用程序,它们使用标准控制台检索用户输入并显示出System.in和System.out中出现的消息。

Now i would like to realize some Swing based class which called from these applications, it shows a frame with 2 text area, one for input (so associated to System.in) and another one (not editable) that shows the messages (hence associated to System.out). 现在,我想实现一些基于Swing的类,这些类从这些应用程序中调用,它显示了一个带有2个文本区域的框架,一个用于输入(因此与System.in关联),另一个用于显示消息(因此与之关联)。到System.out)。 Actually i have implemented all, (actually creating a simple swing based gui and launching it from the event dispatcher thread is not so complex, the same for exporting all as a jar and including it as a library in the original project). 实际上,我已经实现了所有功能(实际上创建一个简单的基于swing的gui并从事件分派器线程中启动它并没有那么复杂,将所有内容导出为jar并将其包含在原始项目中的库中也是如此)。 The only problem I have so far, which took me here is about the swapping of the standard System.in and System.out to some custom ones which are associated with the 2 JTextArea . 到目前为止,我遇到的唯一问题是将标准System.in和System.out交换为与2 JTextArea关联的一些自定义JTextArea Actually checking some solutions online, I ended up with this few lines of code: 实际上在线检查了一些解决方案,最后得到了以下几行代码:

I use 2 PipedInputStream and a PrintWriter: 我使用2 PipedInputStream和一个PrintWriter:

    private final PipedInputStream inPipe = new PipedInputStream(); 
    private final PipedInputStream outPipe = new PipedInputStream(); 
    private PrintWriter inWriter;

then i swap the streams 然后我交换流

    System.setIn(inPipe); 
    System.setOut(new PrintStream(new PipedOutputStream(outPipe), true)); 
    inWriter = new PrintWriter(new PipedOutputStream(inPipe), true); 

for retrieving the data from the outPipe, I use a SwingWorker whose doInBackgroud method troughtout a Scanner reads the lines from the outPipe and publish them in order to append these string of lines in a not editable JTextArea. 为了从outPipe检索数据,我使用了一个SwingWorkerdoInBackgroud方法被删除了, Scanner从outPipe读取行并发布,以便将这些字符串行附加到不可编辑的JTextArea中。 Meanwhile a keyListener checks for VK_ENTER click in order to get the text from the JTextField used as prompt, once this happens, the text is displayed using the System.out itself, and it effectively appears in the previous JTextArea, hence the SwingWorker described above works, and then I wrote the same line of text in the inWriter (the PrintStream object associated to the pipe related to the System.in) so the line should be available to be read from Reader objects which are present in the original application. 同时, keyListener检查VK_ENTER单击以从用作提示的JTextField中获取文本,一旦发生这种情况,将使用System.out本身显示该文本,并有效地显示在先前的JTextArea中,因此上述SwingWorker可以正常工作,然后在inWriter(与System.in相关的管道相关联的PrintStream对象)中写了相同的文本行,因此应该可以从原始应用程序中存在的Reader对象中读取该行。

Unfortunately this is the only part of the code which does not work. 不幸的是,这是代码中唯一不起作用的部分。 Indeed, once i launch the new gui console, then change the streams, the original application will show only the text it prints on System.out, but when it wants to read the text the user writes, for instance troughtout either a BufferedReader or a Scanner object, nothing happens, as if the the in stream was empty. 确实,一旦启动新的gui控制台,然后更改流,原始应用程序将仅显示它在System.out上打印的文本,但是当它想要读取用户编写的文本时,例如,将BufferedReader或扫描程序对象,什么也没有发生,好像in流为空。

I think this is due to the Scanner in the SwingWorker doInBackground method since when it reads the next line on the outPipe, it cleans the stream itself too. 我认为这是由于SwingWorker doInBackground方法中的Scanner所致,因为当它读取outPipe的下一行时,它也会清除流本身。 Any idea to get rid of this problem? 有什么办法摆脱这个问题吗? I know i could write new methods for handling input and output but i would like to keep this not-intrusive approach, so without editing the original code, a part the creation of the gui Console object in the original application main method. 我知道我可以编写用于处理输入和输出的新方法,但是我想保留这种非侵入性的方法,因此无需编辑原始代码,这是在原始应用程序main方法中创建gui Console对象的一部分。 Thanks in advance. 提前致谢。

Update 1 更新1

This is the Console class, all is done here 这是Console类,所有操作都在这里完成

public class Console extends JFrame implements KeyListener 
{

private JTextField prompt;
private JTextArea log;


private final PipedInputStream inPipe = new PipedInputStream(); 
private final PipedInputStream outPipe = new PipedInputStream(); 

private PrintWriter inWriter;


public Console(String title)
{
    super(title);

    System.setIn(inPipe); 

    try 
    {
        System.setOut(new PrintStream(new PipedOutputStream(outPipe), true)); 
        inWriter = new PrintWriter(new PipedOutputStream(inPipe), true); 
    }
    catch(IOException e) 
    {
        System.out.println("Error: " + e);
        return;
    }

    JPanel p = new JPanel();
    p.setLayout(null);
    log = new JTextArea();
    log.setEditable(false);
    log.setBounds(10, 10, 345, 250);
    p.add(log);
    prompt = new JTextField();
    prompt.setBounds(10, 270, 356, 80);
    prompt.addKeyListener(this);
    p.add(prompt);

    getContentPane().add(p);

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
    setSize(392, 400);
    setLocationRelativeTo(null);

    (new SwingWorker<Void, String>() 
    { 
        protected Void doInBackground() throws Exception 
        { 
            Scanner s = new Scanner(outPipe);
            while (s.hasNextLine()) 
            {
                String line = s.nextLine();
                publish(line);
            }
            return null; 
        } 
        @Override 
        protected void process(java.util.List<String> chunks)
        { 
            for (String line : chunks) 
            {
                if (line.length() < 1)
                    continue;
                log.append(line.trim() + "\n"); 
            }
        } 
    }).execute(); 


}
    public void execute() 
{
    String text = prompt.getText();
    prompt.setText("");
    System.out.println(text); 
    inWriter.print(text.trim().replaceAll("\r\n", ""));
}


@Override
public void keyPressed(KeyEvent e)
{
    if (e.getKeyCode() == KeyEvent.VK_ENTER)
        execute();
}

@Override
public void keyReleased(KeyEvent e)
{
    if (e.getKeyCode() == KeyEvent.VK_ENTER)
        execute();

}

@Override
public void keyTyped(KeyEvent e)
{
    if (e.getKeyCode() == KeyEvent.VK_ENTER)
        execute();

}

// this is the method called from the original application
public static void setConsole(final String title) 
{
    EventQueue.invokeLater(new Runnable()
    {
        public void run()
        {
            new Console(title);
            //System.out.println("somewhat");
        }
    });

}

}

I found out the solution by myself, actually all the code posted in the 1st post is almost correct, the problem is with the reading from the System.in the original program, since it was done with a Scanner object (but i tested it with a BufferedReader too) and it seems it's something related to the string termination because if i read by using a simple System.in.read() call, i got the right data, of course char by char. 我自己找到了解决方案,实际上第一篇文章中发布的所有代码几乎都是正确的,问题出在原始程序中,是从System。读取的,因为它是用Scanner对象完成的(但是我用一个BufferedReader也是如此),这似乎与字符串终止有关,因为如果我通过使用简单的System.in.read()调用进行读取,则可以得到正确的数据,当然是逐个字符。 Since both Scanner methods and read one are I/O blocking, I think it's something related to the termination of the string. 由于Scanner方法和read方法都是I / O阻塞,因此我认为这与字符串的终止有关。 Because when i wrote it on the InputStream, i cleared the string from any LF and CF char, as you can see in the above code, so when println is invoked only a \\r\\n should be appended. 因为当我在InputStream上编写它时,我从任何LF和CF字符中清除了该字符串,如您在上面的代码中所见,所以当调用println时,仅应附加一个\\ r \\ n But reading the result char by char I see \\r\\n\\r\\n at the end, so i guess it should be something related to the ending of the string, even if i couldnt figured out the right way to handle it. 但是按字符读取结果char时,我在末尾看到\\ r \\ n \\ r \\ n ,所以我想它应该与字符串的结尾有关,即使我找不到正确的处理方式。 I will keep you informated by updates tought, but however if you have suggestions and/or feedbacks, they will be obviously welcome. 我会及时通知您韧体更新,但是,如果您有建议和/或反馈,则显然会受到欢迎。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM