2010-04-30 106 views
0

下面的類實現chatGUI。當它運行好屏幕看起來是這樣的:的Java的JTextPane JScrollPane的顯示問題

Fine ChatGUI http://img21.imageshack.us/img21/7177/rightchat.jpg

的問題是很多時候,當我進入大長度即文本。 50 - 100個字的鬼瘋了。聊天記錄框縮小如本

image http://img99.imageshack.us/img99/6962/errorgui.jpg

關於是什麼原因造成這種任何想法?

謝謝。

PS:下面所附的類是完整代碼。你可以複製它並在你的電腦上編譯,以確切地看到我的意思。

注意:一旦GUI發瘋那麼,如果我打了「清除」按鈕的歷史窗口清除和GUI可以追溯到再次正確顯示。

package Sartre.Connect4; 

import javax.swing.*; 
import java.net.*; 
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.text.StyledDocument; 
import javax.swing.text.Style; 
import javax.swing.text.StyleConstants; 
import javax.swing.text.BadLocationException; 
import java.io.BufferedOutputStream; 
import javax.swing.text.html.HTMLEditorKit; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.FileNotFoundException; 
import javax.swing.filechooser.FileNameExtensionFilter; 
import javax.swing.JFileChooser; 


/** 
* Chat form class 
* @author iAmjad 
*/ 
public class ChatGUI extends JDialog implements ActionListener { 

/** 
* Used to hold chat history data 
*/ 
private JTextPane textPaneHistory = new JTextPane(); 

/** 
* provides scrolling to chat history pane 
*/ 
private JScrollPane scrollPaneHistory = new JScrollPane(textPaneHistory); 

/** 
* used to input local message to chat history 
*/ 
private JTextPane textPaneHome = new JTextPane(); 

/** 
* Provides scrolling to local chat pane 
*/ 
private JScrollPane scrollPaneHomeText = new JScrollPane(textPaneHome); 

/** 
* JLabel acting as a statusbar 
*/ 
private JLabel statusBar = new JLabel("Ready"); 

/** 
* Button to clear chat history pane 
*/ 
private JButton JBClear = new JButton("Clear"); 

/** 
* Button to save chat history pane 
*/ 
private JButton JBSave = new JButton("Save"); 

/** 
* Holds contentPane 
*/ 
private Container containerPane; 

/** 
* Layout GridBagLayout manager 
*/ 
private GridBagLayout gridBagLayout = new GridBagLayout(); 

/** 
* GridBagConstraints 
*/ 
private GridBagConstraints constraints = new GridBagConstraints(); 

/** 
* Constructor for ChatGUI 
*/ 
public ChatGUI(){ 

    setTitle("Chat"); 

    // set up dialog icon 
    URL url = getClass().getResource("Resources/SartreIcon.jpg"); 
    ImageIcon imageIcon = new ImageIcon(url); 
    Image image = imageIcon.getImage(); 
    this.setIconImage(image); 

    this.setAlwaysOnTop(true); 

    setLocationRelativeTo(this.getParent()); 
    //////////////// End icon and placement ///////////////////////// 

    // Get pane and set layout manager 
    containerPane = getContentPane(); 
    containerPane.setLayout(gridBagLayout); 
    ///////////////////////////////////////////////////////////// 

    //////////////// Begin Chat History ////////////////////////////// 

    textPaneHistory.setToolTipText("Chat History Window"); 
    textPaneHistory.setEditable(false); 
    textPaneHistory.setPreferredSize(new Dimension(350,250)); 

    scrollPaneHistory.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 
    scrollPaneHistory.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 

    // fill Chat History GridBagConstraints 
    constraints.gridx = 0; 
    constraints.gridy = 0; 
    constraints.gridwidth = 10; 
    constraints.gridheight = 10; 
    constraints.weightx = 100; 
    constraints.weighty = 100; 
    constraints.fill = GridBagConstraints.BOTH; 
    constraints.anchor = GridBagConstraints.CENTER; 
    constraints.insets = new Insets(10,10,10,10); 
    constraints.ipadx = 0; 
    constraints.ipady = 0; 

    gridBagLayout.setConstraints(scrollPaneHistory, constraints); 

    // add to the pane 
    containerPane.add(scrollPaneHistory); 

    /////////////////////////////// End Chat History /////////////////////// 

    ///////////////////////// Begin Home Chat ////////////////////////////// 

    textPaneHome.setToolTipText("Home Chat Message Window"); 
    textPaneHome.setPreferredSize(new Dimension(200,50)); 

    textPaneHome.addKeyListener(new MyKeyAdapter()); 

    scrollPaneHomeText.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 
    scrollPaneHomeText.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 

    // fill Chat History GridBagConstraints 
    constraints.gridx = 0; 
    constraints.gridy = 10; 
    constraints.gridwidth = 6; 
    constraints.gridheight = 1; 
    constraints.weightx = 100; 
    constraints.weighty = 100; 
    constraints.fill = GridBagConstraints.BOTH; 
    constraints.anchor = GridBagConstraints.CENTER; 
    constraints.insets = new Insets(10,10,10,10); 
    constraints.ipadx = 0; 
    constraints.ipady = 0; 

    gridBagLayout.setConstraints(scrollPaneHomeText, constraints); 

    // add to the pane 
    containerPane.add(scrollPaneHomeText); 

    ////////////////////////// End Home Chat ///////////////////////// 

    ///////////////////////Begin Clear Chat History //////////////////////// 

    JBClear.setToolTipText("Clear Chat History"); 

    // fill Chat History GridBagConstraints 
    constraints.gridx = 6; 
    constraints.gridy = 10; 
    constraints.gridwidth = 2; 
    constraints.gridheight = 1; 
    constraints.weightx = 100; 
    constraints.weighty = 100; 
    constraints.fill = GridBagConstraints.BOTH; 
    constraints.anchor = GridBagConstraints.CENTER; 
    constraints.insets = new Insets(10,10,10,10); 
    constraints.ipadx = 0; 
    constraints.ipady = 0; 

    gridBagLayout.setConstraints(JBClear, constraints); 

    JBClear.addActionListener(this); 

    // add to the pane 
    containerPane.add(JBClear); 

    ///////////////// End Clear Chat History //////////////////////// 

    /////////////// Begin Save Chat History ////////////////////////// 

    JBSave.setToolTipText("Save Chat History"); 

    constraints.gridx = 8; 
    constraints.gridy = 10; 
    constraints.gridwidth = 2; 
    constraints.gridheight = 1; 
    constraints.weightx = 100; 
    constraints.weighty = 100; 
    constraints.fill = GridBagConstraints.BOTH; 
    constraints.anchor = GridBagConstraints.CENTER; 
    constraints.insets = new Insets(10,10,10,10); 
    constraints.ipadx = 0; 
    constraints.ipady = 0; 

    gridBagLayout.setConstraints(JBSave, constraints); 

    JBSave.addActionListener(this); 

    // add to the pane 
    containerPane.add(JBSave); 

    ///////////////////// End Save Chat History ///////////////////// 

    /////////////////// Begin Status Bar ///////////////////////////// 
    constraints.gridx = 0; 
    constraints.gridy = 11; 
    constraints.gridwidth = 10; 
    constraints.gridheight = 1; 
    constraints.weightx = 100; 
    constraints.weighty = 50; 
    constraints.fill = GridBagConstraints.BOTH; 
    constraints.anchor = GridBagConstraints.CENTER; 
    constraints.insets = new Insets(0,10,5,0); 
    constraints.ipadx = 0; 
    constraints.ipady = 0; 

    gridBagLayout.setConstraints(statusBar, constraints); 

    // add to the pane 
    containerPane.add(statusBar); 

    ////////////// End Status Bar //////////////////////////// 

    // set resizable to false 
    this.setResizable(false); 

    // pack the GUI 
    pack(); 
} 

/** 
* Deals with necessary menu click events 
* @param event 
*/ 
public void actionPerformed(ActionEvent event) { 

    Object source = event.getSource(); 

    // Process Clear button event 
    if (source == JBClear){ 

     textPaneHistory.setText(null); 
     statusBar.setText("Chat History Cleared"); 
    } 

    // Process Save button event 
    if (source == JBSave){ 

     // process only if there is data in history pane 
     if (textPaneHistory.getText().length() > 0){ 

      // process location where to save the chat history file 
      JFileChooser chooser = new JFileChooser(); 

      chooser.setMultiSelectionEnabled(false); 

      chooser.setAcceptAllFileFilterUsed(false); 

      FileNameExtensionFilter filter = new FileNameExtensionFilter("HTML Documents", "htm", "html"); 

      chooser.setFileFilter(filter); 

      int option = chooser.showSaveDialog(ChatGUI.this); 

      if (option == JFileChooser.APPROVE_OPTION) { 

       // Set up document to be parsed as HTML 
       StyledDocument doc = (StyledDocument)textPaneHistory.getDocument(); 

       HTMLEditorKit kit = new HTMLEditorKit(); 

       BufferedOutputStream out; 

       try { 

        // add final file name and extension 
        String filePath = chooser.getSelectedFile().getAbsoluteFile() + ".html"; 

        out = new BufferedOutputStream(new FileOutputStream(filePath)); 

        // write out the HTML document 
        kit.write(out, doc, doc.getStartPosition().getOffset(), doc.getLength()); 

       } catch (FileNotFoundException e) { 

        JOptionPane.showMessageDialog(ChatGUI.this, 
        "Application will now close. \n A restart may cure the error!\n\n" 
        + e.getMessage(), 
        "Fatal Error", 
        JOptionPane.WARNING_MESSAGE, null); 

        System.exit(2); 

       } catch (IOException e){ 

        JOptionPane.showMessageDialog(ChatGUI.this, 
        "Application will now close. \n A restart may cure the error!\n\n" 
        + e.getMessage(), 
        "Fatal Error", 
        JOptionPane.WARNING_MESSAGE, null); 

        System.exit(3); 

       } catch (BadLocationException e){ 

        JOptionPane.showMessageDialog(ChatGUI.this, 
        "Application will now close. \n A restart may cure the error!\n\n" 
        + e.getMessage(), 
        "Fatal Error", 
        JOptionPane.WARNING_MESSAGE, null); 

        System.exit(4); 
       } 

       statusBar.setText("Chat History Saved"); 
      } 
     } 
    } 
} 

/** 
* Process return key for sending the message 
*/ 
private class MyKeyAdapter extends KeyAdapter { 

    @Override 
    @SuppressWarnings("static-access") 
    public void keyPressed(KeyEvent ke) { 

     //DateTime dateTime = new DateTime(); 
     //String nowdateTime = dateTime.getDateTime(); 

     int kc = ke.getKeyCode(); 

     if (kc == ke.VK_ENTER) { 

      try { 
       // Process only if there is data 
       if (textPaneHome.getText().length() > 0){ 

        // Add message origin formatting 
        StyledDocument doc = (StyledDocument)textPaneHistory.getDocument(); 

        Style style = doc.addStyle("HomeStyle", null); 

        StyleConstants.setBold(style, true); 

        String home = "Home [" + nowdateTime + "]: "; 

        doc.insertString(doc.getLength(), home, style); 

        StyleConstants.setBold(style, false); 

        doc.insertString(doc.getLength(), textPaneHome.getText() + "\n", style); 

        // update caret location 
        textPaneHistory.setCaretPosition(doc.getLength()); 

        textPaneHome.setText(null); 

        statusBar.setText("Message Sent"); 
       } 

      } catch (BadLocationException e) { 

       JOptionPane.showMessageDialog(ChatGUI.this, 
         "Application will now close. \n A restart may cure the error!\n\n" 
         + e.getMessage(), 
         "Fatal Error", 
         JOptionPane.WARNING_MESSAGE, null); 

       System.exit(1); 
      } 
      ke.consume(); 
     } 
    } 
} 
} 
+0

您錯過了啓動應用程序的主要方法。 – OscarRyz 2010-04-30 00:41:11

+0

和'DateTime'的定義。 – trashgod 2010-04-30 00:44:03

+0

重新格式化的代碼;如果不正確請回復。 – trashgod 2010-04-30 00:44:38

回答

4

大量的一般意見優先:

a)當您發佈代碼時發佈SSCCE。如果你不知道SSCCE是什麼搜索論壇或網頁。我們只有有限的時間來看代碼,300線太多了。例如:

  • 代碼設置對話框圖標是風馬牛不相及的問題,並沒有運行,因爲我們沒有訪問您的資源文件
  • 執行保存的代碼是無關緊要的,因爲這是不是你想的proble解決
  • 如前面提到的,main()方法缺少

b)用正確的Java命名約定。變量名稱以小寫字符開頭。 「JBSave」和「JBClear」不是標準名稱,它會讓您的代碼難以閱讀。

C)我也同意了的GridBagLayout是複雜的,其他佈局管理器(如前面給出的BorderLayout的方法)更容易使用。具體你對gridx和gridy的理解是不正確的。它們應該用來表示「連續的」行和列的位置。這是你的情況,你應該使用(0,0),(0,1),(1,1),(2,1)。你跳格子到10。10並不反映相對大小。所以你缺少行,1,2,3,4,5,6,7 ...是的,它可能會起作用,但是在閱讀代碼時理解它會讓人困惑。

