找到你要的答案

Q:Can I use a keypress combination to scroll up or down in a JTextArea inside a JScrollPane?

Q:我可以使用一个按键组合在JScrollPane个JTextArea向上或向下滚动?

If the text area has the focus, of course the PgUp and PgDn keys work fine, but I was hoping to scroll it up or down using key bindings, leaving the focus where it is instead of moving it to text area and back.

So I've mapped VK_PAGEDOWN with CTRL_DOWN_MASK to a menu items in hopes that when the user presses Ctrl+PgDn the program would scroll the text area by 20 lines.

But while txaOutput.getLineCount() returns number of lines in text area, I can't find a way to set the caret line to that number minus 20. txaOutput.setCaretPosition(int i) sets caret at BYTE number i.

What I've done is bogus, but it does scroll (Page Up is identical except - scrollBytes):

    PageDown = new KeyBoundMenuItem("PAGEDOWN", VK_PAGE_DOWN, CTRL_DOWN_MASK) 
    {
      @Override
      public void action(ActionEvent e) {
          scrollBytes = 20 * totalBytesInTextArea / txaOutput.getLineCount();
          try{
              txaOutput.setCaretPosition(txaOutput.getCaretPosition() + scrollBytes);
          }catch(Exception ex){}
      }
    };

Is there a way to set the caret to a particular line number in a JTextArea in a JScrollPane?

EDIT

The text area contains single words of 3 to 11 letters per line.

EDIT 2

Here's why it's action and not actionPerformed:

import java.awt.event.ActionEvent;
import javax.swing.*;
import static javax.swing.KeyStroke.getKeyStroke;

public abstract class KeyBoundMenuItem extends JMenuItem{

  public abstract void action(ActionEvent e);


      public KeyBoundMenuItem(String actionMapKey, int key, int mask)
      {
        Action myAction = new AbstractAction()
        {
          @Override public void actionPerformed(ActionEvent e)
          {
            action(e);
          }
        };  

        setAction(myAction);

        getInputMap(WHEN_IN_FOCUSED_WINDOW)
                      .put(getKeyStroke(key, mask),actionMapKey);
        getActionMap().put(                        actionMapKey, myAction);

      }
    }

EDIT 3

Could have used this instead of KeyBoundMenuItem:

  public static void shortcut(JMenuItem item, int mnem, int mods, int key)
  {  
    item.setMnemonic(mnem);
    item.setAccelerator(getKeyStroke(key,mods));
  }

But had code in place for the analogous class KeyBoundButton. Easy change to make late in day.

EDIT 4

Here's the sort of text needing scrolling up or down:

如果文本区的重点,当然,下翻页键上工作的很好,但我希望它向上或向下滚动使用键绑定,让注意力集中在它是不是移动到文本区和背。

所以我vk_pagedown与ctrl_down_mask映射到菜单项希望当用户按下Ctrl +下翻页程序会滚动的文本区域,由20条线。

但txaoutput。getlinecount()返回在文本区域中的行数,我不能找到一种方式来设置插入线数量减20。txaoutput。setcaretposition(int i)套在我插入的字节数

我所做的一切都是假的,但它滚动(上一页是相同的- scrollbytes除外):

    PageDown = new KeyBoundMenuItem("PAGEDOWN", VK_PAGE_DOWN, CTRL_DOWN_MASK) 
    {
      @Override
      public void action(ActionEvent e) {
          scrollBytes = 20 * totalBytesInTextArea / txaOutput.getLineCount();
          try{
              txaOutput.setCaretPosition(txaOutput.getCaretPosition() + scrollBytes);
          }catch(Exception ex){}
      }
    };

有没有一种方法来设置符号在JScrollPane JTextArea特定行数了吗?

编辑

文本区域包含每行3到11个字母的单个单词。

编辑 2

这就是为什么它的行动并没有之前:

import java.awt.event.ActionEvent;
import javax.swing.*;
import static javax.swing.KeyStroke.getKeyStroke;

public abstract class KeyBoundMenuItem extends JMenuItem{

  public abstract void action(ActionEvent e);


