This site requires JavaScript, please enable it in your browser!
Greenfoot back
basil60
basil60 wrote ...

2014/7/3

Can't work out how to use <code>getText()</code>

basil60 basil60

2014/7/3

#
Scenario available at http://www.greenfoot.org/scenarios/11766 I've attempted to hack Ed Parrish's GUI to produce a text based "calculator". The goal was something "simple" using GUI elements - I now know that's not really possible, but I'd like to keep it relatively simple. Initially, I want to capture user input (Weight) and output it to the lable below. I can't work out how to use the "<code>getText()</code>" he talks about in the in-line documentation. I'd appreciate any help. Textfield
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.TextHitInfo;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;

/**
 * Class <code>TextField</code> is a Greenfoot component that allows the user
 * to enter a single line of text.
 *
 * When users are finished entering text, they can signal they are finished by
 * pressing the Enter key. Pressing the Enter key will fire the ActionListener
 * interface.
 *
 * The <code>ActionListener</code> interface is like the
 * <code>ActionListener</code> interface in Java Swing. Scenarios using the
 * <code>ActionListener</code> callback must include the
 * <code>ActionListener</code> interface, and the class listening for button
 * clicks must implement that interface. In addition, the implementing class
 * must add itself to the callback list by calling the
 * <code>addActionListener()</code> method. Then when the Enter key is pressed,
 * the <code>actionPerformed()</code> method in the listening class will be
 * called.
 *
 * The developer can read the text the user entered by calling the
 * <code>getText()</code> method.
 *
 * @author Ed Parrish
 * @version 1.0  12/28/2010
 * @see http://java.sun.com/developer/onlineTraining/Media/2DText/index.html
 */
public class TextField extends GUIComponent {
    private static final Color CARET_COLOR = Color.RED;
    private static final Color HIGHLIGHT_COLOR = Color.PINK;
    private static final long KEYSTOKE_DELAY = 110;
    private static final long BLINK_DELAY = 400;
    // Padding to leave small horizontal gap between box edge and cursor
    private static final int X_PAD = 1;
    // Input text buffer
    private StringBuilder input;
    // Width of the input field
    private int numCols;
    // TextLayout is used for drawing and measuring. Since it is expensive to
    // create, cache it and invalidate it when text is modified.
    private TextLayout layout = null;
    private boolean validTextLayout = false;
    // Timer variable used to prevent keystrokes from going too fast
    private long lastKeystrokeTime;
    // The main insertion index.
    private int index1 = 0;
    // The second insertion index used for mouse selection
    private int index2;
    // The x-coordinate of the origin relative to the left side of the component
    private float originX;
    // The y-coordinate of the origin relative to the top of the component
    private float originY;
    // Component with the cursor showing
    private GreenfootImage cursorOn;
    // Component without the cursor showing
    private GreenfootImage cursorOff;
    // Timer variable to control blinking cursor
    private long lastBlinkTime;
    // Variable to control blink state
    private boolean blinkOn;


    /**
     * Constructs a text field with no text and with a width of one column.
     */
    public TextField() {
        this ("", 1);
    }

    /**
     * Constructs a text field with the initial text displayed in the default
     * text color and font and with a width of one column.
     *
     * @param text The initial text to display on the text field.
     */
    public TextField(String text) {
        this (text, 1);
    }

    /**
     * Constructs a text field  with no text and the specified number of
     * columns.
     *
     * @param columns Number of columns to calculate the width.
     */
    public TextField(int columns) {
        this ("", columns);
    }

    /**
     * Constructs a text field with the specified number of columns and the
     * initial text displayed in the default text color and font.
     *
     * @param text The initial text to display on the text field.
     * @param columns Number of columns to calculate the width.
     */
    public TextField(String text, int columns) {
        this (text, columns, DEFAULT_FONT, DEFAULT_FG, Color.WHITE);
    }

    /**
     * Constructs a text field of the specified width in columns with the
     * initial text displayed in the specified font and default text color.
     *
     * @param text The initial text to display on the text field.
     * @param columns Number of columns to calculate the width.
     * @param font The font used to write on this component.
     */
    public TextField(String text, int columns, Font font) {
        this (text, columns, font, DEFAULT_FG, Color.WHITE);
    }

