LibGdx newline TextArea in android - java

I created an android application with TextArea using LibGdx. My problem is whenever clicked in the touch screen keyboard's newline ("Enter" equivalent in keyboard), it doesn't return a newline. The text still written on the same line. However, it only moves on the second line if it fills the width of the textArea. How could I return a new line on the textarea widget?

Taken from this discussion: http://badlogicgames.com/forum/viewtopic.php?f=11&t=15112
Add the following to the show() function:
final StringBuilder build = new StringBuilder();
final TextArea textArea = new TextArea("", skin);
textArea.setTextFieldListener(new TextFieldListener()
{
#Override
public void keyTyped(TextField textField, char c)
{
// Handle a newline properly. If not handled here, the TextField
// will advance to the next field.
if (c == '\n')
{
textArea.setMessageText(build.append("\n").toString());
}
}
});
This solved the problem for me.

Related

Disable the mouse cursor within a program

I'm creating a text adventure and I need to completely disable the mouse cursor. Not just hide it, although I already know how to do that, but disable it completely so that you must use Alt-Tab or a built-in quit button to stop. The main reason for this is because people can scroll with the mouse cursor and I need to disable that, I thought about canceling MouseEvents when they're fired but I couldn't get it to work (the listener that is.)
If someone knows how then please speak up and tell me! :)
EDIT: Whoops, I forgot my code. Here is my Console class.
This is started by another class with new Console();
EDIT 2: Here are some snippets of me trying to create an invisible cursor and a mouse listener. The first one works, but the latter does not.
// Invisible cursor
Toolkit toolkit = Toolkit.getDefaultToolkit();
Point hotSpot = new Point(0,0);
BufferedImage cursorImage = new BufferedImage(1, 1, BufferedImage.TRANSLUCENT);
Cursor invisibleCursor = toolkit.createCustomCursor(cursorImage, hotSpot, "InvisibleCursor");
frame.setCursor(invisibleCursor);
// Adding mouse listener
frame.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
System.out.println(me);
}
});
EDIT 3: To elaborate on the mouse listener it simply does not work. It doesn't print anything.
If you just want to prevent users from seeing old text, remove the old text from the JTextArea.
The easiest way to do it is to leave the JTextArea in a JScrollPane, and keep track of the lines yourself:
private static final int MAX_VISIBLE_LINES = 12;
private final Deque<String> lines = new LinkedList<>();
void appendLine(String line,
JTextArea textArea) {
lines.addLast(line);
if (lines.size() > MAX_VISIBLE_LINES) {
lines.removeFirst();
}
String text = String.join("\n", lines);
textArea.setText(text);
textArea.setCaretPosition(text.length());
try {
textArea.scrollRectToVisible(
textArea.modelToView(text.length()));
} catch (BadLocationException e) {
throw new RuntimeException(e);
}
}
Trying to commandeer the mouse on a multitasking desktop is just going to make users angry. Would you want an application preventing you from reading your e-mail?
Update:
If you want to base the number of lines of text on the JTextArea’s current height, use the JTextArea’s font metrics. I assume you don’t need to get it exactly right and it’s okay if the number is off by one or two lines. (To account for things like line wrapping would be considerably more difficult.)
private final Deque<String> lines = new LinkedList<>();
void appendLine(String line,
JTextArea textArea) {
FontMetrics metrics = textArea.getFontMetrics(textArea.getFont());
JViewport viewport = (JViewport) textArea.getParent();
int visibleLineCount = viewport.getExtentSize().height / metrics.getHeight();
lines.addLast(line);
while (lines.size() > visibleLineCount) {
lines.removeFirst();
}
String text = String.join("\n", lines);
textArea.setText(text);
textArea.setCaretPosition(text.length());
try {
textArea.scrollRectToVisible(
textArea.modelToView(text.length()));
} catch (BadLocationException e) {
throw new RuntimeException(e);
}
}

EventListener Performed by case

