georgezhang006
georgezhang006

Reputation: 19

How do you add both JTextPane and JTextArea to a JScrollPane?

I am trying to make a notepad like application in java.

Something like this: enter image description here

I want to have the part on the side with the line numbers (JTextArea) and the text part (JTextPane) and I want to add scroll to them both. This is my program right now.

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(-7, -1, 550, 400);
contentPane = new JPanel();
contentPane.setBounds(-7, -1, 550, 400);
setContentPane(contentPane);
contentPane.setLayout(null);
        
JPanel Pane=new JPanel();
Pane.setLayout(null);
        
JTextPane txtp = new JTextPane();
txtp.setFont(new Font("Segoe UI", Font.PLAIN, 11));
txtp.setBounds(22, 0, 413, 250);
Pane.add(txtp);
        
JTextArea header = new JTextArea();
header.setBounds(0, 0, 20, 250);
Pane.add(header);
        
JScrollPane txt=new JScrollPane(Pane);
txt.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
txt.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
txt.setBounds(0, 0, 437, 250);
txt.getVerticalScrollBar().setOpaque(false);
txt.getHorizontalScrollBar().setOpaque(false);
contentPane.add(txt);

count = new JTextField();
count.setText("Word Count: 0,        Character Count: 0");
count.setFont(new Font("Segoe UI", Font.PLAIN, 9));
count.setBounds(0, 250, 439, 13);
contentPane.add(count);
count.setColumns(10);

Any help would be thanked for.

Upvotes: 0

Views: 222

Answers (1)

Gilbert Le Blanc
Gilbert Le Blanc

Reputation: 51445

I created a JFrame with a JTextPane and a JTextArea.

Basic Word Processor GUI

As you can see, there are line numbers, a text area, and a scroll bar.

Here are the steps I took to create this GUI.

  1. I start the application with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.

  2. I use Swing layout managers. This is crucial. There's no way you can build a complex Swing GUI without using layout managers. No way. Inconceivable.

  3. The JFrame has a default BorderLayout. I put the main JPanel in the CENTER. When you create the status JPanel, you can place that JPanel AFTER_LAST_LINE.

  4. I create a main JPanel, a line number JPanel, and a text area JPanel. Almost any GUI can be broken down into multiple JPanels. Once you get the hang of it, you see JPanels everywhere.

  5. I create each JPanel in its own method. This is a separation of concerns. This allows me to focus on one part of the GUI at a time and allows me to experiment with different Swing layout managers to see which layout manager works best.

Here's the complete runnable code. You may use this as a basis to start your application, adding a tiny, tiny bit of code at a time, and testing. Test, test, test. Testing is the only way you learn how to use Swing layout managers.

Did I mention how important Swing layout managers are to creating a GUI? Well, they are.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;

public class BasicWordProcessor implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new BasicWordProcessor());
    }
    
    private int rows;
    
    private Document document;
    
    private JTextArea textArea;
    
    private JTextPane textPane;
    
    public BasicWordProcessor() {
        this.rows = 15;
        this.document = new PlainDocument();
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Basic Word Processor");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createMainPanel(), BorderLayout.CENTER);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createMainPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        
        JPanel innerPanel = new JPanel(new BorderLayout());
        
        innerPanel.add(createLineNumberPanel(), 
                BorderLayout.BEFORE_LINE_BEGINS);
        innerPanel.add(createTextAreaPanel(), BorderLayout.CENTER);
        
        JScrollPane scrollPane = new JScrollPane(innerPanel);
        
        Dimension d = innerPanel.getPreferredSize();
        d.width += 30;
        panel.setPreferredSize(d);
        
        panel.add(scrollPane, BorderLayout.CENTER);
        
        return panel;
    }
    
    private JPanel createLineNumberPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        
        textPane = new JTextPane();
        textPane.setEditable(false);
        
        createRowText();
        
        panel.add(textPane);
        
        return panel;
    }

    private void createRowText() {
        int length = Integer.toString(rows).length();
        String formatter = "%0" + length + "d";
        StringBuilder builder = new StringBuilder();
        
        for (int i = 1; i <= rows; i++) {
            String s = String.format(formatter, i);
            builder.append(s).append(System.lineSeparator());
        }
        
        textPane.setText(builder.toString());
    }
    
    private JPanel createTextAreaPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        
        textArea = new JTextArea(document, "", rows, 60);
        document.addDocumentListener(new MyDocumentListener());
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        panel.add(textArea);
        
        return panel;
    }
    
    public class MyDocumentListener implements DocumentListener {

        @Override
        public void insertUpdate(DocumentEvent event) {
            rows = textArea.getLineCount();
            createRowText();
        }

        @Override
        public void removeUpdate(DocumentEvent event) {
            rows = textArea.getLineCount();
            createRowText();
        }

        @Override
        public void changedUpdate(DocumentEvent event) {
            
        }
        
    }

}

Upvotes: 1

Related Questions