简体   繁体   English

在Jtextpane中向上移动文本

[英]Moving text upwards in Jtextpane

In a Jtextpane (with in a Jscrollpane) whenever we enter text it will be printed from top to bottom, Jtextpane (在Jscrollpane中)中,只要我们输入文字,它就会从上到下打印,

is it possible to keep the scroll bar at the bottom and move old text upwards(enabling scrollbar) whenever a text is appended? 是否可以将滚动条保持在底部并在添加文本时向上移动旧文本(启用滚动条)?

eg : if user is at line 1 and types "xyz" and press ENTER . 例如:如果用户在第1行,然后键入“ xyz”,然后按Enter。 Scrollbar should be enabled and xyz should be moved upwards with caret at second line.So if user scrolls up he will be able to see "xyz". 应当启用滚动条,并在第二行的插入符号处向上移动xyz。因此,如果用户向上滚动,他将能够看到“ xyz”。

The problem is similar to my previous questions. 这个问题和我以前的问题类似。 I am trying to make it clear to get an answer. 我正在努力弄清楚得到答案。

Thanks. 谢谢。

EDIT 编辑

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) {}

} }

I think this is what you want. 我想这就是你想要的。 Some notes: 一些注意事项:

  1. Like your example the code uses blank lines to fill up the document. 像您的示例一样,代码使用空白行来填充文档。 Although in this example the lines are only ever added once when the text component is created. 尽管在此示例中,创建文本组件时仅将行添加一次。
  2. The invokeLater is used in the EnterAction to add the code to the end of the Event Dispatch Thread. 在EnterAction中使用invokeLater将代码添加到Event Dispatch Thread的末尾。 This makes sure that all updates to the Document have been completed and therefore the maximum value of the scrollbar will be correct. 这样可确保对文档的所有更新均已完成,因此滚动条的最大值将是正确的。
  3. I used a JTextArea because it is easy to control the size of the text area based on the number of blank lines you need to initialize the text area. 我使用了JTextArea,因为它很容易根据初始化文本区域所需的空白行数来控制文本区域的大小。 If you use a JTextPane then you will need to do extra calculations to determine the actual size of the text pane so that the scrollbars work correctly. 如果使用JTextPane,则需要进行额外的计算以确定文本窗格的实际大小,以便滚动条正常工作。
  4. As a bonus I created a simple NavigationFilter which will prevent the user from moving the caret to any of the blank lines at the end of the Document. 作为奖励,我创建了一个简单的NavigationFilter,它将防止用户将插入符移动到文档末尾的任何空白行。 This feature will also prevent text selection for any of those blank lines using the mouse. 此功能还将防止使用鼠标为任何这些空白行选择文本。
  5. It is still possible to delete the blank lines. 仍然可以删除空白行。 So you may want to create a KeyBinding that does nothing when the "Delete" key is pressed. 因此,您可能想创建一个在按下“删除”键时不执行任何操作的KeyBinding。
  6. The code to override the width of the frame is just to prevent the horizontal scrollbar from appearing the first time you enter any data in the text pane. 覆盖框架宽度的代码只是为了防止水平滚动条在您第一次在文本窗格中输入任何数据时出现。 You may want to consider to always display the scrollbar, since it will continually be visible after you add the first line of data anyway. 您可能要考虑始终显示滚动条,因为无论如何添加第一行数据后,滚动条将一直可见。

The Code: 编码:

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();
            }
        }
    }
}

Good luck. 祝好运。

Sample code as per the conversation above. 根据上面的对话的示例代码。 Please check if this solves your purpose. 请检查是否可以解决您的目的。

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM