2010-04-30 102 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