I would like to know the best way to approach what I am trying to achieve, I can't figure out the logical path I should take.
I have a JTextField and a JTextButton, when input is added to the JTextField and either enter or the button is pressed, it will display on the JTextArea. Now, what I want is to choose when and what the JTextArea and Button do.
For example I want default Enter & Button to display next append text in my code. Then when a case is presented I want the JTextField to only accept either int or string and then once completed, I want it to go back to default.
I don't know if what I am trying to do is logical or best practice...
The idea behind this is, I have a story text based gui game. I want it to display text to the JTextArea and when Enter or button is pressed to display the next line of text and when in the story it requires user input, the JTextArea will look for that input.
So far I have an EventListener and ActionListener which submits what I type from JTextField to JTextArea, but that is about it.
Thanks for your assistance! I have solved my issue, not sure if this is the "Best Solution". I combined your solution with a bit of tweaking.
In this instance, buttonState is an int which can be changed throughout my code by calling a constructor "setButtonState". I could have made buttonState a static to make things easier, but thought I could keep things clean.
enterButton.addActionListener(new ActionListener()
{ //This is used so when the enter screen button is pressed, it will submit text from text field to text area.
public void actionPerformed(ActionEvent e) {
String text = inputTextField.getText();
InputTextFieldEvent event = new InputTextFieldEvent(this, text);
if (buttonState == 0) //Displays all text in JTextField to JTextArea, mostly for testing purposes.
{
if (textInputListener != null) {
textInputListener.setInputListenerOccurred(event);
}
}
if (buttonState == 1) //Only accepts string for answer
{
if (inputTextField.getText().matches("[a-zA-Z]+"))
{
textInputListener.setInputListenerOccurred(event);
}
else
{
getAppendMainTextArea("You have entered an invalid input, only letters are allowed.");
}
}
if (buttonState == 2) //Only accepts int for answer
{
if (inputTextField.getText().matches("[0-9]+"))
{
textInputListener.setInputListenerOccurred(event);
}
else
{
getAppendMainTextArea("You have entered an invalid input, only numbers are allowed.");
}
}
}
});

Rewriting "HackerType" with Java

I was directed to the website Hackertyper.com - and it intrigued me very much. So I decided that, using Java, I would attempt to re-write it. I stumbled on some issues while I did it.
Currently, so far from my intro Java course, I only learned how to use the Scanner class, so at the moment, my "code" only takes an input after pressing the "Enter" key. At the same time, upon pressing enter, the entire String gets printed out.
My questions are:
Are there any libraries in which it would take an input (any key on the keyboard, in this case) and do something without pressing "Enter", and.
What do I need to do in order to take an input, stop the piece of code, wait for the next input, before executing the next loop?
So far below is the very poorly written code of what I have.
String paragraph = "hellothere";
Scanner newInput = new Scanner(System.in);
String input = newInput.nextLine();
for(int i = 0; i < paragraph.length(); i++){
if(input.equals("2")){
System.out.print(paragraph.charAt(i));
input = newInput.nextLine(); // call input again after executed the loop
}
}
After I solve these issues I think I will dabble with IO and let Java call a text file in which inside would have pieces of code, which onKeyPress would type out the i-th index.
Thanks!
I assume you mean Hacker Typer, not hacker type?
1) I think what you need is a key listener event
2) You could write a method that is called when the key event fires. The method would then return a piece of text. You store the text in an array, so it always returns the next piece of code.
To create the array from string you can use String.split
edit: i just saw that it always puts two characters, not the next word.
I would recommend you used the SWT toolkit.
For a functional example, run my code below. You only need to add the SWT dependencies.
Writing into the console is silly. This is much cooler:
public class Waffles
{
// Keeps track of how many times any key is pressed
private static int keyCounter = 0;
// Used to continuously append characters from the input string
private final StringBuilder builder;
// This can be read from a file, or whatever
private final String GIBBERISH;
public static void main(final String[] args)
{
new Waffles();
}
private Waffles()
{
builder = new StringBuilder();
// Put your dummy code here (extract from a file)
GIBBERISH = " I freaking love waffles!";
// Loop the SWT Display
init();
}
private void init()
{
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("HackerTyper");
shell.setSize(500, 500);
shell.setLayout(new GridLayout());
shell.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
// Here we create the text area
createWidget(shell);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
private void createWidget(final Composite parent)
{
// Wrap it for multi line text, and set it to read only, so we can't modify
// the text 'manually'
final Text textArea = new Text(parent, SWT.MULTI | SWT.WRAP | SWT.READ_ONLY);
textArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
// Yay colours!
textArea.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
textArea.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_GREEN));
// This is what was recommended by the other two answers
textArea.addKeyListener(new KeyListener()
{
#Override
public void keyPressed(final KeyEvent arg0)
{
// *magic*
textArea.setText( getGibberish() );
}
#Override
public void keyReleased(final KeyEvent arg0)
{
}
});
}
private String getGibberish()
{
if (keyCounter > GIBBERISH.length() - 1)
keyCounter = 0; // Careful not to go out of string bounds
// Continuously append it, then pass the whole text to the textArea
builder.append( GIBBERISH.charAt(keyCounter++) );
return builder.toString();
}
}
FEEL like a hacker.
BE like a hacker. HUZZZAAA!
I'm really tired.
There is an interface called KeyListener but this only works with swing classes, and based on you're code this a console application. You could use JNativehook which allows you to use swing events in a console application. You should learn basic swing events before using this though.

JTextArea - Highlight Text While Scrolling Up or Down

I'm trying to work with a non-editable JTextArea added to a JScrollPane. I want a line to be highlighted when the user clicks on that specific line. I could implement this part using the following code:
public static void initHighlightOption(final JTextArea textArea){
textArea.setFont(new Font("Courier New", Font.PLAIN, 12));
textArea.setEditable(false);
final Action selectLine = getAction(textArea, DefaultEditorKit.selectLineAction);
textArea.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 1) {
selectLine.actionPerformed(null);
}
});
textArea.setSelectionStart(0);
textArea.setSelectionEnd(0);
}
public static Action getAction(JTextArea textArea, String name) {
Action action = null;
Action[] actions = textArea.getActions();
for (int i = 0; i < actions.length; i++) {
if (name.equals(actions[i].getValue(Action.NAME).toString())) {
action = actions[i];
break;
}
}
return action;
}
What I want to add is that once a line is highlighted and user scrolls up/down using keyboard up/down key, i want the current line to be highlighted. Is this possible by adding a keyListener? I'm stuck on how highlight data while scrolling up.
The text area contains data like this:
Line1
Line2
Line3
Line4
Line5
(i.e. there might be new lines between two particular lines of data)
What your asking for is not so easy to do. First off use a JTextPane instead of a JTextArea, it'll be much easier to handle. You will be need to get the Highlighter object from it
Highlighter hl = textPane.getHighlighter();
and you would probably have to keep track of your caret position each time the user scrolls with the arrow keys. When doing that you need to programatically change the highlights; something like:
Highlighter.Highlight myHighlight = null;
Highlighter.Highlight[] highlights = textPane.getHighlighter().getHighlights();
myHighlight = highlights[0]; //assuming there is one only
try {
hl.changeHighlight(myHighlight, myHighlight.getStartOffset()+1, myHighlight.getEndOffset());
}
catch(BadLocationException e) {
e.printStackTrace();
}
You can probably put this in your onKeyReleased() method. You kind of get the idea of what you're going to have to do. Read up on using JTextPane and Highlighter classes in the Java API docs, it will really help you alot.

Why does my Java Swing JScrollPane keep scrolling to the top?

I'm developing a small calculator widget that keeps a running log of calculations. It's supposed to scroll to the bottom of the log every time a new entry is added. This part seems to be working fine.
The problem is, when I press a calculator button that does not add to the log, the log pane always scrolls back to the top, and the scrollbar disappears. How can I keep it from doing this?
The code that adds to the log is:
private JTextPane logArea; //This is placed inside a JScrollPane
private void log(String m, SimpleAttributeSet a) {
int len = logArea.getDocument().getLength();
logArea.setEditable(true);
logArea.setCaretPosition(len);
logArea.setCharacterAttributes(a, false);
logArea.replaceSelection(m);
logArea.scrollRectToVisible(new Rectangle(0,logArea.getBounds(null).height,1,1));
logArea.setEditable(false);
}
The code that seems to be messing with the scroll is:
private void addDigit(char digit) {
if (clearDisplayBeforeDigit) {
clearNumDisplay();
}
if (numInDisplay.getText().length() < maxNumDigits) {
if (digit == '.') { //Point
if (!hasPoint) { //Only one point allowed
hasPoint = true;
String newText = numInDisplay.getText() + ".";
numInDisplay.setText(newText);
}
} else { //New digit
String newText = numInDisplay.getText() + digit;
numInDisplay.setText(newText);
}
}
}
The code you think is causing the problem doesn't even reference the logArea, so why would you think this causes the problem?
You don't need to use the scrollRectToVisible(...) method. The setCaretPosition(...) should do the trick. Although you should get the length of the document and invoke that method AFTER you update the document.
Check out Text Area Scrolling for more information.
Edit:
I also don't see any reason for changing the editability of the text area.

Categories