【问题标题】:How to refresh a textbox in zk when input gets updated programmatically?以编程方式更新输入时如何刷新zk中的文本框?
【发布时间】:2016-01-08 21:40:52
【问题描述】:

有一个文本框,我想在我的 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);
    }
}

一切正常,但我想改进它。感谢您提前阅读。

编辑:

索引.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");

    }

视图模型将 Textlog 对象传递给 Pdfmodifier 的新实例。解决这个问题的一个荒谬的尝试。

【问题讨论】:

    标签: java textbox refresh zk


    【解决方案1】:

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

    您可以更轻松地做到这一点:

    在你的虚拟机中创建:

    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";
    

    并提供 getter 和 setter。

    在视图模型中更改为:

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

    现在,当您想要将更改持久化到 GUI 时,您可以使用

    @NotifyChange("textField")
    

    但这仅适用于设置器和命令。

    您可以在视图模型中的其他方法中执行此操作,例如:

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

    编辑:

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

    如果没有,你就快到了:

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

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

    @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;
    }
    

    在该命令中添加了 logText 的 notifychange。

    现在还有一些其他改进:

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

    您不会在 VM 中询问 upEvent,因此只需将其删除即可。

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

    可能是这样的:

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

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

    编辑 2:

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

    但如果链接失效:

    @Command
    @NotifyChange("timer")
    public void longOperation() {
        timer = true;
        Thread r = new Thread(new Runnable() {
    
            @Override
            public void run() {
    
                log = "button pressed, initializing now";
                sleep(5000); // this is a private method for calling Thread.sleep
                log = "initialized done, processing now";
                sleep(5000);
                log = "finished";
                timer = false;
            }
        });
        r.start();
    }
    
    @Command
    @NotifyChange({"log","timer"})
    public void refreshTextbox(){
      if (!timer) {
          Clients.showNotification("timer stopped"); 
      }
    }
    

    还有祖尔:

    【讨论】:

    • 感谢您的帮助,但是您如何从 java 代码中访问 viewmodel 变量?它既不是静态的,我也不能从 PDFmodifier 创建一个 vm 对象(这就是我想出文本框的原因)。主要工作从那里完成,所有的日志记录也在那里完成。
    • 你现在有一个字符串而不是一个文本框。您可以提供给 pdfmodifier 的字符串和您的 Pdfmodifier 应该将字符串返回给视图模型。如果这不可能,您可以抛出一个全局命令并将字符串放入该 args 映射中。
    • 不能那样做。传递的字符串不会在视图模型内部更改,因为它只是按值调用,并且更改发生在 pdfmodifier 内部。现在,除了起始文本之外没有任何变化。我将编辑起始帖子以显示我所做的(以及潜在的错误)。
    • 我确实需要多次更改。现在,通过这些更改,PDFmodifier 根本没有对文本框进行更新,尽管它创建了向对象传递了很多东西,但由于按值调用,它与在通知中从 VM 观察到的对象不同地区。
    • 不,那是另一种技术,在我编辑的第一句话中说明了。您的代码在服务器 siee 上运行。一旦你的方法完成了,那么你'返回'到客户端
    猜你喜欢
    • 1970-01-01
    • 2014-06-02
    • 1970-01-01
    • 2012-12-26
    • 2013-04-19
    • 1970-01-01
    • 2018-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多