2

我正在尝试使用 apache wicket 创建类似于只读控制台窗口的东西。本质上,用户提交表单以启动服务器端操作。然后可以在页面上跟踪作业输出。

我目前正在显示输出,如下所示:

public class ConsoleExample extends WebPage {

protected boolean refreshing;
private String output = "";

public void setOutput(String newOutput) {
    synchronized (this) {
        output = newOutput;
    }
}

public void appendOutput(String added) {
    synchronized (this) {
        this.output = output+added;
    }
}

public ConsoleExample() {

    Form<ConsoleExample> form = new Form<ConsoleExample>("mainform");
    add(form);
        final TextArea<String> outputArea = new TextArea<String>("output",
            new PropertyModel<String>(this, "output"));
    outputArea.setOutputMarkupId(true);
    // A timer event to add the outputArea to the target, triggering the refresh
    outputArea.add(new AbstractAjaxTimerBehavior(Duration.ONE_SECOND){
        private static final long serialVersionUID = 1L;
        @Override
        protected void onTimer(AjaxRequestTarget target) {
            synchronized (this) {
                if(refreshing ){
                    target.focusComponent(null);
                    target.addComponent(getComponent());
                }
            }
        }

    });

    add(outputArea);

    form.add(new AjaxSubmitLink("run") {
        private static final long serialVersionUID = 1L;

        @Override
        public void onSubmit(final AjaxRequestTarget target, Form<?> form) {
            setOutput("");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        refreshing = true;
                        ProcessBuilder pb = new ProcessBuilder(Collections.singletonList("execute"));
                        pb.redirectErrorStream(true);
                        String line;
                        BufferedReader br = new BufferedReader(new InputStreamReader(pb.start().getInputStream()));
                        while ((line = br.readLine()) != null) {
                            appendOutput("\n" + line);
                        }
                    } catch (IOException e) {
                        //...
                    } finally {
                        //...
                        refreshing = false;
                    }
                }
            }).start();
        }
    });
}

该解决方案的问题在于,每次 AjaxTimerBehaviorRuns 刷新都会重置文本区域属性,即光标位置和滚动位置。因此,随着输出的增加,用户无法跟踪输出,因为 textarea 每秒都会跳回开始。

有没有更好的方法来实现这一目标?

4

2 回答 2

0

A posible easy to implement approach is to add a hidden TextField that you update throw AJAX with a AjaxTimerBehavior and then calls a JavaScript function (using AjaxRequestTarget.appendJavaScript()) that synchronizes the value of the hidden TextField with your <textarea>.

于 2012-05-08T19:25:24.103 回答
0

Partial Solution Following on from jordeu's suggestion of using the appendJavaScript() function I am just adding a bit of javascript to append the new text:

protected void onTimer(AjaxRequestTarget target) {
    synchronized (this) {
        if(refreshing ){
            if(update != null){
                target.appendJavascript("var obj=document.getElementById(\"output\");var txt=document.createTextNode(\""+update+"\");obj.appendChild(txt)");
                update = null;
            }
        }
    }
}

Where the update field is any new text since the last update.

This solves the scroll issue but any user selection is still reset. Also it doesn't seem like a "nice" solution to me.

Any further suggestions of how to improve are welcome.

于 2012-05-09T10:35:49.620 回答