Java 相关文件更改时动态刷新JTextPane

Java 相关文件更改时动态刷新JTextPane,java,swing,refresh,dynamic,jtextpane,Java,Swing,Refresh,Dynamic,Jtextpane,我正在工作的当前项目使用log4j库创建了一个日志文件,并且必须具有“showLog”功能,该功能创建了一个可以查看日志的框架。此外,当日志文件被修改(附加新的日志消息)时,该帧必须刷新 嗯,除了刷新操作之外,我已经完成了所有操作,这是一个问题,如何进行动态刷新? 这里是我的代码片段,我只放了相关的行: 接口操作:运行事件操作 公共接口操作{ 公共无效执行者(); } 类CadreTexte:创建并管理显示日志文件的框架 公共类CadreTexte扩展了JFrame{ 私有JTextPa

我正在工作的当前项目使用
log4j
库创建了一个日志文件,并且必须具有“showLog”功能,该功能创建了一个可以查看日志的框架。此外,当日志文件被修改(附加新的日志消息)时,该帧必须刷新

嗯,除了刷新操作之外,我已经完成了所有操作,这是一个问题,如何进行动态刷新?

这里是我的代码片段,我只放了相关的行:

  • 接口操作:运行事件操作
    
    公共接口操作{
    公共无效执行者();
    }
    

  • 类CadreTexte:创建并管理显示日志文件的框架
    
    公共类CadreTexte扩展了JFrame{
    私有JTextPane日志;
    公共CadreTexte(字符串标题、文件文本){
    超级(滴度);
    if(texte.exists()&&texte.canRead()){
    this.texte=texte;
    }
    否则{
    抛出新的ExceptionGenerators(“NE_文件”);//自己的异常
    }
    InitializeName();
    log=新的JTextPane(); log.setEditable(false); java.net.URL urlFichier=null; 试一试{ urlFichier=texte.toURI().tour(); }捕获(格式错误的异常e1){ 抛出新的例外生成程序(“不可编辑的文本文件”); } 试一试{ log.setPage(urlFichier); } 捕获(IOE异常){ System.out.println(e.getLocalizedMessage());//CATCH }最后{ urlFichier=null; } JScrollPane docSP=setScrollPane();//根据需要的条包含JTextPane getContentPane().setLayout(新的BorderLayout()); getContentPane().add(docSP,BorderLayout.CENTER); } }

  • Vue类:主框架。它有一个操作对象列表,这些对象存储在HashMap中。可以通过菜单访问这些操作。由于这个类非常大,我只放了最重要的几行:

  • 动作执行功能:
    
    已执行的公共无效操作(操作事件e){
    jc组件组件;
    动作处理程序;
    composant=(JComponent)e.getSource();
    String idEvenement=composant.getName();
    modele.log(modele.log_DEBUG,String.format(“evénement.ID:%s”,idEvenement));
    handler=ACTIONS\u MAP.get(idEvenement);
    if(handler==null){
    modele.log(modele.log_错误,“操作不可识别”);
    }否则{
    handler.executer();
    log(modele.log_调试,“Fin操作”);
    }
    }
    

  • 动作可视化日志:
    
    Action visualiserLog=新操作(){
    公共无效执行器(){
    如果(cadreLog==null){
    cadreLog=新的CadreTexte(“Fichier du log”,model.getLogFile());
    visuLog=真;
    }
    否则{
    visuLog=!visuLog;
    }
    cadreLog.visualiser(visuLog);
    }
    };
    

最后,激活visualiserLog操作的MenuItem是一个
JCheckBoxMenuItem

我希望你理解了这个大问题后能帮助我。如果有人需要更多信息,请询问

问候


注:如果有人能编辑并给出正确的问题格式,我将不胜感激,我一直在与编辑斗争,它赢得了我=(

我不确定自动刷新是否是一个好主意:日志文件通常非常频繁地被修改,并且可能很快变得很长,因此您有不断地重新读取长文件以更新该区域的风险,而该区域不断地被更新,可能会变得难以读取

如果您真的想这样做,我认为唯一的解决方案是先读取文件并存储其长度或修改日期,然后启动一个线程,每隔N秒将长度或修改日期与存储在内存中的日期进行比较。如果它已更改,请重新读取文件并更新文本区域和长度或修改日期


小心不要从轮询线程更新文本区域,而是从事件调度线程更新文本区域。使用
SwingUtilities.invokeLater
进行更新。

您可以创建一个自定义log4j appender。您的自定义appender可以以某种方式通知GUI某些内容已被记录,这应该比轮询文件更有效


您可能正在重新发明轮子。看起来它可能提供您需要的功能。

您是否总是在运行时创建一个新的JFrame,用于在JTextPaneNo中显示文件内容。仅在第一次。如果您看到executer函数,则仅当它为空时才会创建框架,并且在应用程序启动时才为空。在现在代码显示或隐藏它,仅此而已。好吧,然后按照@JB Nizet+1的建议,来自
长时间运行的线程
后台任务
的每个操作都必须包装到
invokeLater()
,意思是
log.setPage(urlFichier);
无法配置appender,因为logger类是无法扩展的包装器。这是因为从技术上讲,应用程序不知道logger是log4j,而且尽管logger库发生了更改,但应用程序代码没有更改,只有logger类。最后,我决定根据您的回答。由于只有我的应用程序记录在该文件中,所以我在写新的日志消息时会刷新框架。这样我就避免了轮询。谢谢大家! public interface Action { public void executer(); } public class CadreTexte extends JFrame { private JTextPane log; public CadreTexte(String titre, File texte) { super(titre); if (texte.exists() && texte.canRead()) { this.texte = texte; } else { throw new ExceptionGenerateurs("NE_FILE"); //Own exception } initializeFrame();
log= new JTextPane(); log.setEditable(false); java.net.URL urlFichier = null; try { urlFichier = texte.toURI().toURL(); } catch (MalformedURLException e1) { throw new ExceptionGenerateurs("Fichier de texte non montrable"); } try { log.setPage(urlFichier); } catch (IOException e) { System.out.println(e.getLocalizedMessage()); //CATCH } finally { urlFichier = null; } JScrollPane docSP = setScrollPane(); // bars as needed, contains JTextPane getContentPane().setLayout(new BorderLayout()); getContentPane().add(docSP,BorderLayout.CENTER); } } public void actionPerformed(ActionEvent e) { JComponent composant; Action handler; composant = (JComponent) e.getSource(); String idEvenement = composant.getName(); modele.log(Modele.LOG_DEBUG, String.format("Événement. ID: %s",idEvenement)); handler = ACTIONS_MAP.get(idEvenement); if (handler == null) { modele.log(Modele.LOG_ERROR, "Action non identifiée"); } else { handler.executer(); modele.log(Modele.LOG_DEBUG, "Fin action"); } } Action visualiserLog = new Action() { public void executer() { if (cadreLog == null) { cadreLog = new CadreTexte("Fichier du log", model.getLogFile()); visuLog = true; } else { visuLog = !visuLog; } cadreLog.visualiser(visuLog); } };