Adding Component to JScrollPane has weird behavior - java

Executing this code produces very strange behavior.
When running, try resizing and typing to see what I mean.
import java.awt.BorderLayout;
import javax.swing.*;
public class FrameWithScrollPanel extends JFrame {
public static void main(String[] args) {
FrameWithScrollPanel myFrame = new FrameWithScrollPanel();
}
public FrameWithScrollPanel()
{
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
JTextArea textArea1 = new JTextArea(5, 30);
JTextArea textArea2 = new JTextArea(5, 30);
JPanel jPanel = new JPanel();
jPanel.setSize(400,400);
jPanel.setLayout(new BorderLayout());
jPanel.add(textArea1, BorderLayout.NORTH);
jPanel.add(textArea2, BorderLayout.SOUTH);
JScrollPane scrollPane = new JScrollPane();
scrollPane.add(jPanel);
getContentPane().add(scrollPane, BorderLayout.CENTER);
pack();
setVisible(true);
}
}
Now, replace these 2 lines :
JScrollPane scrollPane = new JScrollPane();
scrollPane.add(jPanel);
With this one line and the behavior is as expected.
JScrollPane scrollPane = new JScrollPane(jPanel);
Based on the documentation the JScrollPane constructor accepts a Component and so does the add().
Why the difference in behavior?

This is wrong:
scrollPane.add(jPanel);
Since you're replacing the JScrollPane's all important viewport with this add, preventing it from functioning. You should instead be adding this to the JScrollPane's viewport as per the JScrollPane tutorial and JScrollPane API:
scrollPane.setViewportView(jPanel);
or
scrollPane.getViewport().add(jPanel);
Moral of the story: when in doubt, read the docs.
Note that if you pass the jPanel into the JScrollPane's constructor,
JScrollPane scrollPane = new JScrollPane(jPanel);
it automatically places the component into the viewport for you.
Per the API:
public JScrollPane(Component view)
Creates a JScrollPane that displays the contents of the specified component, where both horizontal and vertical scrollbars appear whenever the component's contents are larger than the view.
Parameters:
view - the component to display in the scrollpane's viewport

Related

Java JTextField window size

