简体   繁体   中英

My Custom JTextField covered by super.paintComponent(g) method

I have create a custom JTextField by extending JtextField Class and overiding paintComponent(Graphics g) method. When I compiled and drag into a JFrame, it work normally. But when I run it, the result is different.

My custom JTextField covered by white square that I suspect that's result of super.paintComponent(g); method.

This is my code on paintComponent() method;

@Override
protected void paintComponent(Graphics g) {
    Graphics2D gd = (Graphics2D) g.create();
    gd.setPaint(new GradientPaint(0, 0, Color.BLUE, getWidth(), 0, Color.BLACK));
    gd.fillRoundRect(0, 0, getWidth(), getHeight(), getWidth() / 2, getHeight() / 2);
    gd.dispose();
    super.paintComponent(g);
}

Move super.paintComponent(g) to the top of your paintComponent . This way you make sure that your custom painting is done after the superclass paintComponent has executed.

//Here is a example for Custom JTextfeild

1. This supports highlighting Jtextfeild with Icons.

2. This custom Jtextfeild with different fonts.

  Header Section
---------------------
import java.awt.*;  
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;  
import javax.swing.*;  
import javax.swing.border.Border;



//Main class section 

    public class CustomJTextFeild extends JTextField implements FocusListener,KeyListener{
          private Color color;
          private ImageIcon normal_icon;
          private ImageIcon hover_icon;
          private ImageIcon icon_Label;
          private boolean start_action=false;
          private String Matchtext;
          private int x0 ;

 //Constructor with input parameters
 //icon ->  normal icon
 //icon 1-> hover icon
 //text ->  initial text 

     public  CustomJTextFeild(ImageIcon icon,ImageIcon icon1, String text) { 


        this.normal_icon=icon;
            this.hover_icon=icon1;
            this.icon_Label=normal_icon;
            this.Matchtext=text;

            Font myFont = new Font("Segoe UI", Font.BOLD,12);
            setFont(myFont);
            Border border = UIManager.getBorder("TextField.border");  
            x0 = border.getBorderInsets(new JTextField()).left;  
            Border Textborder = BorderFactory.createLineBorder(new Color(0xd4d4d4 , false), 2 );
            setBorder(BorderFactory.createCompoundBorder(Textborder, 
            BorderFactory.createEmptyBorder(0,5 + icon_Label.getIconWidth(), 0, 0)));
            setText(text);
            addFocusListener(this) ; 
            addKeyListener(this) ; 

        }

    @Override
    public void paintComponent(Graphics g) {

       int y = (this.getHeight() - icon_Label.getIconHeight())/2;  
       super.paintComponent(g);  
       g.drawImage(icon_Label.getImage(), x0, y, this);   

    }

    @Override
    public void focusGained(FocusEvent e) {
        // TODO Auto-generated method stub
        if(e.getSource() == this && !this.start_action)
            this.setText("");

         this.icon_Label=hover_icon;
         this.repaint();
         this.revalidate();


    }
    @Override
    public void focusLost(FocusEvent arg0) {
        // TODO Auto-generated method stub
        if(!this.start_action || this.getText().length()==0)
           this.setText(this.Matchtext);

         this.icon_Label=normal_icon;
         this.repaint();
         this.revalidate();
    }
    @Override
    public void keyPressed(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }
    @Override
    public void keyReleased(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }
    @Override
    public void keyTyped(KeyEvent arg0) {
        // TODO Auto-generated method stub
        this.start_action=true;
    }



    }  

/* Output */

 JtextFeild name_Value=new CustomJTextFeild(   new ImageIcon(getClass().getResource("filename1")).getImage(), new ImageIcon(getClass().getResource("filename")).getImage(),"Name");  

I know this question is quite old but I stumbled upon it while looking for something else and thought I would add my two cents for others who come across it.

The CAUSE : The cause of the OPs reported issue is exactly as he postulates... ie the behavior in the super.paintComponent(g) effectively paints over his custom painting code.

However... there is nothing really wrong with the code that he posted. It does/will work and I must respecfully disagree with the DanD's suggested answer. Unfortunately, the OP does not include more example code so his exact issue can only be speculated.

Huh? you ask. Then what's going on?

The FIX : Quite simply, if you want to customize the appearance of JTextField using this approach, then you must effectively tell the superclass not to paint over your custom painting. This is accomplished by setting the following property values on your component:

text.setOpaque(false);
text.setBorder(null);

In this manner, you can leave all code as-is and you are effectively telling the original paintComponent() method not to draw a background color nor draw a border.

I offer the following SSCCE as an example and solution. Note the following:

  1. I created a static boolean 'FIXIT'. Hopefully, it goes without saying that you would not include this in "production" code; it is being used within the example to allow you to observe both behaviors. Simply toggle its value to see "BEFORE" and "AFTER".

  2. More importantly (IMO), notice that I set the mentioned property values OUTSIDE of the custom code class. I did this to more align with the way that the OP asked the question and this approach would not require a change to his custom class. However, as the comment in the code states, a more robust solution would set these values in the custom class constructor to ensure their correctness.

  3. I also offer a slightly more visually appealing paint method. While it is almost identical to the original, see the comments for the tweaks made. This is, of course, just my opinion but it is offered as an example nonetheless.

package misc;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

/**
 * An SSCCE in response to the following StackOverflow question:
 * https://stackoverflow.com/questions/13109638/my-custom-jtextfield-covered-by-super-paintcomponentg-method
 * 
 * @author kansasSamurai
 *
 */
@SuppressWarnings("serial")
public class CustomTextField extends JTextField {
    
    private static boolean FIXIT = true;
    
    public static void main(String args[]) {

        SwingUtilities.invokeLater( new Runnable() {
            @Override public void run() { createAndShowGUI(); }
        } );

    }

    protected static void createAndShowGUI() {
        JFrame frame = new JFrame("SSCCE - CustomTextField");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new GridBagLayout());
        
        CustomTextField text = new CustomTextField();
        text.setText("  Ipsum Lorem  "); 
            if (FIXIT) {
                // These two lines are NECESSARY...
                text.setOpaque(false);
                text.setBorder(null);
                // or!!! ... they could/should be added to the constructor(s) of your custom class

                // These two lines are OPTIONAL
                text.setForeground(Color.white);
                text.setCaretColor(Color.white);
            }
        frame.getContentPane().add(text);
        
        frame.pack();
        frame.setSize(330, 100); // these dimensions are "arbitrary"
        frame.setLocationRelativeTo(null); // centers the frame on screen
        frame.setVisible(true);
    }

    @Override
    protected void paintComponent(Graphics g) {
        if (FIXIT) {
            this.betterPaint(g);
            return;
        }

        final Graphics2D gd = (Graphics2D) g.create();
        gd.setPaint(new GradientPaint(0, 0, Color.BLUE, getWidth(), 0, Color.BLACK));
        gd.fillRoundRect(0, 0, getWidth(), getHeight(), getWidth() / 2, getHeight() / 2);
        gd.dispose();

        super.paintComponent(g);
    }
    
    protected void betterPaint(Graphics g) {
        final Graphics2D gd = (Graphics2D) g.create();
        
        // Improve appearance by enabling antialiasing
        gd.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        
        gd.setPaint(new GradientPaint(0, 0, Color.BLUE, getWidth(), 0, Color.BLACK));

        // Fully rounded ends (not strictly required to fixit... just an example)
        gd.fillRoundRect(0, 0, getWidth(), getHeight(), getHeight(), getHeight());

        gd.dispose();

        super.paintComponent(g);
    }
    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM