我的自定义JTextField由super.paintComponent(g)方法覆盖

时间:2012-10-28 14:25:50

标签: java swing jtextfield paintcomponent

我通过扩展JtextField类和覆盖paintComponent(Graphics g)方法创建了一个自定义JTextField。 当我编译并拖入JFrame时,它正常工作。 但是当我运行它时,结果是不同的。

我的自定义JTextField被白色方块覆盖,我怀疑是super.paintComponent(g)的结果;方法

这是我在paintComponent()方法上的代码;

@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);
}

3 个答案:

答案 0 :(得分:3)

super.paintComponent(g)移至paintComponent的顶部。这样,您可以确保在超类paintComponent执行完毕后完成自定义绘制。

答案 1 :(得分:0)

//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");  

答案 2 :(得分:0)

我知道这个问题已经很久了,但是在寻找其他问题时偶然发现了这个问题,并认为我会为遇到这个问题的其他人增加2美分。

原因:报告OP的原因完全是他所假定的……即super.paintComponent(g)中的行为有效地覆盖了他的自定义绘画代码。

但是...他发布的代码并没有真正的错。它确实/将起作用,我必须明确不同意DanD的建议答案。不幸的是,OP没有包含更多示例代码,因此只能推测出他的确切问题。

嗯?你问。那是怎么回事?

FIX :很简单,如果要使用此方法来自定义JTextField的外观,则必须有效地告诉超类不要在自定义绘制上进行​​绘制。这是通过在组件上设置以下属性值来完成的:

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

通过这种方式,您可以将所有代码保持原样,并且可以有效地告诉原始的paintComponent()方法不要绘制背景色或绘制边框。

我提供以下SSCCE作为示例和解决方案。 请注意以下几点:

  1. 我创建了一个静态布尔值'FIXIT'。希望,不用说,您不会在“生产”代码中包含此代码。在示例中使用它来允许您观察这两种行为。只需切换其值即可看到“之前”和“之后”。

  2. 更重要的是(IMO),请注意,我将自定义代码类的属性值设置为OUTSIDE。我这样做是为了与OP提出问题的方式更加吻合,并且这种方法不需要更改其自定义类。但是,如代码中的注释所述,一种更可靠的解决方案是在自定义类构造函数中设置这些值,以确保其正确性。

  3. 我还提供了一种更具视觉吸引力的绘画方法。虽然与原始版本几乎相同,但请参阅注释以了解所做的调整。当然,这只是我的观点,但仍作为示例提供。

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);
    }
    
}