    /**
     * Constructs a text field of the specified width in columns with the
     * initial text displayed in the specified font and text color on the
     * specified background color.
     *
     * @param text The initial text to display on the text field.
     * @param columns Number of columns to calculate the width.
     * @param font The font used to write on this component.
     * @param fg The desired foreground color.
     * @param bg The desired background color.
     */
    public TextField(String text, int columns, Font font, Color fg, Color bg) {
        super(text, font, fg, bg, null);
        numCols = columns;
        input = new StringBuilder(text);
        super.repaint();
        originX = getInsets().left + X_PAD;
    }

    /**
     * Handle keystrokes and mouse actions for this component.
     */
    public void act() {
        super.act(); // check for focus request
        if (!isEnabled()) return;

        // Move caret using mouse pointer
        if (Greenfoot.mousePressed(this)) {
            MouseInfo e = Greenfoot.getMouseInfo();
            if (e != null && layout != null) {
                index1 = getHitPosition(e.getX(), e.getY());
                index2 = index1;
            }
            // Repaint the component so the new caret will be displayed.
            super.repaint();
        }

        // Highlight text with mouse pointer
        if (Greenfoot.mouseDragged(this)) {
            MouseInfo e = Greenfoot.getMouseInfo();
            if (e != null && layout != null) {
                index2 = getHitPosition(e.getX(), e.getY());
            }
            // Repaint the component so the highlight will be displayed.
            super.repaint();
        }

        // Ignore keystrokes if not the focus owner
        if (!isFocusOwner()) return;

        // Blink the cursor
        if (System.currentTimeMillis() - lastBlinkTime > BLINK_DELAY) {
            lastBlinkTime = System.currentTimeMillis();
            blinkOn = !blinkOn;
            if (blinkOn) {
                setImage(cursorOn);
            } else {
                setImage(cursorOff);
            }
        }

        // Slow down keystrokes on fast systems
        if (System.currentTimeMillis() - lastKeystrokeTime < KEYSTOKE_DELAY) {
            return;
        }
        lastKeystrokeTime = System.currentTimeMillis();

        // Process keystrokes
        TextHitInfo newPosition = null;
        String key = Greenfoot.getKey();
        if (key != null && key.length() == 1) {
            // Single character keystrokes like: 'a'...'z', '0'...'9'
            deleteHighlighedChars();
            input.insert(index1, key);
            index1++;
            index2 = index1;
            repaint();
        } else if (Greenfoot.isKeyDown("space")) {
            deleteHighlighedChars();
            input.insert(index1, " ");
            index1++;
            index2 = index1;
            repaint();
        } else if (Greenfoot.isKeyDown("backspace")) {
            if (index1 != index2) {
                deleteHighlighedChars();
                repaint();
            } else if (input.length() > 0 && index1 > 0) {
                --index1;
                input.deleteCharAt(index1);
                index2 = index1;
                repaint();
            }
        } else if (Greenfoot.isKeyDown("enter")) {
            fireActionEvent();
        } else if (Greenfoot.isKeyDown("right") && layout != null) {
            newPosition = layout.getNextRightHit(index2);
        } else if (Greenfoot.isKeyDown("left") && layout != null) {
            newPosition = layout.getNextLeftHit(index1);
        }
        if (newPosition != null) {
            index1 = newPosition.getInsertionIndex();
            index2 = index1;
            super.repaint();
        }
    }

    /**
     * Set the text to be displayed.
     *
     * @param newText The new text to be displayed on the button.
     */
    public void setText(String newText) {
        if (newText == null) {
            input.replace(0, input.length(), "");
        } else {
            input.replace(0, input.length(), newText);
        }
        index1 = 0;
        index2 = index1;
        repaint();
    }

    /**
     * Returns the text for this component.
     *
     * @return The text displayed on this component.
     */
    public String getText() {
        return input.toString();
    }

    /**
     * Sets the number of columns in this <code>TextField</code>.
     *
     * @param columns the number of columns >= 0
     * @exception IllegalArgumentException if <code>columns</code>
     *      is less than 0
     */
    public void setColumns(int columns) {
        int oldVal = numCols;
        if (columns < 0) {
            throw new IllegalArgumentException("columns less than zero.");
        }
        if (numCols != oldVal) {
            numCols = columns;
            repaint();
        }
    }

    /**
     * Returns the number of columns in this <code>TextField</code>.
     *
     * @return the number of columns >= 0.
     */
    public int getColumns() {
        return numCols;
    }

