JTextArea vertical scrollbar showing up when not needed - java

I need a vertical scrollbar in my JTextArea to only appear when it's needed, and for that I know I need to use Vertical Scrollbar As Needed. But the scrollbar keeps showing up, like this:
enter image description here
even when it's clearly not needed. What am I doing wrong?
// make top panel where output from the menu selections will appear
topP = new JPanel(new BorderLayout());
topP.setSize(new Dimension(500,150));
// make default text message to be displayed in top panel
output = new JTextArea("Output printed here...", 20, 20);
// styles the text in the textarea
output.setForeground(Color.BLUE);
output.setFont(new Font("Times New Roman", Font.BOLD, 20));
topP.add(output, BorderLayout.NORTH); // add default text to the top panel
right.add(output);
// here's the scrollbar guys
top = new JScrollPane(output); // applies to the textarea
top.setPreferredSize(new Dimension(500,150));
top.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
top.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
topP.add(top, BorderLayout.NORTH);

Take a look at the documentation for JTextArea. If you scroll down to the constructor summary section, you'll see the following:
JTextArea​(String text, int rows, int columns)
Constructs a new TextArea with the specified text and number of rows and columns.
This is the same as the constructor you're using:
output = new JTextArea("Output printed here...", 20, 20);
By specifying rows and columns, you're effectively telling the JTextArea that it has to be a certain size, and the scrollpane is just responding to your specifications by showing scroll controls. Those scroll controls are displayed based on the number of rows and columns you asked for, as opposed to the amount of visible text within the text area.
If you construct a JTextArea without specifying rows and columns, there won't be any scrollbars. Since you're setting the size of the text area, specifying rows and columns is redundant anyhow. Just don't do it.
Note: You should avoid setting the absolute size of Swing components. Set a preferred size only, and when you call pack(), Swing will try to accommodate your specification as much as possible. When you specify absolute sizes, your UI can look really bad on different platforms or when a user resizes the frame.

Related

Text Field setBounds function is not working on a particular JFrame

I am trying to create a JPanel with 3 text fields. Everything else including buttons is falling into place except for textArea3. The final panel is something like this. As you can see in picture, textArea3 uses entire JFrame instead of following setBounds method.
//Text Area 1
JTextArea textArea = new JTextArea();
JScrollPane jScrollPane1 = new JScrollPane(textArea);
jScrollPane1.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
jScrollPane1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
textArea.setFont(new Font("Consolas", Font.LAYOUT_LEFT_TO_RIGHT, 20));
JTextArea textArea2 = new JTextArea();
JScrollPane jScrollPane2 = new JScrollPane(textArea2);
jScrollPane2.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
jScrollPane2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
textArea2.setWrapStyleWord(true);
textArea2.setLineWrap(true);
textArea2.setFont(new Font("Consolas", Font.LAYOUT_LEFT_TO_RIGHT, 20));
//Text Area 3
JTextField textArea3 = new JTextField();
textArea3.setFont(new Font("Consolas", Font.LAYOUT_LEFT_TO_RIGHT, 20));
jScrollPane1.setBounds(30,30,300,300);
jScrollPane2.setBounds(30,400,200,200);
//textArea3 is not working
textArea3.setBounds(600,800,100,50);
button2.setBounds(350,30,80,30);
button1.setBounds(350,400,80,30);
frame.add(button1);
frame.add(button2);
frame.add(jScrollPane2);
frame.add(jScrollPane1);
frame.add(textArea3);
frame.setVisible(true);
EDIT: So this was a bug within the JDK probably. I made another class called class frame and set methods to produce text area etc.
As you can see in picture, textArea3 uses entire JFrame instead of following setBounds method.
No I can't see. I see 5 components. I don't see any component that uses the entire frame.
If in fact you do see the text area take up the whole frame that is because:
the default layout manager for a JFrame is the BorderLayout
when you add components to a BorderLayout and don't specify a constraint, the CENTER is assumed.
however only a single component can be displayed in the CENTER so the layout manager will only give a size/location to the last component added, which happens to be textArea3.
The other components only happen to appear because you manually set the bounds of each component.
You should NOT be attempting to set the bounds of a component. It is the job of the layout manager to set the size and location of each component.
So the solution is to get rid of all the setBounds() statement and use layout managers.
Read the section from the Swing tutorial on Layout Managers for more information. It appears you are tying to use a grid so you can probably use a GridBagLayout.
Also when you create a JTextArea you should use something like:
JTextArea textArea = new JTextArea(15, 20);
This will allow the text area to calculate its size so that 15 rows will display with about 20 characters in each row. The size will be calculated based on the Font used.

