如何在输入以编程方式更新时刷新zk中的文本框?

时间:2016-01-08 21:40:53

标签: java textbox refresh zk

在我的apache tomcat 7服务器上有一个我想在ZK中用作控制台形式的文本框。现在,它的内容以编程方式更改时不会更新,但我想这样做。每当我的java更改字符串时,它应该及时显示它,但是如何?

(修改了ZK的现有代码)

我的index.zul:

<zk>
  <window id="PDFmodifier" border="normal" height="98%"
     apply="org.zkoss.bind.BindComposer"
     viewModel="@id('vm') @init('toolbox.pdfconverter.FileUploadVM')"> 
    <label value="PDFmodifier"/>
      <separator></separator>
      <separator></separator>
     <hbox>

             <label value="Console log: " />
     <textbox width="500px" height="400px" id="txt" readonly="true" multiline ="true" value="Press the Upload Button to upload any PDF file. PDFmodifier will cover the unwanted area. After processing, the showPDF button will be active and you can save the modified PDF"/>
         <button label="Upload" upload="true"
             onUpload="@command('onUploadPDF',upEvent=event)"> </button>

         <button label="Show PDF" visible="@load(vm.fileuploaded)"
                onClick="@command('showPDF')">
           </button>
     </hbox>

       <iframe height="100%" width="100%" id="reportframe"
          content="@bind(vm.fileContent)">
     </iframe>
 </window>

视图模型:

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Calendar;

import org.zkoss.bind.BindContext;
import org.zkoss.bind.annotation.AfterCompose;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.io.Files;
import org.zkoss.util.media.AMedia;
import org.zkoss.util.media.Media;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.UploadEvent;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Window;

public class FileUploadVM {

    private String filePath;
    private boolean fileuploaded = false;
    AMedia fileContent;

    @Wire("#test")
    private Window win;
    @Wire("#txt")
    Textbox txt;


    public AMedia getFileContent() {
        return fileContent;
    }

    public void setFileContent(AMedia fileContent) {
        this.fileContent = fileContent;
    }

    public boolean isFileuploaded() {
        return fileuploaded;
    }

    public void setFileuploaded(boolean fileuploaded) {
        this.fileuploaded = fileuploaded;
    }

    @AfterCompose
    public void initSetup(@ContextParam(ContextType.VIEW) Component view) {
        Selectors.wireComponents(view, this, false);
        Executions.getCurrent().getDesktop().getWebApp().getConfiguration().setMaxUploadSize(10 * 1024);//for larger files

    }

    @Command
    @NotifyChange("fileuploaded")
    public void onUploadPDF(
            @ContextParam(ContextType.BIND_CONTEXT) BindContext ctx)
            throws IOException {

        UploadEvent upEvent = null;
        Object objUploadEvent = ctx.getTriggerEvent();
        if (objUploadEvent != null && (objUploadEvent instanceof UploadEvent)) {
            upEvent = (UploadEvent) objUploadEvent;
        }
        if (upEvent != null) {
            Media media = upEvent.getMedia();
            Calendar now = Calendar.getInstance();
            int year = now.get(Calendar.YEAR);
            int month = now.get(Calendar.MONTH);
            int day = now.get(Calendar.DAY_OF_MONTH);
            int min = now.get(Calendar.MINUTE);
            String fileName = year+"_"+month+"_"+day+"_"+min+".pdf";
            filePath = Executions.getCurrent().getDesktop().getWebApp().getRealPath("/");
            filePath = filePath + fileName;
            System.out.println("filePath='"+filePath+"'");
            Files.copy(new File(filePath), media.getStreamData());

            PDFmodifier mod = new PDFmodifier(txt);//txt
            filePath = mod.start(filePath);
            System.out.println("Ergbnis-pfad='"+filePath+"'");
            Messagebox.show("File Sucessfully altered. Press \"Show PDF\" to download file.");
            fileuploaded = true;

        }
    }