    /**
     * Paints the component image, including the background, border and text.
     *
     * This method recreates the text layout. To repaint without recreating
     * the text layout, call <code>super.repaint()</code>.
     */
    public void repaint() {
        validTextLayout = false;
        super.repaint();
    }

    /**
     * Paints the text field's background image.
     *
     * @param g The <code>Graphics</code> context in which to paint.
     */
    public void paintComponent(Graphics g) {
        GreenfootImage img = null;
        if (isFixedSize()) {
            img = new GreenfootImage(getWidth(), getHeight());
        } else {
            // Calculate image size based on text height & numCols
            FontMetrics fm = g.getFontMetrics();
            String text = getText();
            if (text == null) text = "";
            int width = fm.charWidth('m') * numCols;
            if (width <= 0) width = 1;
            int height = fm.getHeight();
            Insets insets = getInsets();
            if (insets != null) {
                width += insets.left + insets.right;
                height += insets.top + insets.bottom;
            }
            img = new GreenfootImage(width, height);
        }
        if (getBackground().getTransparency() > 0) {
            img.setColor(getBackground());
            img.fill();
        }
        // Paint box around the text field if no border supercedes it
        if (getBorder() == null) {
            img.setColor(Color.BLACK);
            img.drawRect(0, 0, img.getWidth() - 1, img.getHeight() - 1);
            // Draw thicker line if this component has the focus
            if (isFocusOwner()) {
                img.drawRect(1, 1, img.getWidth() - 3, img.getHeight() - 3);
            }
        }
        setImage(img);
    }

    /**
     * Paints the text onto the labels background image.
     *
     * @param g The <code>Graphics</code> context in which to paint.
     */
    public void paintText(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        // Draw the text that the user has entered
        TextLayout tl = getTextLayout(g2);
        if (tl != null) {
            scrollToVisible();
            AffineTransform at
                = AffineTransform.getTranslateInstance(originX, originY);

            if (isFocusOwner()) {
                // Draw the highlight
                Shape hilight = tl.getLogicalHighlightShape(index1, index2);
                hilight = at.createTransformedShape(hilight);
                g2.setColor(HIGHLIGHT_COLOR);
                g2.fill(hilight);
            }
            if (getForeground() != null) g2.setColor(getForeground());
            tl.draw(g2, originX, originY);
            cursorOff = new GreenfootImage(getImage());
            if (isFocusOwner()) {
                // Draw the caret at the insertion index
                Shape[] carets = tl.getCaretShapes(index2);
                g2.setColor(CARET_COLOR);
                Shape caret = at.createTransformedShape(carets[0]);
                g2.draw(caret);
            }
            cursorOn = getImage();
        } else if (isFocusOwner()) {
            // Draw a caret for the empty box
            cursorOff = new GreenfootImage(getImage());
            g2.setColor(CARET_COLOR);
            Insets i = getInsets();
            g2.drawLine(i.left + X_PAD, i.top, i.right + X_PAD,
                getHeight() - i.bottom);
            cursorOn = getImage();
        }
    }

    /**
     * Scrolls the field left or right until it is visible.
     */
    private void scrollToVisible() {
        if (layout == null) return;
        Insets i = getInsets();
        int xMin = i.left + X_PAD;
        int xMax = getWidth() - i.right - X_PAD;
        int cursorX = layout.getCaretShapes(index2)[0].getBounds().x;
        float adjustX = layout.getAdvance() - xMax + originX;
        if (originX < xMin && adjustX < 0) {
            // adjust right margin when characters deleted
            originX = originX - adjustX;
            if (originX > xMin) originX = xMin;
        }
        if (cursorX < xMin - originX) {
            // Scroll to the left
            originX = xMin - cursorX;
        } else if (cursorX > xMax - originX) {
            // Scroll to the right
            originX = xMax - cursorX;
        }
    }

    /**
     * Returns a text layout for the text that the user has entered. The text
     * layout is cached until <code>invalidateTextLayout</code> is called.
     *
     * @param g  the <code>Graphics</code> context in which to paint.
     * @return a <code>TextLayout</code> for the text that the user has
     *         entered, or <code>null</code> if no text has been entered.
     */
    private TextLayout getTextLayout(Graphics g) {
        if (!validTextLayout) {
            layout = null;
            if (input.length() > 0) {
                Graphics2D g2 = (Graphics2D) g;
                FontRenderContext frc = g2.getFontRenderContext();
                layout = new TextLayout(getText(), getFont(), frc);
                originY = (getHeight() + layout.getAscent()
                           - layout.getDescent()) / 2;
            }
        }
        validTextLayout = true;
        return layout;
    }

