0

I searched for many topics but did not find any with a concrete answer. I need a field data input on the Graphics2D (like the JTextField or TextField).

Does anyone know how I can create this component? Or put a text field (Component) in Graphics2D?

Thank you!

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
lgapontes
  • 467
  • 7
  • 12
  • You will have to build it yourself when working directly with the graphics component, I suppose. I don't know about any built-in textfields for that. – flotothemoon Aug 20 '14 at 17:51
  • Why do you think you need to do this? If you really need to do this, use a KeyListener on whatever component you're extending to override the paintComponent() function. – Kevin Workman Aug 20 '14 at 17:54
  • 2
    A guess: Are you looking for something like this http://stackoverflow.com/a/24851920/3182664 ? – Marco13 Aug 20 '14 at 17:55
  • It's for a game. Yeah ... Marco13, is something like this ... let me try – lgapontes Aug 21 '14 at 11:00

2 Answers2

1

Not really sure what you are asking for, but here is some code that will add a text field to a panel when you double click. You can then add text to the text field.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;

public class InvisibleTextField extends JTextField
    implements ActionListener, FocusListener, MouseListener, DocumentListener
{
    public InvisibleTextField()
    {
        setOpaque( false );
        setColumns( 1 );
        setBorder( null );
        setSize( getPreferredSize() );
        setColumns( 0 );
        addActionListener( this );
        addFocusListener( this );
        addMouseListener( this );
        getDocument().addDocumentListener( this );
    }

//  Implement ActionListener

    public void actionPerformed(ActionEvent e)
    {
        setEditable( false );
    }

//  Implement FocusListener

    public void focusLost(FocusEvent e)
    {
        setEditable( false );
    }

    public void focusGained(FocusEvent e) {}

//  Implement MouseListener

    public void mouseClicked( MouseEvent e )
    {
        if (e.getClickCount() == 2)
            setEditable( true );
    }

    public void mouseEntered( MouseEvent e ) {}

    public void mouseExited( MouseEvent e ) {}

    public void mousePressed( MouseEvent e ) {}

    public void mouseReleased( MouseEvent e ) {}

//  Implement DocumentListener

    public void insertUpdate(DocumentEvent e)
    {
        updateSize();
    }

    public void removeUpdate(DocumentEvent e)
    {
        updateSize();
    }

    public void changedUpdate(DocumentEvent e) {}

    private void updateSize()
    {
        setSize( getPreferredSize() );
    }

    public static void main(String[] args)
    {
        JPanel panel = new JPanel();
        panel.setFocusable( true );
        panel.setLayout( null );
        panel.addMouseListener( new MouseAdapter()
        {
            public void mousePressed(MouseEvent e)
            {
                JPanel panel = (JPanel)e.getSource();

                if (e.getClickCount() == 1)
                {
                    panel.requestFocusInWindow();
                }

                if (e.getClickCount() == 2)
                {
                    InvisibleTextField tf = new InvisibleTextField();
                    tf.setText("Enter Text");
                    tf.setLocation(e.getPoint());
                    panel.add( tf );
                    tf.requestFocusInWindow();
                    tf.selectAll();
                }
            }
        });

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.add(new JLabel("Double Click to Add Text"), BorderLayout.NORTH);
        frame.add(panel);
        frame.setSize(650, 300);
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}
camickr
  • 321,443
  • 19
  • 166
  • 288
  • Sorry, I may not have explained well ... Your code could help me if I could put a InvisibleTextField on Graphics2D and it worked perfectly. But it does not work. When we put a JTextField in graphics the component keeps its behavior (the focus, receipt of characters) normal. This is my problem. Today I have a application built in Graphics2D and I need a JTextField that work in it. Thanks! – lgapontes Aug 21 '14 at 11:03
  • `Today I have a application built in Graphics2D` - I guess I don't understand that comment. Graphics are drawn onto a panel. I just added a text field to the panel. So I don't undersatnd what you are asking. If you just want to display text on the panel then you use the `Graphics.drawstring()` method. – camickr Aug 21 '14 at 14:16
  • I have a class that extends a JPanel and overrides the method paintComponent(Graphics g). Do casting parameter "g" to Graphics2D and draws various things like images, text, rectangles, etc. This JPanel implements MouseListener, KeyListener and MouseMotionListener interfaces and manages the user's actions. What I wanted was to add a JTextField this panel. The problem is that in this case the JTextField gets frozen and does not respond to actions as in your example. – lgapontes Aug 22 '14 at 19:34
  • So I gave you a working example. You did not post any code so how do you expect us to guess what you may be doing. So compare my working code with your code to see what the difference is and fix it. It you can't find the difference then post a `SSCCE` that demonstrates the problem. – camickr Aug 22 '14 at 20:42
  • Sorry guy... :'( my post gone bad ... thanks for your help, I tried to use all the suggestions posted here. In the end, I opted to create a component. See the last answer. Again, thank you! – lgapontes Aug 25 '14 at 14:19
0

you helped me a lot. After testing a few examples posted here, I chose to create a component. See the code below.

package br.com.linu.vectortown.base.screen.textfield;

import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.Serializable;

import br.com.linu.vectortown.base.screen.button.command.ICommand;
import br.com.linu.vectortown.base.screen.button.command.ISendCommand;
import br.com.linu.vectortown.base.screen.font.GameFont;
import br.com.linu.vectortown.base.screen.graphics.IGenericGraphics;
import br.com.linu.vectortown.base.util.PropertiesUtil;

public class GameTextField implements Serializable {

    private static final long serialVersionUID = -8273087631607158422L;

    private static final String CURSOR = "|";

    private StringBuffer buffer;
    private String showableText;
    private int index;
    private GameFont font;
    private int maxLength;
    private float alpha;

    private Rectangle rectangle;
    private Point textPoint;

    private String validCharacters;
    private int padding;

    private int cursorDelay;
    private int countDelay;
    private boolean cursor;
    private int cursorLength;

    private boolean focus;

    private ICommand clickedCommand;
    private ISendCommand returnKeyCommand;
    private ICommand escapeKeyCommand;

    public GameTextField(GameFont font, Rectangle rectangle, int maxLength) {

        /* Get default parameters */
        this.validCharacters = PropertiesUtil.INSTANCE.valorPor("game.text.field.valid.characters");
        this.padding = PropertiesUtil.INSTANCE.inteiroPor("game.text.field.padding");
        this.cursorDelay = PropertiesUtil.INSTANCE.inteiroPor("game.text.field.cursor.delay");
        this.alpha = PropertiesUtil.INSTANCE.floatPor("game.boxlog.text.field.background.alpha");

        /* Set attributes with constructor parameters */
        this.font = font;       
        this.rectangle = rectangle;

        /* Set text point */
        int x = this.rectangle.x + this.padding;
        int y = this.rectangle.y + 
                this.font.getSpacing( this.validCharacters ).height + 
                this.font.getFineTuning() -
                this.padding;       
        this.textPoint = new Point( x , y );

        /* Create variables to control buffer */
        this.buffer = new StringBuffer();
        this.showableText = "";
        this.maxLength = maxLength;     
        this.clearIndex();

        /* Create variables to control cursor */
        this.countDelay = 0; 
        this.cursor = false;
        this.cursorLength = this.font.getSpacing( CURSOR ).width;

        /* Starts without focus */
        this.focus = false;
    }

    private void clearTextField() {
        this.focus = false;
        this.buffer = new StringBuffer();
        this.showableText = "";     
        this.clearIndex();
    }

    private int getAdjustedTextWidth(String text) {
        return font.getSpacing(text).width + cursorLength + (2 * padding);
    }

    public void setClickedCommand(ICommand command) {
        this.clickedCommand = command;
    }

    public void setReturnKeyCommand(ISendCommand command) {
        this.returnKeyCommand = command;
    }

    public void setEscapeKeyCommand(ICommand command) {
        this.escapeKeyCommand = command;
    }

    public synchronized boolean wasClicked(int mouseX, int mouseY) {
        focus = rectangle.contains( new Point( mouseX , mouseY ) );
        if ( focus ) {
            this.clickedCommand.execute();
        }
        return focus;
    }

    public synchronized void onFocus() {
        focus = true;
    }

    /**
     * ENTER
     */
    public synchronized void returnKey() {
        if ( buffer.length() > 0 ) {
            String value = this.buffer.toString();
            clearTextField();
            this.returnKeyCommand.setParameters(value);
            this.returnKeyCommand.execute();
        } else {
            clearTextField();
            this.escapeKeyCommand.execute();
        }       
    }

    /**
     * ESC
     */
    public synchronized void escapeKey() {  
        clearTextField();
        this.escapeKeyCommand.execute();
    }

    private void clearIndex() {
        this.index = 0;
    }

    private int getIndex() {
        return index;
    }

    private void increaseIndex() {
        index++;
    }

    public synchronized void delete() {
        if ( buffer.length() > 0 ) {
            clearIndex();
            buffer.deleteCharAt( buffer.length() - 1 );

            /* Get showable text with index */
            showableText = buffer.substring( getIndex() , buffer.length() );

            /* Adjust showable text if necessary */
            while ( getAdjustedTextWidth(showableText) > rectangle.width ) {
                increaseIndex();
                showableText = buffer.substring( getIndex() , buffer.length() );
            }
        }
    }

    public synchronized void add(char character) {

        /* Validate size */
        if ( buffer.length() >= maxLength ) {
            return;
        }

        /* Validate character */
        if ( validCharacters.indexOf( character ) == -1 ) {
            return;
        }

        /* Add char in buffer */
        buffer.append( character );

        /* Get showable text with index */
        showableText = buffer.substring( getIndex() , buffer.length() );

        /* Adjust showable text if necessary */
        while ( getAdjustedTextWidth(showableText) > rectangle.width ) {
            increaseIndex();
            showableText = buffer.substring( getIndex() , buffer.length() );
        }
    }

    public synchronized void draw(IGenericGraphics graphics) {      

        if ( focus ) {
            /* Draw component */
            graphics.drawFilledRectangle(Color.white, rectangle, alpha);

            /* Verifier if can draw cursor */
            countDelay++;
            countDelay = countDelay % cursorDelay;          
            if ( countDelay == 0 ) {
                cursor = !cursor;
            }

            /* Set text to draw */
            String text = showableText + ( ( cursor ) ? CURSOR : "" );

            /* Draw */
            graphics.drawText(font, textPoint.x, textPoint.y, text);
        }
    }

}

Sorry if I did not put any code in question. What I really needed was a TextField any that ran entirely on a Graphics2D. In this application I get the Graphics2D of JPanel and I change their behavior manually (with keys and mouse listeners). When I put a JTextField in this JPanel, it did not work normally. This was the problem.

As I did not get a good alternative, I decided to create a custom component (code above). What matters is the methods draw() and add(). In the draw() method I drew a rectangle and the text that was entered character by character in the add() method. For now this is working ...

Thanks for the help everyone!

lgapontes
  • 467
  • 7
  • 12