    @Command
    @NotifyChange("fileContent")
    public void showPDF() throws IOException {
        File f = new File(filePath);
        byte[] buffer = new byte[(int) f.length()];
        FileInputStream fs = new FileInputStream(f);
        fs.read(buffer);
        fs.close();
        ByteArrayInputStream is = new ByteArrayInputStream(buffer);
        fileContent = new AMedia("report", "pdf", "application/pdf", is);

    }
}

大大减少了java代码(这个问题需要更多但不需要):

import org.zkoss.zul.Textbox;
public class PDFmodifier {

     String logText ="";
     Textbox text;


    public PDFmodifier(Textbox t)
    {
        text = t;
    }

    protected void printToTextbox(String txt)
    {
        logText += "\n"+txt;
        text.setValue(logText);
    }
}

这一切都有效,但我想改进它。感谢提前阅读。

编辑:

Index.zul

<zk xmlns:n="native" xmlns:c="client">
<?page title="RemoveKlausNote" ?>
  <window id="RemoveKlausNote" 
     apply="org.zkoss.bind.BindComposer"
     viewModel="@id('vm') @init('toolbox.pdfconverter.FileUploadVM')"
     title="Bioinfo Teaching Toolbox" border="normal" width="1000px" position="center,top" mode="embedded"> 
<hbox>
    <label value="Console log: " />
     <textbox width="500px" height="200px" readonly="true" value="@bind(vm.getLogText())" multiline ="true"/>
         <button label="Upload" upload="true"
             onUpload="@command('onUploadPDF',upEvent=event)"> </button>

         <button label="Show PDF" visible="@load(vm.fileuploaded)"
                onClick="@command('showPDF')">
           </button>
     </hbox>

     <iframe height="100%" width="100%" id="reportframe"
          content="@bind(vm.fileContent)">
     </iframe>

 </window>

视图模型:

public class FileUploadVM {

    private String filePath;
    private boolean fileuploaded = false;
    AMedia fileContent;

    @Wire("#test")
    private Window win;

    LogText logText = new LogText();

    public AMedia getFileContent() {
        return fileContent;
    }

    public void setFileContent(AMedia fileContent) {
        this.fileContent = fileContent;
    }

    public boolean isFileuploaded() {
        return fileuploaded;
    }

    public void setFileuploaded(boolean fileuploaded) {
        this.fileuploaded = fileuploaded;
    }

    @AfterCompose
    public void initSetup(@ContextParam(ContextType.VIEW) Component view) {
        Selectors.wireComponents(view, this, false);
        Executions.getCurrent().getDesktop().getWebApp().getConfiguration().setMaxUploadSize(10 * 1024);//for larger files
    }


    @NotifyChange("logText.log")
    public void setLogText(String text) {
        logText.setLog(text);
    }

    @NotifyChange("logText.log")
    public String getLogText()
    {
        return logText.getLog();
    }

    @Command
    @NotifyChange("fileuploaded")
    public void onUploadPDF(
            @ContextParam(ContextType.BIND_CONTEXT) BindContext ctx)
            throws IOException {

        UploadEvent upEvent = null;
        Object objUploadEvent = ctx.getTriggerEvent();
        if (objUploadEvent != null && (objUploadEvent instanceof UploadEvent)) {
            upEvent = (UploadEvent) objUploadEvent;
        }
        if (upEvent != null) {
            Media media = upEvent.getMedia();


            String webAppPath = Executions.getCurrent().getDesktop().getWebApp().getRealPath("/");
            System.out.println("webAppPath='"+webAppPath+"'");


            Calendar now = Calendar.getInstance();
            int year = now.get(Calendar.YEAR);
            int month = now.get(Calendar.MONTH);
            int day = now.get(Calendar.DAY_OF_MONTH);
            int min = now.get(Calendar.MINUTE);
            String originalName = media.getName();

            String fileName = originalName +year+"_"+month+"_"+day+"_"+min+".pdf";
            String tmpPath = PDFmodifier.getTemp();
            if (!tmpPath.endsWith(File.separatorChar+"")) tmpPath = tmpPath + File.separator;
            filePath = tmpPath + fileName;
            System.out.println("filePath='"+filePath+"'");

            Files.copy(new File(filePath), media.getStreamData());

            filePath = new PDFmodifier(logText).start(filePath);
            System.out.println("Ergbnis-pfad='"+filePath+"'");
            Messagebox.show("File Sucessfully altered. Press \"Show PDF\" to download file.");
            fileuploaded = true;
    }
}

LogText对象:

public class LogText {

