Java JTextPane JScrollPane Отображение Проблема - PullRequest
0 голосов
/ 30 апреля 2010

Следующий класс реализует chatGUI. Когда все работает нормально, экран выглядит так:

Прекрасный ChatGUI http://img21.imageshack.us/img21/7177/rightchat.jpg

Проблема очень часто возникает при вводе текста большой длины, т.е. 50 - 100 символов, GUI сходит с ума. окно истории чата уменьшается, как показано на этом

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

Любые идеи относительно того, что вызывает это?

Спасибо.

PS: прикрепленный класс ниже является полным кодом. Вы можете скопировать его и скомпилировать на своем компьютере, чтобы точно понять, что я имею в виду.

ПРИМЕЧАНИЕ: как только 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();
        }
    }
}
}

Ответы [ 2 ]

4 голосов
/ 30 апреля 2010

Сначала много общих комментариев:

а) Размещать SSCCE при отправке кода. Если вы не знаете, что такое SSCCE, выполните поиск на форуме или в Интернете. У нас есть только ограниченное время для просмотра кода, а 300 строк - это слишком много. Например:

  • код установлен, значок диалога не имеет отношения к проблеме и не запускается, так как у нас нет доступа к вашему файлу ресурса
  • код для сохранения не имеет значения, так как это не та проблема, которую вы пытаетесь решить
  • как упоминалось ранее, метод main () отсутствует

b) использовать надлежащие соглашения об именах Java. Имена переменных начинаются с символа нижнего регистра. «JBSave» и «JBClear» не являются стандартными именами, и это затрудняет чтение кода.

в) Я также согласен с тем, что Gridbaglayout сложен, а другие менеджеры компоновки (такие как подход BorderLayout, приведенный ранее) проще в использовании. В частности, ваше понимание gridx и gridy неверно. Их следует использовать для указания «последовательных» позиций строк и столбцов. То есть в вашем случае вы должны использовать (0, 0), (0, 1), (1, 1), (2, 1). Вы перепрыгнули свою сетку до 10. 10 не отражает относительный размер. Таким образом, вам не хватает строк, 1, 2, 3, 4, 5, 6, 7 ... Да, это может работать, но сбивать с толку понимание при чтении кода.

d) Не используйте KeyListener для обработки клавиши 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));

Как правило, вы никогда не должны устанавливать предпочтительный размер компонента, добавляемого в область прокрутки. В этом случае, когда вы устанавливаете нулевой текст, предпочтительный размер сбрасывается до 0, и компоновка всех компонентов, кажется, переделывается.

2 голосов
/ 30 апреля 2010

Возможно, проблема в используемом менеджере раскладки.

У вас есть 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 );

И посмотри, поможет ли это. 1010 * редактировать *

Кстати, работает на Mac

работает на моей машине http://img293.imageshack.us/img293/5785/capturadepantalla201004v.png

Linux

в Linux http://img72.imageshack.us/img72/7384/capturadepantalla201004uy.png

И окна:

альтернативный текст http://img97.imageshack.us/img97/7706/capturadepantalla201004hy.png

...