在Jtextpane中向上移动文本

时间:2014-05-14 05:06:12

标签: java swing jscrollpane jtextpane jscrollbar

Jtextpane (在Jscrollpane中)每当我们输入文本时,它将从上到下打印,

是否可以将滚动条保持在底部,并在添加文本时向上移动旧文本(启用滚动条)?

例如:如果用户位于第1行并输入" xyz"然后按ENTER键。应该启用滚动条,并且应该在第二行使用插入符号向上移动xyz。因此,如果用户向上滚动,他将能够看到" xyz"。

问题与我以前的问题类似。我想说清楚得到答案。

感谢。

修改

public class TextPane extends JFrame implements ActionListener, KeyListener{
public static TextPane instance;
private static JTextPane terminal = new JTextPane();
private static JScrollPane scroll = new JScrollPane();

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            TextPane.getInstance().init();
        }
    });
}
private static TextPane getInstance() {
    if(null == instance){
        instance =  new TextPane();
    }
    return instance;
}
private EnterAction enterAction;

private void init() {
    terminal.setFont(new Font("Courier new", Font.PLAIN, 12));
    terminal.setLayout(new BorderLayout());
    terminal.setBackground(Color.black);
    terminal.setForeground(Color.white);
    terminal.addKeyListener(this);
    terminal.setCaretColor(Color.green);
    terminal.setDragEnabled(false);

    enterAction = new EnterAction();
    terminal.getInputMap().put( KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "enter");
    terminal.getActionMap().put("enter", enterAction);

    DefaultCaret caret = (DefaultCaret) terminal.getCaret();
    caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
    scroll.setViewportView(terminal);
    add(scroll);     
    setTitle("Dummy");
    setSize(500 , 500);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setResizable(true);
    setVisible(true);
}

class EnterAction extends AbstractAction {
   //I typed a single line (in first line) of text and pressed enter.
    private static final long serialVersionUID = 1L;  
    public void actionPerformed(ActionEvent ae ) {
        try {
            Document doc = terminal.getDocument();
            int car = terminal.getCaretPosition();

            //Currently i tried adding newlines to get scroll bar in order to hide previously displayed contents.
            for(int i=0 ; i< 35 ; i++){
               doc.insertString(doc.getLength(), "\n", null);
            }               
            terminal.setCaretPosition(car + 1); // To set the caret at second line.
            JScrollBar sb = scroll.getVerticalScrollBar();
            sb.setValue( sb.getMaximum());//to keep the scroll bar at bottom.(Any how above setCaretPositon() makes it not work).
        } catch (Exception ex) {
            ex.printStackTrace();

        }
    }
}
@Override
public void actionPerformed(ActionEvent e) {}

@Override
public void keyTyped(KeyEvent e) {}

@Override
public void keyPressed(KeyEvent e) {}

@Override
public void keyReleased(KeyEvent e) {}

}

2 个答案:

答案 0 :(得分:1)

我认为这就是你想要的。一些说明:

  1. 与您的示例一样,代码使用空行填充文档。虽然在此示例中,只有在创建文本组件时才会添加一行。
  2. 在EnterAction中使用invokeLater将代码添加到Event Dispatch Thread的末尾。这确保了对Document的所有更新都已完成,因此滚动条的最大值将是正确的。
  3. 我使用了JTextArea,因为根据初始化文本区域所需的空白行数很容易控制文本区域的大小。如果使用JTextPane,则需要执行额外的计算以确定文本窗格的实际大小,以便滚动条正常工作。
  4. 作为奖励,我创建了一个简单的NavigationFilter,它将阻止用户将插入符号移动到文档末尾的任何空白行。此功能还可以防止使用鼠标选择任何空行。
  5. 仍然可以删除空白行。因此,您可能希望创建一个在按下“删除”键时不执行任何操作的KeyBinding。
  6. 覆盖框架宽度的代码只是为了防止第一次在文本窗格中输入任何数据时出现水平滚动条。您可能需要考虑始终显示滚动条,因为无论如何在添加第一行数据后它将一直显示。
  7. 守则:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.text.*;
    
    public class NavigationFilterSuffix extends NavigationFilter
    {
        private int suffixLength;
        private Document doc;
    
        public NavigationFilterSuffix(int suffixLength, Document doc)
        {
            this.suffixLength = suffixLength;
            System.out.println(suffixLength);
            this.doc = doc;
        }
    
        public void setDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
        {
            int endOfDocument = doc.getLength() - suffixLength + 1;
            fb.setDot(Math.min(dot, endOfDocument), bias);
        }
    
        public void moveDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias)
        {
            int endOfDocument = doc.getLength() - suffixLength + 1;
            fb.moveDot(Math.min(dot, endOfDocument), bias);
        }
    
        public static void main(String args[]) throws Exception
        {
            final JTextArea terminal = new JTextArea(15, 30);
            // add 14 new lines (one less than rows specified above
            terminal.setText("\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
            terminal.setFont(new Font("Courier new", Font.PLAIN, 12));
            terminal.setBackground(Color.black);
            terminal.setForeground(Color.white);
            terminal.setCaretColor(Color.green);
            terminal.setDragEnabled(false);
            terminal.setCaretPosition(0);
    
            final JScrollPane scrollPane = new JScrollPane( terminal );
    
            Action enterAction = new EnterAction();
            terminal.getInputMap().put( KeyStroke.getKeyStroke("ENTER"), "enter");
            terminal.getActionMap().put("enter", enterAction);
    
            terminal.setNavigationFilter(new NavigationFilterSuffix(terminal.getRows(), terminal.getDocument()));
    
            JFrame frame = new JFrame("Navigation Filter Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(scrollPane);
            frame.pack();
            Dimension d = frame.getSize();
            d.width += 20;
            frame.setSize(d);
            frame.setLocationRelativeTo( null );
            frame.setVisible(true);
        }
    
    
        static class EnterAction extends AbstractAction
        {
            public void actionPerformed(ActionEvent ae )
            {
                try
                {
                    final JTextArea terminal = (JTextArea)ae.getSource();
                    Document doc = terminal.getDocument();
                    int car = terminal.getCaretPosition();
                    doc.insertString(car, "\n", null);
    
                    SwingUtilities.invokeLater(new Runnable()
                    {
                        public void run()
                        {
                            JScrollPane scrollPane = (JScrollPane)SwingUtilities.getAncestorOfClass(JScrollPane.class, terminal);
                            JScrollBar sb = scrollPane.getVerticalScrollBar();
                            sb.setValue( sb.getMaximum());
                        }
                    });
    
                }
                catch (Exception ex)
                {
                    ex.printStackTrace();
                }
            }
        }
    }
    
    祝你好运。

答案 1 :(得分:0)

根据上述对话的示例代码。请检查这是否能解决您的目的。

public class ThingDoer extends JPanel {

    public ThingDoer() {
        JTextArea text = new JTextArea(1, 10);
        text.setLineWrap(true);
        text.setWrapStyleWord(true);

        JScrollPane scrollPane = new JScrollPane(text,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
                );
        add(scrollPane);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.add(new ThingDoer());
        frame.pack();
        frame.setSize(200, 300);
        frame.setVisible(true);
    }
}