    /**
     * Computes the character position of the mouse cursor.
     *
     * @param mouseX The x-coordinate of the mouse pointer.
     * @param mouseY The y-coordinate of the mouse pointer.
     * @return The character position of the mouse cursor.
     */
    private int getHitPosition(int mouseX, int mouseY) {
        // Compute mouse click location relative to text layout's origin
        float x = mouseX - getX() + getWidth() / 2 - originX;
        float y = mouseY - getY() + getHeight() / 2;
        // Get the character position of the mouse click.
        TextHitInfo hit = layout.hitTestChar(x, y);
        return hit.getInsertionIndex();
    }

    /**
     * Deletes the characters within the highlighted area.
     */
    private void deleteHighlighedChars() {
        if (index2 > index1) {
            input.delete(index1, index2);
            index2 = index1;
        } else if (index1 > index2) {
            input.delete(index2, index1);
            index1 = index2;
        }
    }
}
GUI World
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;

/**
 * Tests for GUI components in various configurations.
 *
 * @author Ed Parrish
 * @version 1.0 1/4/2011
 */
public class GUIWorld extends World implements ActionListener {
    public static final Font LARGE_FONT = new Font("SansSerif", Font.BOLD, 20);
    public static final Font MED_FONT = new Font("SansSerif", Font.ITALIC, 14);
    public static final Font SMALL_FONT = new Font("SansSerif", Font.PLAIN, 10);

    private Label defaultLabel;
    private Label label1;
    private TextField defaultTF;
    private Label label2;
   

    /**
     * Constructor for objects of class GUIWorld.
     */
    public GUIWorld() {
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(600, 430, 1);

        // Test labels
        // Following use of GreenfootImage works with version 2.0.1 or later
//        Label label = new Label(new GreenfootImage("Various labels", 16,
//            Color.BLACK, new Color(0, 0, 0, 0)));
        
        defaultLabel = new Label("Weight in Kg");
        addObject(defaultLabel, 65, 83);
        label1 = new Label("Weight for Age");
        addObject(label1, 67, 159);
        label1.setSize(new Dimension(75, 50));

        label2 = new Label("");
        addObject(label2, 165, 159);
        label2.setBackground(Color.WHITE);
        label2.setSize(new Dimension(75, 50));
       


        // Text fields
        
        defaultTF = new TextField("", 8);
        defaultTF.addActionListener(this);
        defaultTF.requestFocus();
        addObject(defaultTF, 164, 84);
        defaultTF.setSize(new Dimension(75, 50));
    }

    // Test the isPressed() method of Button
    public void act() {
       

           }

    // Test the actionPerformed() callback
    public void actionPerformed(GUIComponent c) {
        
        
    }
}
Label
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;

/**
 * A label with a transparent background for writing text.
 *
 * @author Ed Parrish
 * @version 1.1  12/25/2010
 */
public class Label extends GUIComponent {
    // FontMetrics makes line height too high so reduce it
    private static final double ASCENT_MULT = .90;
    // Label backgrounds are transparent by default
    private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
    // Flag to test if background image was set by user
    private boolean hasBGImage;

    /**
     * Constructs a label with the specified background image. The image may
     * be written upon by calling <code>setText()</code>.
     *
     * @param img The background image to display.
     */
    public Label(GreenfootImage img) {
        hasBGImage = true;
        setImage(img);
        setFocusable(false);
    }

    /**
     * Constructs a label with the specified text displayed in the default text
     * color and font on a transparent background without a border.
     *
     * @param text The text to display on the label
     */
    public Label(String text) {
        this (text, DEFAULT_FONT, DEFAULT_FG);
    }

    /**
     * Constructs a label with the specified text and font using the default
     * text color on a transparent background without a border.
     *
     * @param text The text to display on the label
     * @param font The font with which to write the text.
     */
    public Label(String text, Font font) {
        this (text, font, DEFAULT_FG);
    }

    /**
     * Constructs a label with text of the specified color using the default
     * font on a transparent background without a border.
     *
     * @param text The text to display on the label
     * @param textColor The color to use for displaying text.
     */
    public Label(String text, Color textColor) {
        this (text, DEFAULT_FONT, textColor);
    }