d)不要使用KeyListener的處理在textpane Enter鍵。 Swing旨在使用「密鑰綁定」。有關更多信息,請閱讀Swing教程中關於同一主題的部分。

最後修復你的代碼很簡單:

textPaneHome.setToolTipText("Home Chat Message Window"); 
// textPaneHome.setPreferredSize(new Dimension(200,50)); 
    textPaneHome.addKeyListener(new MyKeyAdapter()); 

    scrollPaneHomeText.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 
    scrollPaneHomeText.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 
    scrollPaneHomeText.setPreferredSize(new Dimension(200,50)); 

在一般情況下,你永遠不應該設置添加到滾動窗格組件的首選大小。 在這種情況下,當您將文本設置爲null時,首選大小將重置爲0,並且所有組件的佈局似乎都將重新進行。

+0

@camickr:你解決了它!我經常發現,像這樣的小活動可以持續一段時間的發展。你的解決方案非常好。我將在未來兌現你的其他評論。即儘可能減少代碼,這樣讀者只能看到手頭的問題。我認爲我附上的代碼就是這樣做的,但晚些時候,我沒有明確地指出,並且從瀏覽本網站我看到附件往往冗長的代碼,所以我不認爲這是一個問題。是的,保持英語是好的做法,除非他不明白。 – iTEgg 2010-04-30 11:36:18

+0

@camichr:關於命名約定,即時通訊仍然非常新,而且沒有內涵,我傾向於稍微滑動一下。希望隨着時間的推移完善。 – iTEgg 2010-04-30 11:41:08

+0

@camichr:關於gridbaglayout佈局設計。我遵循不同的佈局組件的風格,可能會讓不熟悉我的代碼的人感到困惑。我所做的是使用比例表繪製佈局,然後對其進行編碼。它爲我服務的很好。 – iTEgg 2010-04-30 11:43:15

2

問題可能是您使用的佈局管理器。

您有所有組件的GridBagLayout。嘗試在自己的面板中添加底部組件,而不是將它們與歷史文本區域對齊。

喜歡的東西:

JScrollPane history = new JScrollPane(new JTextPane()); 

JPanel inputClearSavePane = new JPanel(); 
// layout the input, clear save button 

getContentPane().add(history); 
getContentPane().add(inputClearSavePane, BorderLayout.SOUTH); 

,看看有沒有幫助。 編輯

順便說一句,它在Mac

works on my machine http://img293.imageshack.us/img293/5785/capturadepantalla201004v.png

的Linux

on linux http://img72.imageshack.us/img72/7384/capturadepantalla201004uy.png

和Windows:

alt text http://img97.imageshack.us/img97/7706/capturadepantalla201004hy.png

+0

+1我錯過了關於佈局的問題的本質 – trashgod 2010-04-30 00:52:32

+0

@Oscar:如果你輸入很多沒有任何空格的字符,那麼會發生什麼? – iTEgg 2010-04-30 00:58:20

+0

@Oscar:在你的代碼中,你改變了inputclearsave ..狀態欄呢? – iTEgg 2010-04-30 01:10:28