以下类实现了chatGUI。当它运行正常时,屏幕看起来像这样:
Fine ChatGUI http://img21.imageshack.us/img21/7177/rightchat.jpg
当我输入大长度的文本时,问题经常发生。 50 - 100 chars gui变得疯狂。聊天记录框缩小,如此
所示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 :(得分:4)
首先是很多一般性评论:
a)发布代码时发布SSCCE。如果你不知道SSCCE是什么搜索论坛或网站。我们只有有限的时间来查看代码,300行是太多了。例如:
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旨在使用“Key Bindings”。有关详细信息,请阅读相同主题的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,并且所有组件的布局似乎都将重做。
答案 1 :(得分: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 );
看看是否有帮助。 的修改
BTW,它适用于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