javaswingjtextpane

Java Swing: User typing text - inserting it in the middle of a sentence: The problem is the cursor jumps to the end after each letter being typed


I know Java Swing is dated, but I still use it. Mostly I use JTextArea and it works fine, if the users wants to insert text in the middle of existing text. But there is no line spacing in JTextArea and in Hebrew with punctation the punctation of the lines above and below overlap. Therefore I used a JTextPane instead and was able to change the line spacing. BUT if the user wants to insert text into an existing text, the cursor jumps to the end of the text after EACH letter. That makes inserting text tedious.

I did a lot of googling, but have not found anything on this topic.

Here is my code:

  hebrewField = new JTextPane();
  hebrewField.setFont(ApplicationFonts.getHebrewFont(30F));
  hebrewField.setDocument(new NikudStyledDocument(true));
  hebrewField.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);     
  hebrewField.setMinimumSize(new Dimension(Settings.getKeyboardWidth() - 30,
        (heightTotal - heightBorderTitel)));
  hebrewField.setMaximumSize(
        new Dimension(this.widthTotal, (heightTotal - heightBorderTitel)));
  hebrewField.setBorder(
        BorderFactory.createTitledBorder(translator.realisticTranslate(
              Translation.HEBRAEISCH__EINFACHE_SCHREIBWEISE)));
  changeLineSpacing(hebrewField);

and

 private void changeLineSpacing(JTextPane pane) {
  SimpleAttributeSet set = new SimpleAttributeSet(pane.getParagraphAttributes());
  StyleConstants.setLineSpacing(set, 0.5F);
  pane.setParagraphAttributes(set, true);
  }

Does anyone still remember how to go about this in Java Swing? Any ideas are appreciated. Thank you for your kindness.

JTextPane

UPDATE

Here the text is set. I guess I have to set the caret position after inserting the text.

public void mousePressed(MouseEvent e)
  {
     DataButton jButton = (DataButton) e.getComponent();
     String caption = jButton.getData();

     JTextComponent focusElement = findFocusElement();
     if (focusElement != null)
     {
        int position = focusElement.getCaretPosition();
        String text = focusElement.getText();
        String before = text.substring(0, position);
        String after = text.substring(position);
        focusElement.setText(before + caption + after);
        focusElement.requestFocus();
     }
  }

UPDATE

Here is the minimal reproducible example:

import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;

public class Testing
{
   public static void main(String[] args)
   {     
      SwingUtilities.invokeLater(() -> {
      javax.swing.JFrame window = new JFrame();
      JPanel panel = new JPanel();
     
      JButton buttonM = new JButton("M");
      JButton buttono = new JButton("o");
      JButton buttont = new JButton("t");
      JButton buttonh = new JButton("h");
      JButton buttone = new JButton("e");
      JButton buttonr = new JButton("r");
      JButton buttonSpace = new JButton(" ");

      JTextPane textPane = new JTextPane();
      textPane.setPreferredSize(new Dimension(580,200));
     
      addActionListener(buttonM, textPane);
      addActionListener(buttono, textPane);
      addActionListener(buttont, textPane);
      addActionListener(buttonh, textPane);
      addActionListener(buttone, textPane);
      addActionListener(buttonr, textPane);
      addActionListener(buttonSpace, textPane);
     
      panel.add(textPane);
      panel.add(buttonM);
      panel.add(buttono);
      panel.add(buttont);
      panel.add(buttonh);
      panel.add(buttone);
      panel.add(buttonr);
      panel.add(buttonSpace);
     
      window.add(panel);
    window.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
     window.setSize(new Dimension(600, 400));
     window.setLocationRelativeTo(null);
     window.setVisible(true);
  });
}

   private static void addActionListener(JButton button, JTextPane textPane)
   {
  button.addActionListener(event -> {
     String caption = button.getText();
     int position = textPane.getCaretPosition();
     String text = textPane.getText();
     String before = text.substring(0, position);
     String after = text.substring(position);
     textPane.setText(before + caption + after);
     textPane.requestFocus();
     // textPane.setCaretPosition(position + 1); // this was missing
  });
  }
  }

Solution

  • Thank you Abra for your requests. It made me rethink the problem. And here is the solution. The text is added letter by letter and after each letter the caret position has to be advanced by one.

    public void mousePressed(MouseEvent e)
      {
         DataButton jButton = (DataButton) e.getComponent();
         String caption = jButton.getData();
    
         JTextComponent focusElement = findFocusElement();
         if (focusElement != null)
         {
            int position = focusElement.getCaretPosition();
            String text = focusElement.getText();
            String before = text.substring(0, position);
            String after = text.substring(position);
            focusElement.setText(before + caption + after);
            focusElement.requestFocus();
            focusElement.setCaretPosition(position + 1); //this was missing
         }
      }