Enable ScrollPane when components exceed inside a text area

Before anything else there might be some people who already asked this question. However, i am certain that I couldn't google it. Anyway, I have a scrollPane which has a viewPortView of textArea. My question is I would like to show my scrollpane when i insert numerous components inside my textArea. How am i supposed to do this? I have no idea and I'm not that expert with Javax Swing.
Code goes like this:
textArea = new JTextArea();
scrollPane = new JScrollPane();
textArea.setBounds(0,50,520,550);
textArea.setBackground(Color.DARK_GRAY);
scrollPane.setBounds(textArea.getBounds());
scrollPane.setViewportView(textArea);
thanks for the help!
My question is I would like to show my scrollpane when i insert numerous components inside my textArea.
A text area displays text, not components. The scrollbars will appear automatically when you actually add text to the text area.
textArea.setBounds(0,50,520,550);
Don't use setBounds. Swing was designed to be used with layout managers. In particular a JScrollPane will only work properly when you use layout managers.
//textArea = new JTextArea();
textArea = new JTextArea(5, 20);
When you create a JtextArea use code like the above. This will allow the text area to determine its own preferred size. Then scrollbars will appear once you add more than 5 rows of text.
Read the section from the Swing tutorial on How to Use Text Areas for more information and working examples. Keep a link to the tutorial handy for all Swing basics.
Just for information,
If you have multiple lines in your text area, the scroll bar is by default scrolled to the end of the text area. To keep the lines in the text area wrapped and scroll bar to the top of the text area, following code would help
textArea .setWrapStyleWord(true);
textArea .setLineWrap(true);
DefaultCaret caret = (DefaultCaret) textArea .getCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);

How do I center a label that is already affected by BoxLayout?

So I have got round to creating a panel that has two labels and a button inside and these are alligned on the Y_axis via a box layout.
I am now trying to get it so that the text is alligned to the centre of the panel as well as on the Y axis for neatness.
Here is the code I have right now:
JPanel statPanel = new JPanel();
statPanel.setBorder(BorderFactory.createTitledBorder("Text Statistics"));
statPanel.add((averageLength = new JLabel("The average length of the words: ")));
statPanel.add((totalWords = new JLabel("The total number of words: ")));
//Create button inside statPanel
statPanel.add((stats = new JButton("Update Text Statistics")));
stats.addActionListener(new ButtonListener());
statPanel.setOpaque(false);
statPanel.setLayout(new BoxLayout(statPanel, BoxLayout.Y_AXIS));
As you can see I have already used BoxLayout in order to get the vertical alignment and I have tried the following code which didnt seem to affect my situation at all (and did seem very long winded):
averageLength.setHorizontalAlignment(SwingConstants.CENTER);
averageLength.setVerticalAlignment(SwingConstants.CENTER);
totalWords.setHorizontalAlignment(SwingConstants.CENTER);
totalWords.setVerticalAlignment(SwingConstants.CENTER);
stats.setHorizontalAlignment(SwingConstants.CENTER);
stats.setVerticalAlignment(SwingConstants.CENTER);
If you could advise me that would be much appreciated!
Thanks
You don't need to set the horizontal or vertical alignment. Those properties are used with a layout manager (ie BorderLayout) that changes the size of the component to be something greater than the preferred size of the component. Then the component aligns the text based on its painting rules.
Instead, you need to set the x alignment. In this case the component size is still the preferred size. However, the layout manager aligns the component to the space available in the container. So to center the component in the width of the container you would use:
averageLength.setAlignmentX(0.5f);
totalWords.setAlignmentX(0.5f);
stats.setAlignmentX(0.5f);
The BoxLayout doesn't change the size of the component so it respects this property.

Resizing JTextArea while using lineWrap

