I'm using a JEditorPane
inside a JPanel
which I've called my contentPane
in the example below. The content pane is inside a JScrollPane
. I would like the editor pane to fill as little space as possible (to just contain it's text) and the rest of the space available in the content pane be left empty to the bottom, and on either side. If the text gets too large, the editor pane will grow, and eventually the scroll pane will create scroll bars to browse through all of the content. However, instead of the editor pane only taking up its preferred size (which is the size of the text it contains) it fills up the entire content pane which fills the entire view port of the scroll pane. Here's some example code to demonstrate my problem:
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.BoxLayout;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
@SuppressWarnings("serial")
public class ScrollPaneExample extends JFrame {
public static void main(String[] args) {
new ScrollPaneExample();
}
public ScrollPaneExample() {
super("ScrollPaneExample");
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JEditorPane editorPane = new JEditorPane("text/plain", "");
editorPane.setBackground(Color.YELLOW);
for (int i = 0; i < 5; i++)
editorPane.setText(editorPane.getText() + "Hello World\n");
JPanel contentPane = new JPanel();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
contentPane.setBackground(Color.BLUE);
contentPane.add(editorPane);
JScrollPane scrollPane = new JScrollPane(contentPane);
add(scrollPane, BorderLayout.CENTER);
setVisible(true);
}
}
When run, this is what the window looks like:
By the yellow background, we can see that the editor pane is taking up all the space. Here is a (Photoshopped) example of what I want the layout to look like:
The blue background represents the content pane, and the yellow represents the editor pane.
Edit: In my working program, there is more than just an editor pane in the contentPane
. This is why I am using a BoxLayout
instead of a FlowLayout
for the contentPane
; because the vertical page-flow layout is desired.
Just use a FlowLayout
for the content pane. BorderLayout
won't respect preferred size and will stretch the component to fit. See more about layout managers at Laying out Components Withing a Container
If you want to set an initial size for the editor pane, just like with any other component that is Scollable
, you can override getPreferredScrollableViewportSize()
to set the size for the scroll pane view (when the component is added)
Also you should be adding the editor to the scroll pane, not the panel. Doing the latter, the editor will not be scrollable in the scroll pane.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
@SuppressWarnings("serial")
public class ScrollPaneDemo extends JFrame {
public static void main(String[] args) {
new ScrollPaneDemo();
}
public ScrollPaneDemo() {
super("ScrollPaneExample");
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
JEditorPane editorPane = new JEditorPane("text/plain", "") {
@Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
};
editorPane.setBackground(Color.YELLOW);
for (int i = 0; i < 50; i++) {
editorPane.setText(editorPane.getText()
+ "Hello World Hello World\n");
}
JScrollPane scrollPane = new JScrollPane(editorPane);
add(scrollPane);
setVisible(true);
}
}
UPDATE
In my working program, there is more than just an editor pane in the contentPane. This is why I am using a BoxLayout instead of a FlowLayout for the contentPane; because the vertical page-flow layout is desired.
The BoxLayout is the problem. You need to set a maximum size for the editor pane. Or just get rid of the BoxLayout all together. FlowLayout or GridBagLayout will respect the preferred size
UPDATE 2
Here is an example using GridBagLayout that may more suitable for your "expanding" editor.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Timer;
@SuppressWarnings("serial")
public class ScrollPaneExample extends JFrame {
public static void main(String[] args) {
new ScrollPaneExample();
}
public ScrollPaneExample() {
super("ScrollPaneExample");
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
//getContentPane().setBackground(Color.BLUE);
final JEditorPane editorPane = new JEditorPane("text/plain", "") {
};
editorPane.setBackground(Color.YELLOW);
for (int i = 0; i < 5; i++)
editorPane.setText(editorPane.getText() + "Hello World\n");
JPanel contentPane = new JPanel();
contentPane.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weighty = 1;
contentPane.setBackground(Color.BLUE);
contentPane.add(editorPane, gbc);
gbc.gridy++;
contentPane.add(new JButton("Button"), gbc);
gbc.gridy++;
contentPane.add(new JButton("Button"), gbc);
JPanel panel = new JPanel();
panel.add(contentPane);
JScrollPane scrollPane = new JScrollPane(panel);
add(scrollPane);
setVisible(true);
Timer timer = new Timer(1000, new ActionListener(){
public void actionPerformed(ActionEvent e) {
editorPane.setText(editorPane.getText() + "Hello World\n");
setVisible(true);
}
});
timer.start();
}
}