Im trying to display to the user some text:
JTextField warningComponent = new JTextField(VERY_LONG_TEXT_NOENTERS);
warningComponent.setEditable(false);
but the window size is changed according to the text size. I want to set the window to be 30 X 40 all the time regardless of the warning text length.
And i want the warning text to be adjusted to the window size (maybe the user will have to scroll to see the end)
How do i do it?
Maybe i should use other swing component?
I tried most of the methods in JTextField class.
Thanks.
I add it to JPanel
Then the default layout manager should be a FlowLayout which will respect the preferred size of the text field.
To give a suggestion for the preferred size of the text field you need to do:
JTextField warningComponent = new JTextField(VERY_LONG_TEXT_NOENTERS, 20);
The second parameter will give a suggestion on how to size the text field to make approximately 20 characters visible at one time. You will then need to use the arrow keys to see the remaining characters.
And i want the warning text to be adjusted to the window size
If you want the textfield to resize according to the frame size and not the frame size following the dimension of the textfield, you may make use of specific layout to achieve that:
Using BorderLayout:
class MainPanel extends JPanel{
private JTextField txt;
public MainPanel(){
setLayout(new BorderLayout());
setPreferredSize(new Dimension(30, 40));
txt = new JTextField();
txt.setHorizontalAlignment(JTextField.HORIZONTAL);
add(txt);
}
}
Runner class to run to codes:
class TextFieldRunner{
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
JFrame frame = new JFrame("Text Runner");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
You can try JScrollPane in your application, JScrollPane is scroll-able horizontally and vertically as you wish. And add JTextArea to JScrollPane. JTextField is not scroll-able.
Here is a small example:
JScrollPane scrollPane = new JScrollPane();
JTextArea textArea = new JTextArea();
scrollPane.add(textArea);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
This is the values for the scroll policy:
VERTICAL_SCROLLBAR_AS_NEEDED
VERTICAL_SCROLLBAR_NEVER
VERTICAL_SCROLLBAR_ALWAYS
HORIZONTAL_SCROLLBAR_AS_NEEDED
HORIZONTAL_SCROLLBAR_NEVER
HORIZONTAL_SCROLLBAR_ALWAYS

JScrollPane doesn't work while inside a JPanel

JScrollPane works perfectly when I give it a JPanel and then add the JScrollPane directly on to a JFrame with frame.getContentPane.add(). However, it doesn't work when I add the JScrollPane to a JPanel and then add the JPanel to the JFrame. I need to use the second method because I'm going to add multiple things inside the JPanel and JFrame and I need to keep it organized. Here is my code.
import java.awt.*;
import javax.swing.*;
public class Main {
/**
* #param inpanel asks if the JScrollPane should
* be inside of a JPanel (so other things can also be added)
*/
public static void testScroll(boolean inpanel) {
JFrame f = new JFrame();
f.setLayout(new BorderLayout());
f.setResizable(true);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createLineBorder(Color.red));
//panel.setLayout(new BoxLayout(panel, 1));
panel.setLayout(new GridLayout(0,1));
for (int i = 0; i < 100; i++) {
JLabel l = new JLabel("hey"+i,SwingConstants.CENTER);
l.setBorder(BorderFactory.createLineBorder(Color.green));
l.setPreferredSize(new Dimension(200,200));
panel.add(l);
}
JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.setBorder(BorderFactory.createLineBorder(Color.blue));
//**********THIS DOES NOT WORK HOW I WANT IT TO************
if(inpanel){
JPanel holder = new JPanel();
holder.add(scrollPane);
f.getContentPane().add(holder);
}
//************THIS DOES WORK HOW I WANT IT TO****************
else{
f.getContentPane().add(scrollPane);
}
f.pack();
f.setSize(500, 500);
f.setExtendedState(JFrame.MAXIMIZED_BOTH);
f.setVisible(true);
JScrollBar bar = scrollPane.getVerticalScrollBar();
bar.setValue(bar.getMaximum());
bar.setUnitIncrement(50);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
testScroll(false); //OR TRUE
}
};
SwingUtilities.invokeLater(r);
}
}
In the main method, if I pass false, it works like I mentioned before, but when I pass true it shows up without a scroll bar.
Picture when passing false
Picture when passing true
I need a way to add the JScrollPane to a JPanel and still have it work.
Thanks in advance!
Your problem is the holder JPanel's layout. By default it is FlowLayout which will not re-size its child components when need be. Make it a BorderLayout instead, and your scrollpane will resize when needed. If you need something more complex, check out the layout manager tutorials.

How can I size a Java Swing JTextArea