      public KeyBoundMenuItem(String actionMapKey, int key, int mask)
      {
        Action myAction = new AbstractAction()
        {
          @Override public void actionPerformed(ActionEvent e)
          {
            action(e);
          }
        };  

        setAction(myAction);

        getInputMap(WHEN_IN_FOCUSED_WINDOW)
                      .put(getKeyStroke(key, mask),actionMapKey);
        getActionMap().put(                        actionMapKey, myAction);

      }
    }

编辑 3

可以用这个代替KeyBoundMenuItem:

  public static void shortcut(JMenuItem item, int mnem, int mods, int key)
  {  
    item.setMnemonic(mnem);
    item.setAccelerator(getKeyStroke(key,mods));
  }

但有代码,类似的类keyboundbutton。容易改变,使晚。

编辑 4

以下是需要滚动向上或向下滚动的文本类型:

answer1: 回答1:

Is there a way to set the caret to a particular line number

Check out the Text Utilities class. Methods like:

  1. getLineAtCaret() and
  2. gotoStartOfLine(...)

should allow you to do what you want. That is to scroll down you can do:

int currentLine = RXTextUtilities.getLineAtCaret(textArea);
RXTextUtilities.gotoStartOfLine(textArea, currentLine + 10);

有没有一种方法来设置插入到一个特定的行数

检查文本实用程序类。方法:

  1. getLineAtCaret() and
  2. gotoStartOfLine(...)

应该让你做你想做的。那是向下滚动你可以做:

int currentLine = RXTextUtilities.getLineAtCaret(textArea);
RXTextUtilities.gotoStartOfLine(textArea, currentLine + 10);
answer2: 回答2:

Thanks to @camickr, here's what worked (code for PAGEUP is identical except for - instead of +:

PageDown = new KeyBoundMenuItem("PAGEDOWN", VK_PAGE_DOWN, CTRL_DOWN_MASK) 
{
  @Override
  public void action(ActionEvent e) 
  {
      int currentLine = RXTextUtilities.getLineAtCaret(txaOutput);
      RXTextUtilities.gotoStartOfLine(
        txaOutput, 
        currentLine + RXTextUtilities.maxLinesVisibleInWindow(txaOutput));
  }
};

I should probably have revised this code to reflect his valid criticism that I didn't have to make an abstract class to accomplish the key binding, but it ain't broke. (I may get around to it one day...)

I even figured out (by studying his Text Utilities) how to scroll the window without using a constant (28, see comments):

  public static int maxLinesVisibleInWindow(JTextComponent component)
  {
      Container container = getAncestorOfClass(JViewport.class, component);

    if (container == null) return 0;

    JViewport   viewport        = (JViewport)container;
    int         extentHeight    = viewport.getExtentSize().height;
    FontMetrics fm              = component.getFontMetrics(component.getFont());
    int         characterHeight = fm.getHeight();

    return (int)extentHeight/characterHeight - 1;
  }

感谢@ camickr,这里就是工作(代码页是相同的除了代替+:

PageDown = new KeyBoundMenuItem("PAGEDOWN", VK_PAGE_DOWN, CTRL_DOWN_MASK) 
{
  @Override
  public void action(ActionEvent e) 
  {
      int currentLine = RXTextUtilities.getLineAtCaret(txaOutput);
      RXTextUtilities.gotoStartOfLine(
        txaOutput, 
        currentLine + RXTextUtilities.maxLinesVisibleInWindow(txaOutput));
  }
};

我可能已经修改了这个代码,以反映他有效的批评,我不必做一个抽象的类来完成密钥绑定,但它没有打破。总有一天我会得到它…)

我甚至想出了(通过研究他的文本工具)如何在不使用常量的情况下滚动窗口(28,见注释):

  public static int maxLinesVisibleInWindow(JTextComponent component)
  {
      Container container = getAncestorOfClass(JViewport.class, component);

    if (container == null) return 0;

    JViewport   viewport        = (JViewport)container;
    int         extentHeight    = viewport.getExtentSize().height;
    FontMetrics fm              = component.getFontMetrics(component.getFont());
    int         characterHeight = fm.getHeight();

    return (int)extentHeight/characterHeight - 1;
  }
java  swing  jscrollpane  jtextarea  key-bindings