I created JFrame and JTextArea above it. JTextArea has defaul text "This is text for demo version", that has been set via setText() method.
The goal is to implement this logic:
If I start printing text, the old text should be deleted and new one should apper.
After that, when new text is printed and if I click "Enter" - new text should be saved into private ArrayList<String> textList
The main question is How to replace old text when I print the first symbol of my text?
I tried to add TestTextArea.this.replaceRange(keyText,0, 30); inside keyReleased(KeyEvent e) {}; (30 it's the last index of default string "This is text for demo version" ). But everytime when I print anything, it causes IllegalArgumentException and seems that old text is still visible on the background.
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
public class TestTextArea extends JTextArea {
private String text = "This is text for demo version";
private ArrayList<String> textList = new ArrayList<>();
TestTextArea() {
setBackground(new Color(23, 28, 34, 240));
setForeground(new Color(6, 200, 109));
setCaretColor(new Color(6, 200, 109));
setCaretPosition(0);
setFont(new Font("Helvetica Neue", Font.BOLD, 16));
setText(text);
setLineWrap(true);
setWrapStyleWord(true);
setFocusable(true);
setEnabled(true);
setEditable(true);
setVisible(true);
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
String keyText = KeyEvent.getKeyText(e.getKeyCode());
TestTextArea.this.replaceRange(keyText,0, 30);
if (keyText.equals("Enter")) {
textList.add(TestTextArea.this.getText());
}
}
});
}
public static void main(String []args) {
JFrame f = new JFrame();
TestTextArea area = new TestTextArea();
f.add(area);
f.setSize(400,200);
f.setDefaultCloseOperation(EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
Is there any another way to solve this? I want that after I type the text and press Enter, all the text that I typed is saved. But at the moment it turns out that when you enter the first character, the default text is deleted, but even no one character is saved.
I am sorry, in advance for the possibly not very successful statement of the problem.
I think I understand your requirements.
When the first character is typed, clear the JTextArea and capture the typed text in the JTextArea,
When the Enter key is pressed, save the typed text in the List.
This code meets these requirements.
I use a JTextArea. The only reason you extend a Swing component, or any Java class, is to override one or more of the class methods.
I set the size of the JTextArea in the JTextArea constructor. Then I pack the JFrame.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TextEntryExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new TextEntryExample());
}
private List<String> textList;
private String text;
private JTextArea textArea;
public TextEntryExample() {
this.text = "This is text for demo version";
this.textList = new ArrayList<>();
}
#Override
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.textArea = createPrompt();
f.add(textArea, BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private JTextArea createPrompt() {
JTextArea textArea = new JTextArea(10, 30);
textArea.addKeyListener(new PromptListener());
textArea.setBackground(new Color(23, 28, 34, 240));
textArea.setForeground(new Color(6, 200, 109));
textArea.setCaretColor(new Color(6, 200, 109));
textArea.setCaretPosition(0);
textArea.setFont(new Font("Helvetica Neue", Font.BOLD, 16));
textArea.setText(text);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
return textArea;
}
public class PromptListener implements KeyListener {
private boolean entry;
public PromptListener() {
this.entry = false;
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent event) {
if (!entry) {
String oldText = textArea.getText();
textArea.replaceRange("", 0, oldText.length());
entry = true;
}
}
#Override
public void keyReleased(KeyEvent event) {
if (entry) {
String keyText = KeyEvent.getKeyText(event.getKeyCode());
if (keyText.equals("Enter")) {
textList.add(textArea.getText());
entry = false;
}
}
}
}
}
This might not be the easiest, but you could replace the document with one that clears the text on the first edit.
I haven't checked, but I think JTextArea uses a DefaultStyledDocument. You can extend that and override the editing methods to check a flag - if it's set, clear the text and clear the flag. I've done something similar this for JTextField (using PlainDocument) - here's how that would look:
public class PromptDocument
extends PlainDocument
{
private bool clearOnEdit = false;
public void insertString(int offset, String str, AttributeSet a)
throws BadLocationException
{
if (clearOnEdit) {
super.remove(offset, getLength());
clearOnEdit = false;
}
super.insertString(offset, str, a);
}
public void remove(int offset, int len)
throws BadLocationException
{
if (clearOnEdit) {
super.remove(offset, getLength());
clearOnEdit = false;
} else {
super.remove(offset, len);
}
}
public void setClearOnEdit(final boolean clear) {
clearOnEdit = clear;
}
}
It should be similar for JTextArea (I haven't tested this, might be missing things). You can just use setDocument() on your JTextArea after you create it.
Related
I'm using a JTextArea in a JFrame. I would like the tab key to insert four spaces instead of a tab.
The method setTabSize does not work, as it puts a tab ('\t') in the contents of the text area.
How can I have JTextArea insert four spaces instead of a tab whenever I press the tab key? That way the getText() method will return indentations of four spaces for every tab.
I would avoid using KeyListeners (as a general rule with JTextComponents) and even Key Bindings, since while Key Bindings would work for keyboard input, it wouldn't work for copy-and-paste.
In my mind, the best way is to use a DocumentFilter set on the JTextArea's Document (which is a PlainDocument, by the way). This way, even if you copy and paste text into the JTextAreas, one with tabs, then all the tabs will automatically be converted to 4 spaces on insertion.
For example:
import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.PlainDocument;
public class TestTextArea {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JTextArea textArea = new JTextArea(20, 50);
JScrollPane scrollPane = new JScrollPane(textArea);
int spaceCount = 4;
((PlainDocument) textArea.getDocument()).setDocumentFilter(new ChangeTabToSpacesFilter(spaceCount));
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
private static class ChangeTabToSpacesFilter extends DocumentFilter {
private int spaceCount;
private String spaces = "";
public ChangeTabToSpacesFilter(int spaceCount) {
this.spaceCount = spaceCount;
for (int i = 0; i < spaceCount; i++) {
spaces += " ";
}
}
#Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)
throws BadLocationException {
string = string.replace("\t", spaces);
super.insertString(fb, offset, string, attr);
}
#Override
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
super.remove(fb, offset, length);
}
#Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
throws BadLocationException {
text = text.replace("\t", spaces);
super.replace(fb, offset, length, text, attrs);
}
}
}
So now, even if I copy and paste a document with tabs within it, into the JTextArea, all tabs will be automatically replaced with spaceCount spaces.
This is one of those “I wonder if…” moments.
Personally, I’d try a tackle the problem more directly, at the source. This means “trapping” the Tab event some how and “replacing” it’s functionality.
So, I started by modifying http://www.java2s.com/Tutorial/Java/0260__Swing-Event/ListingtheKeyBindingsinaComponent.htm, which could list the key bindings for component, for this, I found that the JTextArea was using insert-tab as the action map key.
I then created my own Action designed to insert spaces at the current caret position, for example…
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
// insert-tab
JTextArea ta = new JTextArea(10, 20);
add(new JScrollPane(ta));
ActionMap am = ta.getActionMap();
am.put("insert-tab", new SpacesTabAction());
}
public class SpacesTabAction extends AbstractAction {
#Override
public void actionPerformed(ActionEvent e) {
if (!(e.getSource() instanceof JTextArea)) {
return;
}
JTextArea textArea = (JTextArea) e.getSource();
int caretPosition = textArea.getCaretPosition();
Document document = textArea.getDocument();
try {
document.insertString(caretPosition, " ", null);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
}
}
}
Admittable limitations
This will not cover pasting the text into the component, which would otherwise be covered by a DocumentFilter, but, I like to think about scenarios where a DocumentFilter might not be usable (such as having one already installed)
More investigations
The method setTabSize does not work, as it puts a tab ('\t') in the contents of the text area.
Is this one of those “spaces vs tabs” flame wars :P
I did some fiddling and discovered that, most of the inconsistencies with setTabSize came about from not using a fixed width font, for example…
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
Font font = Font.decode("Courier New").deriveFont(12);
JTextArea ta = new JTextArea(10, 40);
ta.setFont(font);
ta.setText("---|----|----|----|----|----|----|----|\n\tHello");
ta.setTabSize(0);
add(new JScrollPane(ta));
DefaultComboBoxModel<Integer> model = new DefaultComboBoxModel<>(new Integer[] {0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24});
JComboBox<Integer> tabSizes = new JComboBox<>(model);
add(tabSizes, BorderLayout.NORTH);
tabSizes.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Integer tabSize = (Integer)tabSizes.getSelectedItem();
ta.setTabSize(tabSize);
}
});
}
}
}
When I set the font to “Courier New”, I was able to get a consistent indentation which was in align with the set tab size
I'm obviously missing something...
The tab is four spaces. In this "111\t" string, the tab is expands to 1 space; "22\t" — to 2 spaces; "3\t" — to 3 spaces; finally, "\t" expands to four spaces.
Yes, isn't this the expected behaviour?!
JTextArea, tabSize of 4, mono spaced font
Sublime text editor, tabSize of 4, mono spaced font
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.util.StringJoiner;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
StringJoiner textJoiner = new StringJoiner("\n");
for (int row = 0; row < 10; row++) {
StringJoiner rowJoiner = new StringJoiner("\t");
for (int col = 0; col < 10; col++) {
rowJoiner.add(Integer.toString(col).repeat(row));
}
textJoiner.add(rowJoiner.toString());
}
setLayout(new BorderLayout());
JTextArea ta = new JTextArea(10, 40);
ta.setFont(new Font("Monospaced", Font.PLAIN, 13));
ta.setText(textJoiner.toString());
add(new JScrollPane(ta));
}
protected String replicate(char value, int times) {
return new String(new char[times]).replace('\0', value);
}
}
}
I think you're thinking of "tab stops", rather than "tab size", for example, in which case, even the DocumentFilter won't do what you're expecting.
I assume the use of monospace font is implied in the question
Don't "assume" we know anything. In my experimentation, the font was NOT monospaced. This is where providing "expected" and "actual" results and a minimal reproducible example, as it removes the ambiguity and doesn't waste everybody's time (especially yours) 😉
It is how it works in any text editor.
I'm obviously using different text editors 🤪
I am trying to write a text editor. I want two TextAreas: 1st one for typing/editing in unicode script and 2nd one for simultaneously printing output of the unicode script input in corresponding Roman Script (ASCII) set by myself on the basis of a transliteration scheme.
I am not able to update and simultaneously print the input text in output textarea while I call the transliteration method. I can sense a little bit that there is something wrong while I set the output textArea to print simultaneously but I am unable to find out what exactly is that.
The Editor class------->
import java.awt.*;
import java.beans.PropertyChangeSupport;
import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
public class editor extends JPanel {
private static final int ROWS = 10;
private static final int COLS = 50;
private static final String[] BUTTON_NAMES = {"विविधाः", "द्वाराणि", "Setting", "Parse", "Compile"};
private static final int GAP = 3;
private JTextArea inputTextArea = new JTextArea(ROWS, COLS);
private JTextArea outputTextArea = new JTextArea(ROWS, COLS);
private JTextArea TA = new JTextArea(ROWS, COLS);
//calling the transliteration method
transliterator tr = new transliterator();
Document asciiDocument=tr.DevanagariTransliteration(inputTextArea.getDocument());
public editor() throws BadLocationException {
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, GAP, 0));
for (String btnName : BUTTON_NAMES) {
buttonPanel.add(new JButton(btnName));
}
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(buttonPanel);
add(putInTitledScrollPane(inputTextArea, "देवनागरी <<<<<<>>>>>> Devanagari"));
inputTextArea.setFocusable(true);
outputTextArea.setFocusable(false);
outputTextArea.setEditable(false);
//String inputCheck = inputTextArea.getText();
//inputTextArea.setText("x");
//if (inputTextArea.getText().length()>0) {
outputTextArea.setDocument(asciiDocument);//printing input in 2nd textarea
// outputTextArea.setDocument(inputTextArea.getDocument());//printing input in 2nd textarea
add(putInTitledScrollPane(outputTextArea, "IndicASCII"));
}
private JPanel putInTitledScrollPane(JComponent component,
String title) {
JPanel wrapperPanel = new JPanel(new BorderLayout());
wrapperPanel.setBorder(BorderFactory.createTitledBorder(title));
wrapperPanel.add(new JScrollPane(component));
return wrapperPanel;
}
private static void createAndShowGui() throws BadLocationException {
editor mainPanel = new editor();
JFrame frame = new JFrame("Unicode Editor");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
ImageIcon imgicon = new ImageIcon("MyIcon.jpg");
frame.setIconImage(imgicon.getImage());
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
createAndShowGui();
} catch (BadLocationException e) {
e.printStackTrace();
}
}
});
}
}
And transliteration class method:
import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
public class transliterator {
//method that returns a Document type
// the method - importing devanagari text through the type 'Document' from input textArea by call
public Document DevanagariTransliteration(Document devanagariTextDocument) throws BadLocationException {
//extracting the devanagari text from the imported Document type
String asciiText = devanagariTextDocument.getText(0, devanagariTextDocument.getLength());
//devanagari unicode a replaced by ascii a
String transliteratedText = asciiText.replace('\u0905', 'a');
JTextArea jt = new JTextArea();
//inserting the TRANSLITERATED text to a textArea to extract as a Document again
jt.setText(transliteratedText);
//extracting and creating as a document
Document ASCIITextDocument = jt.getDocument();
//returning the document
return ASCIITextDocument;
}
}
To reflect changes in one document onto another document you can use a DocumentListener as suggested by camickr.
The following is an mre that demonstrates updating the "output" JTextArea after processing the changes in the "input" JTextArea.
The processing used for demonstration purposes is a simply converting the input to upper case. This should be changed to your specific needs :
import java.awt.BorderLayout;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
public class MyWindow extends JPanel {
private static final int ROWS = 10, COLS = 50;
private final JTextArea outputTextArea;
public MyWindow() {
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
JTextArea inputTextArea = new JTextArea(ROWS, COLS);
inputTextArea.getDocument().addDocumentListener(new TransliterateDocumentListener());
add(putInTitledScrollPane(inputTextArea,"Input"));
outputTextArea = new JTextArea(ROWS, COLS);
outputTextArea.setFocusable(false);
outputTextArea.setEditable(false);
add(putInTitledScrollPane(outputTextArea, "Output"));
}
private JPanel putInTitledScrollPane(JComponent component, String title) {
JPanel wrapperPanel = new JPanel(new BorderLayout());
wrapperPanel.setBorder(BorderFactory.createTitledBorder(title));
wrapperPanel.add(new JScrollPane(component));
return wrapperPanel;
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Document Listener Demo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add( new MyWindow());
frame.pack();
frame.setVisible(true);
}
private void insert(String text, int from) {
text = process(text);
try {
outputTextArea.getDocument().insertString(from, text, null);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
private void remove(int from, int length) {
try {
outputTextArea.getDocument().remove(from, length);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
private String process(String text) {
//todo process text as needed
//returns upper case text for demo
return text.toUpperCase();
}
class TransliterateDocumentListener implements DocumentListener {
#Override
public void insertUpdate(DocumentEvent e) {
Document doc = e.getDocument();
int from = e.getOffset(), length = e.getLength();
try {
insert(doc.getText(from, length), from);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
#Override
public void removeUpdate(DocumentEvent e) {
remove(e.getOffset(), e.getLength());
}
#Override
public void changedUpdate(DocumentEvent e) {
//Plain text components don't fire these events.
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
When I used the setDocument() method I cannot handle the text input
All the setDocument() method does is share the Document between multiple components. So whatever you type will be displayed in both components.
Instead you would use a DocumentListener. The listener will generate an event whenever text is added or removed from the Document. Then you will need to read the text from the Document and do your translation and update the second text area.
See the section from the Swing tutorial on How to Write a DocumentListener for the basics to get you started.
This count line number of textarea. The code works correctly, but when run this code the textarea is not active, the caret is hidden and the keyboard
keys not work unless I click on textarea.
code:
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Element;
public class LineNumber extends JFrame implements DocumentListener {
private static final long serialVersionUID = -1093726028044203117L;
private JScrollPane scroll;
private JTextArea textArea, lineArea;
public static void main(String[] args) {
new LineNumber().setVisible(true);
}
public LineNumber() {
super("Line Numbers");
setSize(500, 500);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setUI();
}
private void setUI() {
textArea = new JTextArea();
lineArea = new JTextArea(0, 3);
lineArea.setEditable(false);
lineArea.setForeground(Color.GRAY);
scroll = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
textArea.getDocument().addDocumentListener(this);
scroll.setViewportView(textArea);
scroll.setRowHeaderView(lineArea);
getContentPane().add(scroll, BorderLayout.CENTER);
}
public void changedUpdate(DocumentEvent event) {
lineArea.setFont(textArea.getFont());
lineArea.setText(getLine());
}
public void insertUpdate(DocumentEvent event) {
lineArea.setFont(textArea.getFont());
lineArea.setText(getLine());
}
public void removeUpdate(DocumentEvent event) {
lineArea.setFont(textArea.getFont());
lineArea.setText(getLine());
}
public String getLine() {
int caretPos = 0;
String lines;
caretPos = textArea.getDocument().getLength();
Element root = textArea.getDocument().getDefaultRootElement();
lines = String.format("%s%s", 1, System.lineSeparator());
for (int i = 2; i < root.getElementIndex(caretPos) + 2; i++) {
lines += String.format("%s%s", i, System.lineSeparator());
}
return lines;
}
}
If I do not add lineArea to the scrollpane the textarea work correctly but after add to setRowHeaderView the textarea only gets active with a mouse click....
You can prevent the line number text area from gaining focus by using:
lineArea = new JTextArea(0, 3);
lineArea.setEditable(false);
lineArea.setFocusable(false);
You can also check out Text Component Line Number for a fancier implementation that supports:
wrapped text
text with different size fonts (when using a JTextPane)
By default it focus on first component, so if you want to focus on another one try this code in the constructor.
addWindowFocusListener(new WindowAdapter() {
#Override
public void windowGainedFocus(WindowEvent e) {
textArea.requestFocusInWindow();
}
});
textArea is now focused, more on this.
a basic problem that i can't figure out, tried a lot of things and can't get it to work, i need to be able to get the value/text of the variable
String input;
so that i can use it again in a different class in order to do an if statement based upon the result
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class pInterface extends JFrame {
String input;
private JTextField item1;
public pInterface() {
super("PAnnalyser");
setLayout(new FlowLayout());
item1 = new JTextField("enter text here", 10);
add(item1);
myhandler handler = new myhandler();
item1.addActionListener(handler);
System.out.println();
}
public class myhandler implements ActionListener {
// class that is going to handle the events
public void actionPerformed(ActionEvent event) {
// set the variable equal to empty
if (event.getSource() == item1)// find value in box number 1
input = String.format("%s", event.getActionCommand());
}
public String userValue(String input) {
return input;
}
}
}
You could display the window as a modal JDialog, not a JFrame and place the obtained String into a private field that can be accessed via a getter method. Then the calling code can easily obtain the String and use it. Note that there's no need for a separate String field, which you've called "input", since we can easily and simply extract a String directly from the JTextField (in our "getter" method).
For example:
import java.awt.Dialog.ModalityType;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.*;
import javax.swing.text.JTextComponent;
public class TestPInterface {
#SuppressWarnings("serial")
private static void createAndShowGui() {
final JFrame frame = new JFrame("TestPInterface");
// JDialog to hold our JPanel
final JDialog pInterestDialog = new JDialog(frame, "PInterest",
ModalityType.APPLICATION_MODAL);
final MyPInterface myPInterface = new MyPInterface();
// add JPanel to dialog
pInterestDialog.add(myPInterface);
pInterestDialog.pack();
pInterestDialog.setLocationByPlatform(true);
final JTextField textField = new JTextField(10);
textField.setEditable(false);
textField.setFocusable(false);
JPanel mainPanel = new JPanel();
mainPanel.add(textField);
mainPanel.add(new JButton(new AbstractAction("Get Input") {
#Override
public void actionPerformed(ActionEvent e) {
// show dialog
pInterestDialog.setVisible(true);
// dialog has returned, and so now extract Text
textField.setText(myPInterface.getText());
}
}));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
// by making the class a JPanel, you can put it anywhere you want
// in a JFrame, a JDialog, a JOptionPane, another JPanel
#SuppressWarnings("serial")
class MyPInterface extends JPanel {
// no need for a String field since we can
// get our Strings directly from the JTextField
private JTextField textField = new JTextField(10);
public MyPInterface() {
textField.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
JTextComponent textComp = (JTextComponent) e.getSource();
textComp.selectAll();
}
});
add(new JLabel("Enter Text Here:"));
add(textField);
textField.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Window win = (Window) SwingUtilities.getWindowAncestor(MyPInterface.this);
win.dispose();
}
});
}
public String getText() {
return textField.getText();
}
}
A Good way of doing this is use Callback mechanism.
I have already posted an answer in the same context.
Please find it here JFrame in separate class, what about the ActionListener?.
Your method is a bit confusing:
public String userValue(String input) {
return input;
}
I guess you want to do something like this:
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
Also your JFrame is not visible yet. Set the visibility like this setVisible(true)
So I've built a very basic Web browser - I'm trying desperately to remove the contents of the address bar when a user clicks on it (JTextField) this appears with some text in as default. Any advice is appreciated.
Have a great day!
MY CODE
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Web_Browser extends JFrame {
private final JTextField addressBar;
private final JEditorPane display;
// Constructor
public Web_Browser() {
super("Web Browser");
addressBar = new JTextField("Click & Type Web Address e.g. http://www.google.com");
addressBar.addActionListener(
new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
loadGo(event.getActionCommand());
}
}
);
add(addressBar, BorderLayout.NORTH);
display = new JEditorPane();
display.setEditable(false);
display.addHyperlinkListener(
new HyperlinkListener(){
#Override
public void hyperlinkUpdate(HyperlinkEvent event){
if(event.getEventType()==HyperlinkEvent.EventType.ACTIVATED){
loadGo(event.getURL().toString());
}
}
}
);
add(new JScrollPane(display), BorderLayout.CENTER);
setSize(500,300);
setVisible(true);
}
// loadGo to sisplay on the screen
private void loadGo(String userText) {
try{
display.setPage(userText);
addressBar.setText(userText);
}catch(IOException e){
System.out.println("Invalid URL, try again");
}
}
}
Use a FocusListener. On focusGained, select all.
addressBar.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
JTextComponent textComponent = (JTextComponent) e.getSource();
textComponent.selectAll();
}
});
For example:
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.*;
import javax.swing.text.JTextComponent;
#SuppressWarnings("serial")
public class FocusExample extends JPanel {
private static final int TF_COUNT = 5;
private JTextField[] textFields = new JTextField[TF_COUNT];
public FocusExample() {
for (int i = 0; i < textFields.length; i++) {
textFields[i] = new JTextField("Foo " + (i + 1), 10);
textFields[i].addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
JTextComponent textComponent = (JTextComponent) e.getSource();
textComponent.selectAll();
}
});
add(textFields[i]);
}
}
private static void createAndShowGui() {
FocusExample mainPanel = new FocusExample();
JFrame frame = new JFrame("FocusExample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
This gives the user the option of leaving the previous text in place, of adding to the previous text, or of simply over-writing it by typing.
new JTextField("Click & Type Web Address e.g. http://www.google.com");
Maybe you want the Text Prompt, which doesn't actually store any text in the text field. It just gives the user a hint what the text field is for.
This is beneficial so that you don't generate DocumentEvents etc., since you are not actually changing the Document.
Add a mouseListener instead of your actionListener method.
addressBar.addMouseListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent e){
addressBar.setText("");
}