    /**
     * Constructs a label with text of the specified color and font on a
     * transparent background without a border.
     *
     * @param text The text to display on the label
     * @param font The font with which to display the text.
     * @param textColor The color to use for displaying text.
     */
    public Label(String text, Font font, Color textColor) {
        super(text, font, textColor, TRANSPARENT);
        setFocusable(false);
        setBorder(null); // calls repaint
    }

    /**
     * Constructs a label with text of the specified color on a background
     * of the specified color with a border.
     *
     * @param text The text to display on the label
     * @param font The font with which to display the text.
     * @param textColor The color to use for displaying text.
     * @param bgColor The desired background color.
     */
    public Label(String text, Font font, Color textColor, Color bgColor) {
        super(text, font, textColor, bgColor);
        setFocusable(false);
        repaint();
    }

    /**
     * Prepares the labels background image.
     *
     * @param g The <code>Graphics</code> context in which to paint.
     */
    public void paintComponent(Graphics g) {
        if (hasBGImage) return;
        GreenfootImage img = null;
        if (isFixedSize()) {
            img = new GreenfootImage(getWidth(), getHeight());
        } else {
            // Create image sized for text width and height
            Dimension d = getTextDimension(getText(), g);
            img = new GreenfootImage(d.width, d.height);
        }
        if (getBackground() != TRANSPARENT) {
            img.setColor(getBackground());
            img.fill();
        }
        setImage(img);
    }

    /**
     * Paints the text onto the labels background image.
     *
     * @param g The <code>Graphics</code> context in which to paint.
     */
    public void paintText(Graphics g) {
        String labelText = getText();
        if (labelText == null || labelText.length() == 0) return;
        String[] lines = splitLines(labelText, g);
        GreenfootImage img = getImage();
        if (getFont() != null) img.setFont(getFont());
        if (getForeground() != null) img.setColor(getForeground());

        FontMetrics fm = g.getFontMetrics();
        int lineHeight = (int) (fm.getHeight() * ASCENT_MULT);
        int y = lineHeight + (getHeight() - (lineHeight * lines.length)
            - fm.getDescent()) / 2;
        for (int i = 0; i < lines.length; i++) {
            int x = getWidth() / 2 - fm.stringWidth(lines[i]) / 2;
            img.drawString(lines[i], x, y);
            y += lineHeight;
        }
    }
}
Game/maniac Game/maniac

2014/7/6

#
getText literally just returns the string of text in the text field
basil60 basil60

2014/7/14

#
Thanks So how do I get the content of the InputTextBox (in this scenario) to output to a label (label)? I've tried getText() as well as Textfield.getText(). I'm no closer at this point - also, can I store the value of the Textfield as a variable - so I can then apply some Math? ie int weight =Textfield.getText(); weight = weight * 1.6;
danpost danpost

2014/7/14

#
From the world class you can just use:
String text = defaultTF.getText();
From an actor class, you need to code it this way:
String text = ((TextField)getWorld().getObjects(TextField.class).get(0)).getText();
which is the same as:
World world;
world = getWorld();
java.util.List<Object> objects;
objects = world.getObjects(TextField.class);
TextField textField;
textField = (TextField)objects.get(0);
String text;
text = textField.getText();
As an alternative, you can add a 'get' method to the world class to return the TextField object ('defaultTF'), like this:
public TextField getTextField()
{
    return defaultTF;
}
and then use:
String text = ((GUIWorld)getWorld()).getTextField().getText();
You will need to convert the String into an int value before using maths. Please refer to this page of the Java tutorials for information on Converting Strings to Numbers and back.
basil60 basil60

2014/7/14

#
Thanks danpost. Where does
String text = ((GUIWorld)getWorld()).getTextField().getText(); 
get inserted?
danpost danpost

2014/7/14

#
It would go at the place after you grab user input and before you set the text of the label and do the maths,,I guess.
basil60 basil60

2014/7/15

#
Thanks Danpost. Even just getting the textfield data to appear in the label is alluding me. I regularly get java.lang.NullPointerException errors (I realise these are operator errors). In the World class I tried
// Test the actionPerformed() callback
    public void actionPerformed(GUIComponent c) {
       String text = defaultTF.getText(); 
           }
I tried assigning the text to String text in the Textfield Actor, and calling it in the Label Actor . In short, no further ahead. I feel I'll have to ditch the GUI - I find it's not intuitive.
danpost danpost

2014/7/15

#
Maybe you should consult this page of the java tutorials.
You need to login to post a reply.