Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JTextArea border in java swing

I am new to java and creating UI widgets using java and created the following class for the same. But in order to add border to textarea I know that I have to use borderfactory class. But as I have separate class for JFrame and JTextArea I could not do it. Any help?

class

import javax.swing.*;
import java.awt.*;
import javax.swing.BorderFactory;

    public class UIFactory {

        //Border border = BorderFactory.createLineBorder(Color.BLACK);
        public JButton newButton(int posx, int posy, int buttonWidth, int buttonHeight) {
            JButton b = new JButton("Test");
            b.setBounds(posx, posy, buttonWidth, buttonHeight);
            return b;
        }

        public JFrame newFrame(int width, int height) {
            JFrame f = new JFrame();
            f.setSize(width, height);
            f.setLayout(null);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            return f;
        }

        public JTextArea newTextArea(int xpos, int ypos, int twidth, int theight) {
            JTextArea t = new JTextArea(300,300);
            JScrollPane sp = new JScrollPane(t);            
            t.setBounds(xpos, ypos, twidth, theight);
            t.setBackground(Color.orange);  
            t.setForeground(Color.black); 
         //   t.setBorder(BorderFactory.createCompoundBorder(border,BorderFactory.createEmptyBorder(10, 10, 10, 10)));            
            return t;
        }

}

and my main program

import javax.swing.*;
import java.awt.*;
public class MyUI {
public static void main(String[] args) {
        UIFactory ui = new UIFactory();    
        JFrame mainf = ui.newFrame(800, 800);        
        mainf.setLocation(400, 400);

        JButton b2;
        JButton b3;


        mainf.add(b2 = ui.newButton(50, 50, 100, 50));
        mainf.add(b3 = ui.newButton(50, 100, 100, 50));   

        JTextArea area;
        mainf.add(area = ui.newTextArea(170,50,1600,300));
        mainf.setVisible(true);
        mainf.add(area = ui.newTextArea(170,400,1600,300));
        mainf.setVisible(true);
    }
}
like image 318
Rajesh Avatar asked Dec 06 '22 15:12

Rajesh


2 Answers

try below in newTextArea

Border border = BorderFactory.createLineBorder(Color.BLACK);
    t.setBorder(BorderFactory.createCompoundBorder(border,
            BorderFactory.createEmptyBorder(10, 10, 10, 10)));
like image 77
SAQ Avatar answered Dec 08 '22 04:12

SAQ


There are a couple of ways you might be able to achieve this, you could just apply the border AFTER the fact to either the frame or the JTextArea or you could supply the Border value to either methods based on your needs

My preference would be to consider using a builder pattern, which would allow you to supply the properties your interested in and make the final result.

Because many of the properties are shared between components, I'd be tempted to start with an abstract implementation

public abstract class ComponentBuilder<B extends ComponentBuilder<B, T>, T extends JComponent> {

    public static final String BORDER = "border";
    public static final String FOREGROUND = "foreground";
    public static final String BACKGROUND = "background";

    private Map<String, Object> properties = new HashMap<>();

    protected abstract B self();

    protected void put(String key, Object value) {
        properties.put(key, value);
    }

    public B withBorder(Border border) {
        put(BORDER, border);
        return self();
    }

    public B withForeground(Color color) {
        put(FOREGROUND, color);
        return self();
    }

    public B withBackground(Color color) {
        put(BACKGROUND, color);
        return self();
    }

    public abstract T build();

    public <O> O get(String key, Class<O> type, O defaultValue) {
        Object value = properties.get(key);
        if (value == null) {
            return defaultValue;
        } else if (value.getClass().isAssignableFrom(type)) {
            return (O)value;
        }
        return defaultValue;
    }

    protected Border getBorder() {
        return get(BORDER, Border.class, null);
    }

    protected int getInt(String key, int defaultValue) {
        return get(key, int.class, defaultValue);
    }

    protected Color getColor(String key, Color defaultValue) {
        return get(key, Color.class, defaultValue);
    }

    protected Color getForeground() {
        return getColor(FOREGROUND, null);
    }

    protected Color getBackground() {
        return getColor(BACKGROUND, null);
    }
}

Okay, don't panic, that's some awesome generic trickery, but trust me, it makes the whole API very flexible

Now, you could include a lot more properties, like font for example, but let's stick with a basic example.

Next, we need a text area builder to build a textarea the way we want it

public class TextAreaBuilder extends ComponentBuilder<TextAreaBuilder, JTextArea> {

    public static final String ROWS = "rows";
    public static final String COLUMNS = "columns";

    @Override
    protected TextAreaBuilder self() {
        return this;
    }

    public TextAreaBuilder withRows(int rows) {
        put(ROWS, rows);
        return self();
    }

    public TextAreaBuilder withColumns(int cols) {
        put(COLUMNS, cols);
        return self();
    }

    protected int getRows(int defaultValue) {
        return getInt(ROWS, defaultValue);
    }

    protected int getColumns(int defaultValue) {
        return getInt(COLUMNS, defaultValue);
    }

    @Override
    public JTextArea build() {
        JTextArea ta = new JTextArea();
        ta.setColumns(getColumns(0));
        ta.setRows(getRows(0));
        ta.setBorder(getBorder());
        ta.setForeground(getForeground());
        ta.setBackground(getBackground());
        return ta;
    }

}

Then we can simply make a new JTextArea with the properties we want to use...

JTextArea ta = new TextAreaBuilder().
        withColumns(40).
        withRows(20).
        withBackground(Color.ORANGE).
        withForeground(Color.BLACK).
        withBorder(BorderFactory.createLineBorder(Color.RED)).
        build();

Done!

Now, if all that seems "to hard", you could simply change your current method to require an instance of Border, for example

public JTextArea newTextArea(int rows, int cols, Border border) {
    JTextArea ta = new JTextArea(rows, cols);
    ta.setBorder(border);
    return ta;
}

Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify

Have a look at Why is it frowned upon to use a null layout in SWING? and Laying Out Components Within a Container for more details

like image 35
MadProgrammer Avatar answered Dec 08 '22 03:12

MadProgrammer