1

I'm learning Java using Art and Science of Java (using Java SE 6u45). Trying to Change the font of text by entering the new font type in a JTextField. But the problem is that I can't enter any text in JTextField. The problem is common to other swing components i've used like JButton, JCheckBox. But in the latter components I could see the effect of selection, even though the visual selection stays the same, meaning that the check box remains checked even after clicking but the code shows the result of an unchecked box.

But in case of JTextField, not even the effect is showing. Not also could i delete a test text i put in JTextField. Tried to use isEditable() , grabFocus() and isFocusable(). Could it be a Java bug ?

/**
* Example 10.9
 * 
 * This program prints the given text in the font inputted by the user in JTextField
 */
package ASJ_Examples;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JLabel;
import javax.swing.JTextField;

import acm.graphics.GLabel;
import acm.program.GraphicsProgram;

public class FontSampler extends GraphicsProgram implements ActionListener{
/**
 * Eclispe Generated
 */
private static final long serialVersionUID = -5734136235409079420L;
private static final String TEST_STRING = "This is a test";
private static final double LEFT_MARGIN = 3;
private static final int MAX_FONT_NAME = 10;

public void init(){
    addJFontLabel();
    addJFontTextField();
    lastY = 0;
    addGLabel(); 
}
/**
 * Adds a text field to enter the required font
 */
private void addJFontTextField() {
    String test = "new";
    fontField = new JTextField(test, MAX_FONT_NAME);    //added to see if Jtextfiled is responding 
//      fontField.setEnabled(true);
//      fontField.setEditable(true);
    fontField.addActionListener(this);
    //added these to give focus to jtextfield but no effect
    fontField.isEditable();
    fontField.grabFocus();
    fontField.isFocusable();
    //add to window
    add(fontField, SOUTH);

}
/**
 * Adds JFontLAbel to denote the text input field
 */
private void addJFontLabel() {
    add(new JLabel("Font"), SOUTH);

}

/**
 * Adds the test label to canvas
 */
private void addGLabel() {
    lastLabel = new GLabel(TEST_STRING);
    add(lastLabel, 20, 20);

}

public void ActionPerformed(ActionEvent e){
    if(e.getSource() == fontField){
        GLabel label = new GLabel(TEST_STRING);
        label.setFont(lastLabel.getFont()); //to display the text even if the suer entered a non-allowed font
        label.setFont(fontField.getText()); //change the font to u4ser demanded font
        addGlabel(label);
        lastLabel = label;
    }
}
/**
 *adds a Glabel on the next line adjusting for heights
 * @param label
 */
private void addGlabel(GLabel label) {
    lastY += label.getHeight();
    lastY += lastLabel.getDescent() - label.getDescent();
    add(label, LEFT_MARGIN, lastY);

}
/**
 * JTextField to enter font
 */
private JTextField fontField;
/**
 * GLabel which is being worked on
 */
private GLabel lastLabel;
/**
 * 
 */
private double lastY;
}
Robin Green
  • 32,079
  • 16
  • 104
  • 187
  • 1
    The ACM API is pure AWT, but the 'J' components are Swing. You might need to invoke the functionality to allow a [mix of AWT & Swing](http://www.oracle.com/technetwork/articles/java/mixing-components-433992.html). – Andrew Thompson May 06 '13 at 05:18
  • i guess that's the case, but that will take me time to understand. Tried the example from the tutorial u pointed to effect component hierarchy, but no effect. I suppose will get back to the issue at a later stage. – Akash Kumar Sharma May 06 '13 at 06:59
  • 1
    for better help sooner post an [SSCCE](http://sscce.org/), short, runnable, compilable, (shot to the dark) BTW use undecorated JDialog instead of J/Window – mKorbel May 06 '13 at 07:15
  • Try using a `java.awt.TextField` instead and see if it makes a difference – MadProgrammer May 06 '13 at 21:26

3 Answers3

0

try using fontField.requestFocus(); instead of fontField.grabFocus(); and fontField.setEditable(true); instead of fontField.isEditable(); fontField.setFocusable(true); instead of fontField.isFocusable();

btw fontField.setEditable(true); and fontField.setFocusable(true); are not necessary by default they are set to true.

Thudani Hettimulla
  • 754
  • 1
  • 12
  • 32
0

But in the latter components I could see the effect of selection, even though the visual selection stays the same, meaning that the check box remains checked even after clicking but the code shows the result of an unchecked box.

That sounds very strange. Maybe the GraphicsProgram class is doing something naughty. Cannot tell w/o its code though.

fontField.isEditable();
fontField.grabFocus();
fontField.isFocusable();

The first returns a boolean if the field is editable (it is by default). The second should not be used by client programs, use fontField.requestFocusInWindow() instead. The third returns a boolean if the field is focusable (it is by default).

fontField.addActionListener(this);

An ActionListener on a JTextField does nothing. Try doing this:

fontfield.getDocument().addDocumentListener(new DocumentListener() {

    @Override
    public void removeUpdate(DocumentEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void insertUpdate(DocumentEvent e) {
        // TODO Auto-generated method stub  
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
        // TODO Auto-generated method stub
    }
});
Marco
  • 1,430
  • 10
  • 18
  • 2
    A developer dies a slow and horrible death every time some attaches a `KeyListener` to a text field :P – MadProgrammer May 06 '13 at 06:04
  • Use `DocumentListener` to JTextField instead of using `KeyListener` – Amarnath May 06 '13 at 06:16
  • tried it `fontField.addKeyListener(new KeyAdapter(){ @Override public void keyTyped(KeyEvent e){ if(e.getKeyCode() == KeyEvent.VK_ENTER){ println("test"); } } });` but no effect still. Guess it's some [AWT- Swing mix](http://www.oracle.com/technetwork/articles/java/mixing-components-433992.html) stuff as noted by @andrew-thompson . Have to read it. For now the issue is unresolved. I agree it was my bad to add ActionListener to JTextField. Thanks for that :) – Akash Kumar Sharma May 06 '13 at 06:56
  • Is it hitting to `keyTyped(){}` of your KeyListener()? If not it might be due to something like laying out components. I guess – Thudani Hettimulla May 06 '13 at 07:28
  • @MadProgrammer Oh my, I better stop answering questions before I had my first coffee then ;) Obviously it's the DocumentListener.. Thanks for pointing it out. Edited. – Marco May 06 '13 at 15:27
  • @Diluu yeah, it is layout issue. For this reason instead of using GraphicsProgram layout I created layout using JPanel which extends Program and then it worked. – Akash Kumar Sharma May 07 '13 at 03:11
0

As @andrew-thompson pointed out, the issue was mix of awt and swing. I suppose somehow the GComponent was overlaying Swing component JTextField which made it inaccessible. So the workaround is to create JPanel and a KeyListener to the JTextField as noted by @marco . This is the code that works : SSCCE Code

 /**
 * 
 * This program prints the given text in the font inputted by the user in JTextField
 */

import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JPanel;
import javax.swing.JTextField;

import acm.graphics.GLabel;
import acm.program.GraphicsProgram;

public class FontSampler extends GraphicsProgram implements KeyListener{
private static final String TEST_STRING = "This is a test";
private static final double LEFT_MARGIN = 3;
private static final int MAX_FONT_NAME = 10;

public void init(){
    initPanel();    //init panel
    addJFontTextField();    //adds fontField to enter the font type
    addGLabel();    //adds default label to GCanvas
    lastY = 0;  //default y offset for post-processed label
    add(panel); //adds panel to canvas
}

/**
 * initialises panel 
 */
private void initPanel() {
    panel = new JPanel();
    panel.setLayout(new BorderLayout());

}

/**
 * Adds a text field to enter the required font
 */
private void addJFontTextField() {
    fontField = new JTextField( MAX_FONT_NAME);//added to see if Jtextfiled is responding
    panel.add(fontField, BorderLayout.SOUTH);
    fontField.addKeyListener(this); //adds key listener
}

/**
 * Adds the test label to canvas
 */
private void addGLabel() {
    lastLabel = new GLabel(TEST_STRING);
    add(lastLabel, 20, 20);

}

    /**
     * Called when any key is pressed
     */
public void keyPressed(KeyEvent e){
    if(e.getKeyCode() == KeyEvent.VK_ENTER){//check for enter key pressed
        GLabel label = new GLabel(TEST_STRING);
        label.setFont(lastLabel.getFont()); 
        label.setFont(fontField.getText());
        addGlabel(label);
        lastLabel = label;
    }
}

/**
 *adds a Glabel on the next line adjusting for heights
 * @param label
 */
private void addGlabel(GLabel label) {
    lastY += label.getHeight();
    lastY += lastLabel.getDescent() - label.getDescent();
    add(label, LEFT_MARGIN, lastY);
}

/**
 * JTextField to enter font
 */
private JTextField fontField;
/**
 * GLabel which is being worked on
 */
private GLabel lastLabel;
/**
 * 
 */
private double lastY;

private JPanel panel;

}

Thanks :)

  • Don't use a KeyListener. Add an ActionListener to the text field. – camickr May 06 '13 at 15:13
  • @camickr Neither. Use a DocumentListener. ActionListener only triggers in a JTextField when the user presses Enter. – Marco May 06 '13 at 15:29
  • @Marco, The KeyListener (in the code posted above) is just looking for the Enter key, that is why the ActionListener should be used in the context of this answer. – camickr May 06 '13 at 16:08
  • @camickr Oh, I did not see that. Well in that case you are correct ;) Still it's not advisable to do it that way, what happens when the user copy&pastes something and then just switches to another component w/o pressing Enter? – Marco May 06 '13 at 16:10
  • @marco yeah. ActionListener will be far better in that case. – Akash Kumar Sharma May 06 '13 at 18:29
  • @Marco, if somebody switches to another component without pressing Enter, then the user doesn't want the Enter Action to be executed. You should not use a KeyListener or a Document or a DocumentFilter to listen for the pressing of the Enter key. The advisable way to listen for the Enter key is to add an Action to the text field. That is why this component supports the addActionListener() method. – camickr May 06 '13 at 19:41