    public String log;

    public LogText()
    {
        log ="Press the Upload Button to upload any PDF file. PDFmodifier will cover the unwanted area. After processing, the showPDF button will be active and you can save the modified PDF";
    }

    public void setLog(String txt)
    {
        log += "\n"+txt;
    }

    public String getLog()
    {
        return log;
    }       
}

PDFmodifier(我不妨展示我的核心方法start()):

protected void printToTextbox(String txt)
    {
        log.setLog("\n"+txt);

    }

public String start(String uploadFile) throws IOException
       {
        setStringVariables(uploadFile);

        System.out.println("Processing inputFile='"+inputFile+"'");
        File f = new File(inputFile);
        if (!f.exists()) {
            System.err.println("inputFile not found)");
            return null;
        }
        long startTime = System.currentTimeMillis();
        //file can be opened and normally processed
        if(accessChecker(inputFile)){  
            coverWithRectangle(inputFile, outputFile) ;
            return outputFile;
        }
        //file needs further work
        else
        {
            printToTextbox("Accessing PDFsam for split...");
            if (createDirectory(outputDir)) {
                long startTimeSplit = System.currentTimeMillis();
                boolean splitOk = splitPDF(inputFile, outputDir);
                long endTimeSplit = System.currentTimeMillis();
                printToTextbox("Time for splitting [ms]: "+(endTimeSplit-startTimeSplit));

                if (!splitOk) {
                    printToTextbox("PDF couldn't be split. Exiting.");
                    return null;
                } 
                else 
                {
                    long startTimeMerge = System.currentTimeMillis();
                    boolean mergeOk = mergePDF(getAllFiles(),tempPDF,tempCSV);
                    long endTimeMerge = System.currentTimeMillis();
                    printToTextbox("Time for merging [ms]: "+(endTimeMerge-startTimeMerge));

                    if (mergeOk) {  
                        coverWithRectangle(tempPDF, outputFile);
                        deleteTrash();
                    } else {
                        printToTextbox("ERROR: merge failed!");
                    }


                }
            }
            writeLog(outputFile);
            long endTime = System.currentTimeMillis();
            printToTextbox("Total time needed [ms]: "+(endTime-startTime));
            printToTextbox("outputFile='"+outputFile+"'");
            return outputFile;
        }

编辑2:

祖尔:

<textbox width="500px" height="200px"  readonly="true" value="@bind(vm.logText)" multiline ="true"/>
        <timer id="timer" delay="50" repeats="true" onTimer="@command('refreshTextbox')" />

视图模型:

String logText;
    LogText log = new LogText();

    @NotifyChange("logText")
    public void setLogText(String txt)
    {
        log.log ="\n"+txt;
        logText = log.log;

    }

    @NotifyChange("logText")
    public String getLogText()
    {
        logText = log.log;
        return logText;
    }

    @Command
    public void refreshTextbox()
    {
        logText = log.log;
        BindUtils.postNotifyChange(null,null,this,"logText");

    }

viewmodel将Textlog对象传递给Pdfmodifier的新实例。一个解决这个问题的尝试。

1 个答案:

答案 0 :(得分:2)

您正在混合两种类型,MVVM和MVC。 窗口和文本框以MVC方式使用。

您可以更轻松地完成此任务:

在您的VM中创建:

 public class MainActivity extends Activity {
  ProgressDialog mDialog;
  ....
   protected void onCreate(){
     //Add remaining code
     if(mDialog==null){
        showLoadingDialog(//send in params);
     }
     asyncTask.execute(apiRequestModel);

   }
    public void showLoadingDialog(String title, String message){
        mDialog= new ProgressDialog(this);
        mDialog.setTitle(title);
        mDialog.setMessage(message);
        mDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        mDialog.setIndeterminate(true);
        mDialog.setProgress(0);
        mDialog.setCancelable(false);
        mDialog.show();
    } //Close dialog box code

    public class GetAPIResponse extends AsyncTask<APIRequestModel, Void, String> {
      //Custom functions that you already have. Leave doInBackground as it is

      @Override
        protected void onPostExecute(String result) {
        super.onPostExecute(result);
        if(mDialog!=null){
          mDialog.dismiss();
        }

       }

    }//Close async task
   }//Close Activity

并提供getter和setter。

在viewmodel中更改为:

private String textField = "Press the Upload Button to upload any PDF file. PDFmodifier will cover the unwanted area. After processing, the showPDF button will be active and you can save the modified PDF";

现在,当想要将更改保留到GUI时,您可以使用

<textbox width="500px" height="400px" id="txt" readonly="true" multiline ="true" value=@bind(vm.textField)"/>

但这只适用于制定者和命令。

您可以在viewmodel中的其他方法中执行此操作,如:

@NotifyChange("textField")

编辑:

如果您的文本框需要在文件上载繁忙时更新一次,则需要单独的线程。

如果没有,你几乎就在那里:

BindUtils.postNotifyChange(null,null,this,"textField");

在这里删除了notifychanged,不需要和完美的解决方案来显示文本。

public void setLogText(String text) {
    logText.setLog(text);
}

public String getLogText() {
    return logText.getLog();
}

将logText的notifychange添加到此命令。

现在还有其他一些改进:

@Command
@NotifyChange({"fileuploaded","logText"})
public void onUploadPDF(
        @ContextParam(ContextType.BIND_CONTEXT) BindContext ctx)
        throws IOException {

    UploadEvent upEvent = null;
    Object objUploadEvent = ctx.getTriggerEvent();
    if (objUploadEvent != null && (objUploadEvent instanceof UploadEvent)) {
        upEvent = (UploadEvent) objUploadEvent;
    }
    if (upEvent != null) {
        Media media = upEvent.getMedia();


        String webAppPath = Executions.getCurrent().getDesktop().getWebApp().getRealPath("/");
        System.out.println("webAppPath='"+webAppPath+"'");


        Calendar now = Calendar.getInstance();
        int year = now.get(Calendar.YEAR);
        int month = now.get(Calendar.MONTH);
        int day = now.get(Calendar.DAY_OF_MONTH);
        int min = now.get(Calendar.MINUTE);
        String originalName = media.getName();

        String fileName = originalName +year+"_"+month+"_"+day+"_"+min+".pdf";
        String tmpPath = PDFmodifier.getTemp();
        if (!tmpPath.endsWith(File.separatorChar+"")) tmpPath = tmpPath + File.separator;
        filePath = tmpPath + fileName;
        System.out.println("filePath='"+filePath+"'");

        Files.copy(new File(filePath), media.getStreamData());

        filePath = new PDFmodifier(logText).start(filePath);
        System.out.println("Ergbnis-pfad='"+filePath+"'");
        Messagebox.show("File Sucessfully altered. Press \"Show PDF\" to download file.");
        fileuploaded = true;
}

你不要在虚拟机中询问upEvent,只需将其删除即可。

<button label="Upload" upload="true"
         onUpload="@command('onUploadPDF',upEvent=event)"> </button>

可能是这样的:

public void onUploadPDF(
        @ContextParam(ContextType.BIND_CONTEXT) BindContext ctx)
        throws IOException {

因为您唯一要做的就是从bindContext获取触发器事件,因此无需获取该对象,并且它会删除方法中的大量样板代码。

编辑2:

看起来你需要一个单独的线程来处理。 I created a fiddle所以你可以看到我是怎么做到的。

但如果链接死了:

 public void onUploadPDF(
        @ContextParam(ContextType.TRIGGER_EVENT) UploadEvent evt)
        throws IOException {

和zul: