Search code examples
javaswinguser-interfacelook-and-feel

Customizing JTextField


I would like to know how to customize the ui of a jtextfield so I could create rounded rectangular border without the document going outside the border.

So far I think I have tried the most of what I can think of, I have created a new FieldView class and changed the shape in the paint method according to my customized border that draw rounded rects, the only way I sort of managed to get rid of the white textfield document/view was to set it opaque but I think there should be another way without setting the opaque value.

Have You any experience in customizing the laf of a jtextfield please write back, I have even read the Core Swing advanced book without luck and if you try searching with google please let me know the search phrase as I have tried with keywords like "styling","customizing","ui","plaf","laf" and what not.

I sincerely hope you can give me a nudge in the right direction and I hope nobody will make a flamewar out of this, I have truly used all my resources I can think of.

Sincerely regards.


Solution

  • I wanted to solve almost same problem yesterday and I got some inspiration by your thought and I finally find the solution.

    1. To make document inside the border of JTextField, you can use

    javax.swing.border.EmptyBorder.EmptyBorder(Insets borderInsets)

    2.To avoid the white space in four corners of JTextField, you can use

    g2d.setStroke(new BasicStroke(12));

    before drawing the round rectangle.The width of stroke is based on your demand and just make it wide enough to cover the space in corner.

    It's the code:

    import java.awt.BasicStroke;
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Insets;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    
    import javax.swing.BorderFactory;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    import javax.swing.border.AbstractBorder;
    import javax.swing.border.EmptyBorder;
    
    
    public class JTextFieldTest {
        JTextField textField;
        boolean activate = false;
    
        public void createUI(){
            JFrame frame = new JFrame("Test JTextField");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setResizable(true);
    
            MainPanel mainPanel = new MainPanel();
            mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
            frame.add(mainPanel,BorderLayout.CENTER);
    
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            JTextFieldTest jTextFieldTest = new JTextFieldTest();
            jTextFieldTest.createUI();
        }
    
        public void setActivate(boolean activate){
            this.activate = activate;
        }
    
        @SuppressWarnings("serial")
        class MainPanel extends JPanel{
            public MainPanel(){
    
                textField = new JTextField("Please input:");
                Font fieldFont = new Font("Arial", Font.PLAIN, 20);
                textField.setFont(fieldFont);
                textField.setBackground(Color.white);
                textField.setForeground(Color.gray.brighter());
                textField.setColumns(30);
                textField.setBorder(BorderFactory.createCompoundBorder(
                        new CustomeBorder(), 
                        new EmptyBorder(new Insets(15, 25, 15, 25))));
                textField.addActionListener(new FieldListener());
                textField.addMouseListener(new FieldMouseListener());
    
    
                add(textField,BorderLayout.CENTER);
                setBackground(Color.blue);
                setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
            }
        }
    
        @SuppressWarnings("serial")
        class CustomeBorder extends AbstractBorder{
            @Override
            public void paintBorder(Component c, Graphics g, int x, int y,
                    int width, int height) {
                // TODO Auto-generated method stubs
                super.paintBorder(c, g, x, y, width, height);
                Graphics2D g2d = (Graphics2D)g;
                g2d.setStroke(new BasicStroke(12));
                g2d.setColor(Color.blue);
                g2d.drawRoundRect(x, y, width - 1, height - 1, 25, 25);
            }   
        }
    
        class FieldListener implements ActionListener{
    
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                System.out.println(textField.getText());
            }
    
        }
    
        class FieldMouseListener implements MouseListener{
            @Override
            public void mouseClicked(MouseEvent e) {
                // TODO Auto-generated method stub
                if(activate == false){
                    textField.setText("");
                }
                activate = true;
                textField.setForeground(Color.black);
            }
    
            @Override
            public void mousePressed(MouseEvent e) {
                // TODO Auto-generated method stub
    
            }
    
            @Override
            public void mouseReleased(MouseEvent e) {
                // TODO Auto-generated method stub
    
            }
    
            @Override
            public void mouseEntered(MouseEvent e) {
                // TODO Auto-generated method stub
    
            }
    
            @Override
            public void mouseExited(MouseEvent e) {
                // TODO Auto-generated method stub
    
            }
        }
    }
    

    It's the effect:

    enter image description here

    For more details , you can browse How to make a round rectangle JTextField