I want to create three JTextArea in my swing application.
Each JTextArea has a different size.
The first JTextArea should have 8 columns
The second one should only have 1 column
And the last one should have 50 columns.
My initial problem is that:
Whenever I type something, the JTextArea will keep on re-sizing its width.
This has been fixed by JScrollPane, setLineWrap(true), and setWrapStyleWord(true).
So here's my problem.
Whenever I add setLineWrap() to a JTextArea, the JTextArea will be resized.
My first and second JTextArea have been resized to 12 columns.
I searched and found some solution but they use MigLayout.
Is there any way to add word and line wrap in JTextArea without resizing it (and ofcourse, without the use of MigLayout)?
What's the easiest way to set the columns of JTextArea with word and line wrap?
What's the easiest way to set the columns of JTextArea with word and line wrap?
You create the JTextArea with code like:
JTextArea textArea = new JTextArea(5, 50);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane scrollPane = new JScrollPane( textArea );
JPanel panel = new JPanel();
panel.add(scrollPane);
frame.add(panel, BorderLayout.PAGE_START);
By default a JPanel uses a FlowLayout which respects the size of any component added to it. The BorderLayout.PAGE_START will repect the height of any component added to it.
Scrollbars will appear as required what text is added to the text area. So the key is to use a layout manager (or combination of layout managers) that meet your requirement.

Can you set a permanent size for a JPanel inside of a JFrame?

My current problem is that I have a JFrame with a 2x2 GridLayout. And inside one of the squares, I have a JPanel that is to display a grid. I am having a field day with the java swing library... take a look
Image
Java is automatically expanding each JLabel to fit the screen. I want it to just be those blue squares (water) and the black border and not that gray space. Is there a way I can just set the size of that JPanel permanently so that I don't have to go through changing the size of the JFrame a million times before I get the exact dimension so that the gray space disappears?
I also would like to set the size of those buttons so they are not so huge (BorderLayout is being used for the buttons and TextField)
GridBagLayout is what you really want to use. The GridLayout will force the same size for each component in the layout no matter what size constraints you put on them. GridBagLayout is a lot more powerful and a lot more complicated. Study up on the API page for it. Using GridBagLayout, the components won't fill the whole grid space if you don't want them to and can even stay the size that you ask it to be. To keep a component's size from changing, I would set all three available size constraints:
water.setPreferredSize(new Dimension(20, 20));
water.setMinimumSize(new Dimension(20, 20));
water.setMaximumSize(new Dimension(20, 20));
For your buttons, I would definitely use an inner panel as Bryan mentions. You could use either a GridLayout like he suggests or a FlowLayout if you don't want all the buttons to be the same size. Add all your buttons to that inner panel instead of the main one.
If you want the two checkerboards to stay the same size, then you'll need to have them each contained in their own JPanel. Set each of those parent JPanel's to have a layout type of GridBagLayout. Set the preferedSize for each checkerboard component and then add them to their respective containers. GridBagLayout should by default lay each board out in the center of the parent JPanel. So as the window is resized, the JPanel parent area will get larger or smaller, but the checkerboard components inside will remain the same size.
Alternatively, you could have your blue squares scale to the right size as the window is resized by having each checkboard square be a JPanel with a BorderLayout layout manager and adding the JLabel (with a blue background color) to its BorderLayout.CENTER location.
As for your buttons, try something like this:
JPanel theButtonPanel = new JPanel(new BorderLayout());
JButton button1 = new JButton("Fire");
JButton button2 = new JButton("Pass");
JButton button3 = new JButton("Forfiet");
JPanel innerButtonContainer = new JPanel(new Grid(1, 3, 8, 8));
innerButtonContainer.add(button1);
innerButtonContainer.add(button2);
innerButtonContainer.add(button3);
theButtonPanel.add(innterButtonContainer);
Lastly, consider using a design tool for your Swing user interface. Netbeans has an excellent UI designer built into it. Download Netbeans here.
If you can setResizeable( false ) on the top level frame you can then set your layout manager to null and hard code each location and size via setBounds. This is how I would do it (contingent on resizing of course).
I have had success solving problems like these using TableLayout which is a third party layout manager. You will need to download it and read the tutorial but the key would be to set the justification to CENTER when adding the JButtons to their positions in the layout.

Categories