2012-10-25 112 views
1

這是從Display and interact with an HTML form in a Swing application開始的問題。我已經複製了代碼並在Eclipse(Indigo)中成功運行它,但出於某種神祕的原因,它停止工作。我能夠連續運行數次,但現在我很幸運,如果我能夠完全實現它的話。JFrame在之前顯示之前停止顯示

在調試下運行它與JUnit,它我單步加強到javax.swing.SwingUtilities.invokeLater(new Runnable() {行;下一步直接跳到System.in.read()行,有效地跳過顯示邏輯。

我懷疑它有一些東西給invokeLater方法。從我的研究中,invokeLater將其Runnable()放在調度隊列中,並且每當VM接近它時將運行Runnable。有一些提到,如果一個Runnable()經驗和例外它不會「放鬆」,我認爲這意味着它不會關閉,並最終會阻止隊列。我懷疑我的一個調用已經停止並阻塞隊列,但不知道爲什麼或如何清除隊列。

問題: 有什麼辦法可以清除隊列嗎?我已經停止並重新啓動Eclipse幾次,認爲這將清除調度隊列,但沒有運氣。

是否有可能就Java而言,JFrame顯示,但它並沒有實際顯示在屏幕上,所以我可以點擊提交按鈕?什麼會造成這種情況?爲什麼它會連續多次工作,然後突然停止?

下面是相關的代碼。

JUnit的存根:

@Test 
public final void testTestForms() { 
    // https://stackoverflow.com/questions/6145405/display-and-interact-with-an-html-form-in-a-swing-application 
    Navigate n = new Navigate(); 
    try { 
     n.testForms(); 
     n= null; // in desperate attempt to garbage collect 
    } catch (IOException e) { 
     System.out.println("Error invoking n.testForms()"); 
     e.printStackTrace(); 
     n= null; 
    } 
    n = null; 

} 

研究專題:

public class Navigate { 
@Test 
public void testForms() throws IOException { 
    System.out.println("in testForms()"); 
    javax.swing.SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      System.out.println("in run()"); 
      javax.swing.JFrame jf = new javax.swing.JFrame(); 
      jf.setSize(300, 300); 
      jf.setVisible(true); 
      jf.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); 

      JTextPane textPane = new JTextPane(); 
      textPane.setContentType("text/html"); 
      textPane.setEditable(false); 
      textPane.setText("<html>" + "<body>" + "<form action=\"#\">" 
        + "<input name=\"input1\" type=\"text\" />" 
        + "<input name=\"input2\" type=\"text\" /><br/>" 
        + "<input name=\"cb1\" type=\"checkbox\" /><br/>" 
        + "<input name=\"rb1\" type=\"radio\" /><br/>" 
        + "<input type=\"submit\" value=\"go\" />" + "</form>" 
        + "</body>" + "</html>"); 

      jf.getContentPane().setLayout(
        new BoxLayout(jf.getContentPane(), BoxLayout.Y_AXIS)); 

      jf.getContentPane().add(textPane); 

      HTMLEditorKit kit = (HTMLEditorKit) textPane.getEditorKit(); 
      kit.setAutoFormSubmission(false); 
      textPane.addHyperlinkListener(new HyperlinkListener() { 
       public void hyperlinkUpdate(HyperlinkEvent e) { 
        if (e instanceof FormSubmitEvent) { 
         System.out.println(((FormSubmitEvent) e).getData()); 
        } 
       } 
      }); 
     } 
    } 
); 
    // try to catch exceptions that could plug the queue? 
    try { 
     System.in.read(); 
    } catch (IOException e) { 
    System.out.println("Error with System.in.read()"); 
     e.printStackTrace(); 
     throw new IOException(e); 
    } 
    try { 
     finalize(); // another desperate attempt 
    } catch (Throwable e) { 
     e.printStackTrace(); 
    } 
} 
} 
+1

你試過'SwingUtilities.invokeAndWait'代替? – MadProgrammer

+0

@MadProgrammer +1是可以工作的。 –

回答

2

是否有可能儘可能的Java來講JFrame是 顯示,但它實際上沒有顯示出來在屏幕上,我可以 擊中提交按鈕?什麼會造成這種情況?爲什麼它會連續數次運行 ,然後突然停止?

是的,因爲您在JFrame實例上調用setVisible(true)實例,然後再添加所有組件。

也有在你的代碼中的其他異常可能導致的問題:只設置JFrame可見 前

  • 不要調用JFrame#setVisible(true)所有組件之前已被添加到JFrame
  • 不要調用JFrame#setSize(..),而調用JFrame#pack()
  • 您的SwingUtilities.invokeLater(..)不應該嵌套在JFrame類本身中,而應該使其包含在中以創建JFrame實例
  • 不要電話System.in.read()這將阻止EDT線程和你的用戶界面將凍結
  • 不要依靠調用創建JFrame實例(testForms())的方法,確保JFrame實例類的構造函數中創建。

這裏是
的一個實例我做:

enter image description here

import javax.swing.BoxLayout; 
import javax.swing.JTextPane; 
import javax.swing.event.HyperlinkEvent; 
import javax.swing.event.HyperlinkListener; 
import javax.swing.text.html.FormSubmitEvent; 
import javax.swing.text.html.HTMLEditorKit; 

public class JavaApplication26 { 

    public static void main(String[] args) { 

     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       //create new instance of JFrame 
       new Navigate(); 
      } 
     }); 
    } 
} 

class Navigate { 

    public Navigate() { 
     initComponents(); 
    } 

    private void initComponents() { //this is a constructor 

     javax.swing.JFrame jf = new javax.swing.JFrame(); 
     jf.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); 

     JTextPane textPane = new JTextPane(); 
     textPane.setContentType("text/html"); 
     textPane.setEditable(false); 
     textPane.setText("<html>" + "<body>" + "<form action=\"#\">" 
       + "<input name=\"input1\" type=\"text\" />" 
       + "<input name=\"input2\" type=\"text\" /><br/>" 
       + "<input name=\"cb1\" type=\"checkbox\" /><br/>" 
       + "<input name=\"rb1\" type=\"radio\" /><br/>" 
       + "<input type=\"submit\" value=\"go\" />" + "</form>" 
       + "</body>" + "</html>"); 

     HTMLEditorKit kit = (HTMLEditorKit) textPane.getEditorKit(); 
     kit.setAutoFormSubmission(false); 
     textPane.addHyperlinkListener(new HyperlinkListener() { 
      @Override 
      public void hyperlinkUpdate(HyperlinkEvent e) { 
       if (e instanceof FormSubmitEvent) { 
        System.out.println(((FormSubmitEvent) e).getData()); 
       } 
      } 
     }); 

     //add components 
     jf.getContentPane().setLayout(new BoxLayout(jf.getContentPane(), BoxLayout.Y_AXIS)); 
     jf.getContentPane().add(textPane); 

     jf.pack();//pack 
     jf.setVisible(true); 
    } 
} 
+0

+1不錯的工作! ... – MadProgrammer

+1

感謝您的新例子和建議。在這方面仍然是新的,只是做了一個簡單的代碼剪切和粘貼,所以我可以玩它。 它必須是JUnit的東西,因爲當通過JUnit的測試存根運行示例時,它的行爲方式是相同的 - 跳過顯示邏輯。同時運行我的原始和您的示例與靜態main()每次都一直工作。 –