How can I size a Java Swing JTextArea - java

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.

Related

Java swing JScrollPane not scrollable

This is the add(main) version
This is the add(scroll) version
Im trying to get a window full of lables and make it scrollable, this is my code for that purpose:
public class JobHistoryListScreen extends JFrame implements View
{
#Override
public void showScreen()
{
setSize(800, 800);
setLayout(new BorderLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel main = new JPanel();
main.setSize(500,500);
JScrollPane scroll = new JScrollPane(main,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setSize(500,500);
//Font
//Font david50 = new Font("David", Font.BOLD, 50);
for(int i=0; i<1000; i++)
{
JLabel empty = new JLabel("No jobs to display!");
empty.setBounds(0,i+250,400,100);
empty.setFont(david50);
main.add(empty);
}
add(main);
setVisible(true);
}
public static void main(String[] args) {
JobHistoryListScreen v = new JobHistoryListScreen();
v.showScreen();
}
}
For some reason the window gets filled with the labels but is not scrollable at all.
Learn about layout managers. Refer to Laying Out Components Within a Container. Default for JPanel is FlowLayout and because the JPanel is inside a JScrollPanel, the labels will not wrap. And since you set the horizontal scroll bar policy to NEVER, there is no horizontal scroll bar and hence you cannot scroll horizontally. Try using BoxLayout to display all the labels one under the other. Alternatively you could use a GridLayout with 0 (zero) rows and 1 (one) column. Refer to the tutorial for more details.
EDIT
Here is my modified version of your code. Explanatory notes appear after the code.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;
public class JobHistoryListScreen implements Runnable {
private JFrame frame;
#Override // java.lang.Runnable
public void run() {
showScreen();
}
public void showScreen() {
frame = new JFrame("Jobs");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel main = new JPanel(new GridLayout(0, 1));
JScrollPane scroll = new JScrollPane(main,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setPreferredSize(new Dimension(500, 500));
Font david50 = new Font("David", Font.BOLD, 50);
for(int i=0; i<1000; i++) {
JLabel empty = new JLabel("No jobs to display!");
empty.setFont(david50);
main.add(empty);
}
frame.add(scroll);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
JobHistoryListScreen v = new JobHistoryListScreen();
// Launch Event Dispatch Thread (EDT)
EventQueue.invokeLater(v);
}
}
I don't know what interface View is so I removed that part.
No need to extend class JFrame.
No need to explicitly call setSize() on JFrame. Better to call pack().
Default content pane for JFrame is JPanel and default layout manager for that JPanel is BorderLayout so no need to explicitly set.
No need to call setSize() on JPanel.
Call setPreferredSize() rather than setSize() on JScrollPane.
Add the JScrollPane to the JFrame and not the JPanel.
No need to call setBounds() because GridLayout handles this.
Explicitly launch EDT (Event Dispatch Thread) by calling invokeLater().
Here is a screen capture of the running app. Note the vertical scroll bar.

Adding Component to JScrollPane has weird behavior

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

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.

JLabel alignment in JPanel

I'm trying to align a JLabel to the right in a JPanel. I'm adding a JTabbedPane, a JPanel which contains my JLabel and JTextArea to a main JPanel.
I have searched SO and tried some methods like setAlignmentX, setHorizontalAlignment(SwingConstants.LEFT) and nested containers to no avail.
Here's my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class LabelProblem
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Label Problem");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel Main = new JPanel();
Main.setLayout(new BoxLayout(Main, BoxLayout.Y_AXIS));
JPanel ComponentPanel = new JPanel();
JLabel label = new JLabel("Sample Text");
label.setHorizontalAlignment(SwingConstants.LEFT);
label.setBorder(BorderFactory.createLineBorder(Color.BLACK));
label.setAlignmentX(Component.RIGHT_ALIGNMENT);
ComponentPanel.add(label);
JTabbedPane Tab = new JTabbedPane();
Tab.add("Document 1", new JPanel());
Main.add(Tab);
Main.add(ComponentPanel);
JTextArea Area = new JTextArea(10,10);
JScrollPane Scroll = new JScrollPane(Area);
frame.add(Main);
frame.add(Scroll, BorderLayout.SOUTH);
frame.setSize(450,450);
frame.setVisible(true);
}
}
How can I align my JLabel to the right?
Thanks!
So, the place of that label is determined by the layout of ComponentPanel. Since you didn't specify any layout it is using the default FlowLayout with a CENTER alignment. Assuming that you are ok with a FlowLayout it is a mere question of setting the alignment of the LEFT since this is possible with this layout.
Here's the code with the fix, however I suspect that as you put more elements to the ComponentPanel you will want to use another layout since FlowLayout is more adequate for menus and the like and not for displaying the main content.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
class LabelProblem
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
initGUI();
}
});
}
public static void initGUI()
{
JFrame frame = new JFrame("Label Problem");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel main = new JPanel();
main.setLayout(new BoxLayout(main, BoxLayout.Y_AXIS));
JPanel componentPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JLabel label = new JLabel("Sample Text");
label.setBorder(BorderFactory.createLineBorder(Color.BLACK));
componentPanel.add(label);
JTabbedPane Tab = new JTabbedPane();
Tab.add("Document 1", new JPanel());
main.add(Tab);
main.add(componentPanel);
JTextArea area = new JTextArea(10, 10);
JScrollPane scroll = new JScrollPane(area);
frame.add(main);
frame.add(scroll, BorderLayout.SOUTH);
frame.setSize(450, 450);
frame.setVisible(true);
}
}
Result:
Note: I also changed the variable names to follow the java style convention: variable names should start with lower case to differenciate them from clases names, starting in upper case.
One simple approach is to set the label's horizontalAlignment to JLabel.RIGHT in the constructor.
import java.awt.*;
import javax.swing.*;
class LabelProblem {
public static void main(String[] args) {
JFrame frame = new JFrame("Label Problem");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(0, 1));
JTabbedPane tab = new JTabbedPane();
tab.add("Document 1", new JPanel());
frame.add(tab);
JLabel label = new JLabel("Sample Text", JLabel.RIGHT);
frame.add(label);
JTextArea area = new JTextArea(10, 10);
JScrollPane scroll = new JScrollPane(area);
frame.add(scroll);
frame.pack();
frame.setSize(450, 450);
frame.setVisible(true);
}
}
I think it may be a matter of you not actually setting layouts where you imagine you're setting layouts.
You have a JPanel with a vertically oriented BoxLayout (Main) enclosing another JPanel with default layout (ComponentPanel), finally enclosing your label. The reason why your label can't be pushed to the right is because is already is pushed to the right within it's enclosing container. If you set a colored border around ComponentPanel, you'll see what I mean -- it only occupies the same amount of space as the JLabel, giving the JLabel nowhere to move.
You need to set a layout and constraints for your intermediate ComponentPanel, allowing it to horizontally fill its parent container so that the label has someplace to go.
You haven't really specified how your layout is supposed to look, but if you change the layout on Main to X_AXIS, your label will pop over to the left (as will its parent container). Without knowing what you're really trying to do, I can't say much more.
I would however, suggest you throw your BoxLayout away entirely and look into using GridBagLayout, which gives you a high level control over your UI. GridBagLayout isn't the most concise construct, but that's the price of control.

Java: Extra space in AbsoluteLayout

Is it possible to have some extra space around the edges of a JFrame that uses AbsoluteLayout? When I have a button as the downwardsmost component on the JFrame, it gets positioned right up against the bottom edge of the JFrame window, and it looks bad. I would like to know if there's a way to add a little extra space between components and the edge of the JFrame while using AbsoluteLayout.
Suggestions:
When you add a component to a JFrame, you're actually adding it to the JFrame's contentPane. To give the contentPane a "buffer" border, consider giving it an EmptyBorder(...) with the parameters being int constants for the amount of border desired around the component.
Avoid using "absolute" layouts for anything, and especially for placing components at easy to place locations for the layout managers, such as at the bottom of the GUI.
For example, note in the GUI created in the code below how the center and bottom JPanel's don't go out to the edge of the GUI because of the empty border:
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.*;
public class ButtonAtBottom {
private static void createAndShowGui() {
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton("Bottom Button"));
bottomPanel.setBorder(BorderFactory.createTitledBorder("Bottom Panel"));
JPanel centerPanel = new JPanel();
centerPanel.setBorder(BorderFactory.createTitledBorder("Center Panel"));
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(centerPanel, BorderLayout.CENTER);
mainPanel.add(bottomPanel, BorderLayout.PAGE_END);
// **** here I add the border to the mainPanel which I'll
// make into the contentPane
int eb = 25;
mainPanel.setBorder(BorderFactory.createEmptyBorder(eb, eb, eb, eb));
// don't set the preferredSize per Kleopatra, but am doing it
// here simply to make code shorter for this sscce
mainPanel.setPreferredSize(new Dimension(500, 400));
JFrame frame = new JFrame("ButtonAtBottom");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
You can use Box.createRigidArea(dimensions) to create an empty space that you can add below the button.
Set an empty border on your content panel where SIZE is the amount of padding you want.
JFrame frame = new JFrame();
JPanel panel = new JPanel(null);
panel.setBorder(BorderFactory.createEmptyBorder(SIZE,SIZE,SIZE,SIZE);
frame.setContentPane(panel);
//The rest
The arguments are for top, left, bottom and right padding so if you want different paddings on each edge, you can set it accordingly.

Categories

Resources