I am trying to put a text area onto a dialog box using Java Swing. I have a problem of setting the size of this JTextArea. The width of the text area is always equal to the whole width of the window and stretches with the window if I resize it.
private void arrangeComponents() {
JTextArea textArea = new JTextArea();
JPanel outerPanel = new JPanel();
outerPanel.setLayout(new BoxLayout(outerPanel, BoxLayout.PAGE_AXIS));
JScrollPane scrollPane = new JScrollPane(textArea);
outerPanel.add(scrollPane, BorderLayout.CENTER);
Container contentPane = getContentPane();
contentPane.add(outerPanel, BorderLayout.CENTER);
}
I want the JTextArea to be horizontally aligned to the centre of the window and does not change its size.
What did I do wrong?
Use the JTextArea(int rows, int columns) constructor that specifies rows and columns, as shown here, and don't neglect to pack() the enclosing Window.
outerPanel.add(scrollPane, BorderLayout.CENTER);
A BoxLayout doesn't take constraints, so the BorderLayout.CENTER is unnecessary.
The problem is that a BoxLayout respects the maximum size of the component which for a scrollpane is set very large.
Instead of using a BoxLayout, just use a panel with a FlowLayout.
Run the example below to see what you are currently doing. Then comment out the setLayout(...) statement and run again. By default the panel uses a FlowLayout so you will get what you want.
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
public class SSCCE extends JPanel
{
public SSCCE()
{
setLayout( new BoxLayout(this, BoxLayout.PAGE_AXIS));
JTextArea textArea = new JTextArea(5, 30);
JScrollPane scrollPane = new JScrollPane(textArea);
//scrollPane.setMaximumSize( scrollPane.getPreferredSize() );
add(scrollPane);
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new SSCCE() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Or if you really want to keep the BoxLayout then leave keep the setLayout(...) statement and then set the maximum size equal to the preffered size. Many people will say you should never invoke a "setXXX()" method directly and instead you should override the setMaximumSize() method of the scrollpane to just return the preferred size.
Note, when testing these two solutions make sure you make the window smaller than the scrollpane to see how each layout works differently.
i found this from a simple coding site. This code sample may be useful for you.
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class JTextAreaTest {
public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("JTextArea Test");
frame.setLayout(new FlowLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String text = "A JTextArea object represents a multiline area for displaying text. "
+ "You can change the number of lines that can be displayed at a time, "
+ "as well as the number of columns. You can wrap lines and words too. "
+ "You can also put your JTextArea in a JScrollPane to make it scrollable.";
JTextArea textAreal = new JTextArea(text, 5, 10);
textAreal.setPreferredSize(new Dimension(100, 100));
JTextArea textArea2 = new JTextArea(text, 5, 10);
textArea2.setPreferredSize(new Dimension(100, 100));
JScrollPane scrollPane = new JScrollPane(textArea2,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
textAreal.setLineWrap(true);
textArea2.setLineWrap(true);
frame.add(textAreal);
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
}
}
Just call that method for ur text area: setLineWrap(true);
If JTextArea is initializated
JTextArea text = new JTextArea(int rows, int columns)
you just call the method text.setLineWrap(true)
then text'size is fixed.

How to get JScrollPanes within a JScrollPane to follow parent's resizing

So I have a bunch of JTables. Each JTable is inside a JScrollPane. I'm then adding each of these JScrollPanes to a JPanel. I'm then adding this JPanel to a JScrollPane then that to another JPanel with BorderLayout. The larger JScrollPane properly resizes with its parent, but each of the smaller JScrollPanes have constant height, which is larger than the window when it is small. How can I get each of the children JScrollPanes to resize with the height of the window/their parent?
I've tried adding more intermediary JPanels with FlowLayout, BorderLayout, and nothing seems to work.
Here's some relevant code:
public class MyPanel extends JPanel
{
public MyPanel()
{
super(new BorderLayout());
JPanel panel = new JPanel();
for (int i = 0; i < 5; i++)
{
// View extends JTable
panel.add(new JScrollPane(new View(new Model())));
}
add(new JScrollPane(panel));
}
}
I'm really just trying to get a bunch of tables with scrollbars horizontally next to each other inside a larger panel with a horizontal scrollbar. And I want all that stuff to resize appropriately when the window size changes.
more code:
final MyPanel panel = new MyPanel();
final JTabbedPane tabView = new JTabbedPane();
tabView.add(...);
tabView.add("foo", panel);
final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, ..., tabView);
this.add(splitPane); // this extends JFrame
You can use a BoxLayout. If you want the opposite: some table being fixed, you can wrap it with constraint Box.createRigidArea(new Dimension(100, 100)) .

JScrollBar Vertical/Horizontal setting problem- Java Swing

I am just trying to add a vertical scroll bar to my TextField and TextArea.
I am using a ScrollPane and it should create avertical/horizontal scroll bar by default.
Problem:
I need a vertical scroll bar to see the data which is not visible.
In the start a vertical scrollbar appears but when the data increases the vertical scrollbar changes to a horizontal scroll bar.
Also the TextField disappears and only a horizontal scrollbar appears in its place.
I guess it is because how I have set the bounds but I tried changing the bounds and it ends up completely doing away with the TextField.
My code snippet:
public JTextField inputField = new JTextField();
public JTextArea talkArea = new JTextArea();
public JScrollPane inputFieldScroll = new JScrollPane(inputField);
public JScrollPane talkAreaScroll = new JScrollPane(talkArea);
talkArea.setEditable(false);
talkArea.setBackground(Color.white);
talkAreaScroll.setBounds(new Rectangle(TALK_LEFT, TALK_TOP, TALK_WIDTH, TALK_HEIGHT));
this.getContentPane().add(talkAreaScroll, null);
//set input area
inputField.setBackground(Color.white);
inputField.setBounds(new Rectangle(INPUT_LEFT, INPUT_TOP, INPUT_WIDTH, INPUT_HEIGHT));
inputFieldScroll.setVerticalScrollBar(new JScrollBar());
inputFieldScroll.setBounds(new Rectangle(INPUT_LEFT, INPUT_TOP, INPUT_WIDTH, INPUT_HEIGHT));
Question:
Is there some parameter I need to set so that it remains a vertical scroll bar?
Why does the input scroll bar occupy the whole inputfield when the data becomes a huge line? It appears as a proper vertical scrollbar in the start.
Any advice appreciated.
Thanks
Below is a small compilable code snippet I mentioned above. I agree with camickr that you should not be using absolute positioning but rather use the layout managers. If you absolutely need to have a horizontal scrollbar for the JTextField, then one way to get it to work is to have it show up always, using the JScrollPane constructor that allows for this. i.e,
JScrollPane inputPane = new JScrollPane(inputField, JScrollPane.VERTICAL_SCROLLBAR_NEVER,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
For e.g.,
import java.awt.*;
import javax.swing.*;
public class FuSwing1b extends JPanel {
private static final int TA_ROWS = 25;
private static final int TA_COLS = 60;
private JTextField inputField = new JTextField();
private JTextArea talkArea = new JTextArea(TA_ROWS, TA_COLS);
public FuSwing1b() {
talkArea.setEditable(false);
talkArea.setFocusable(false);
talkArea.setBackground(Color.white);
//talkArea.setPreferredSize(new Dimension(TALK_WIDTH, TALK_HEIGHT));
JScrollPane talkPane = new JScrollPane(talkArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
JScrollPane inputPane = new JScrollPane(inputField, JScrollPane.VERTICAL_SCROLLBAR_NEVER,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
int gap = 10;
setLayout(new BorderLayout(gap, gap));
add(talkPane, BorderLayout.CENTER);
add(inputPane, BorderLayout.SOUTH);
setBorder(BorderFactory.createEmptyBorder(gap , gap, gap, gap));
}
private static void createAndShowUI() {
JFrame frame = new JFrame("FuSwing1b");
frame.getContentPane().add(new FuSwing1b());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
Don't play with the bounds. Use a layout manager and you won't have to worry about this.
When you create the text field use something like:
JTextField textField = new JTextField(10);
This will create a text field that will hold a minimum of 10 characters. If the number of characters exceeds the display width of the text field the use can see the remaining characters by using the right/left arrow keys. That is the normal UI used by all applications I have ever seen. Don't try to create your own UI by using a horizontal scrollbar. Users are not accustomed to that.
for the text area you can create it using:
JTextArea textArea = new JTextArea(5, 30);
JScrollPane scrollPane = new JScrollPane( textArea );
to create a text area with 5 rows and approximately 30 character per row.
Now add the text field and the scrollpane to your frame "using layout managers" and then pack the frame. The layout managers will determine the best size for the compoents. Scrollbars will automatically appear on the text area as you add text to it and the text exceeds 5 lines.

Categories

Resources