G'day all,
I have an application which needs to display an ASCII file of 15 lines in a Swing component that cannot be edited by the user.
Below is my code which reads the ASCII file byte by byte. My thanks to the helpful commenters who explained that a JTextArea.setEditable(false) would be appropriate in Swing.
However, my code merely displays a string of numbers, when I personally made the ASCII file to be something quite different. Does anyone know what I am doing wrong and how to get the ASCII characters themselves to display?
import java.io.*;
import javax.swing.*;
public class LoadMap extends JFrame {
public LoadMap() throws IOException {
FileInputStream fIn = new FileInputStream("map.srn");
BufferedReader rd = new BufferedReader(new InputStreamReader(fIn, "US-ASCII"));
String map = "";
JTextArea mapArea = new JTextArea(15, 50);
try {
int c;
while ((c = rd.read()) != -1) {
map= map + c;
}
} finally {
if (rd != null) {
rd.close();
}
}
mapArea.setText(map);
mapArea.setEditable(false);
add(mapArea);
pack();
setVisible(true);
}
}
You could construct a String inside the loop, and then put the string into JLabel when you've finished.
This makes me feel like Captain Obvious, but still: just load the entire text first, and then build the label using the desired text. Or, as other posters rightly suggest, use a JTextArea since its more well-suited for multiline content.
Use a JTextArea and call
setEditable(false);
to stop the user being able to edit the data
I've just read your code through and realise that's not a comprehensive enough answer. You can't do "+" on a label. What you need to do is read the text in first and store it somewhere, then call
setText(yourTextAsString);
on your text component on screen (for which I'd still use the JTextArea), and you need to add the text area to the frame, so your code would look something like:
public LoadMap() {
String data = // read your data
JTextArea textArea = new JTextArea();
textArea.setText(data);
textArea.setEditable(false);
setLayout(new GridLayout());
add(textArea);
pack();
setVisible(true);
}
I would suggest reading the Swing tutorial to get some more info on using Swing components
A JLabel will not display line breaks (unless you use HTML). So as the others wrote, use a text area.
However, there's another hidden problem with your code: you don't specify the file's encoding, which means the file contents may be garbled if it contains non-ASCII characters and its encoding does not match Java's platform default. To fix this, do not use FileReader. Instead, use a FileInputStream and wrap it in an InputStreamReader, specifying the encoding in its constructor.
Use a JTextArea and call setEditable(false).
https://docs.oracle.com/javase/1.5.0/docs/api/javax/swing/text/JTextComponent.html#setEditable(boolean)
Here:
String map = "";
int c;
while ((c = rd.read()) != -1) {
map= map + c;
}
What you're doing it appending int's to the string.
You should cast them to char instead.
int c;
while ((c = rd.read()) != -1) {
map= map + ( char ) c;
}
You can see much better patterns in these questions.
How do I create a Java string from the contents of a file?
https://stackoverflow.com/questions/181634/simplest-efficient-ways-to-read-binary-and-ascii-files-to-string-or-similar-in-v/324792#324792 ( see java part )
You could use a JTextArea and set it to read only:
jtextarea.setEditable(false);
Related
When I do something like fileText.setText(path) in a JTextField, it works well unless the text is in Hebrew (or combines English and Hebrew). Then I get something like this:
I tried different fonts (even fonts that "Hebrew" is mentioned in them), but it didn't help. How do I fix it?
By the way, it is working properly with the ToolTipText (fileText.setToolTipText(path))
Here's my code:
// browse files or folders
public void browse(JTextField txtField) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int result = fileChooser.showOpenDialog(this);
if (result == JFileChooser.APPROVE_OPTION) {
File selectedDir = fileChooser.getSelectedFile();
String path = selectedDir.getAbsolutePath();
if (txtField == srcText) {
srcText.setText(path);
srcText.setToolTipText(path);
}
else {
if (txtField == dstText) {
dstText.setText(path);
dstText.setToolTipText(path);
}
}}
}
Not an answer, since your code works well as it is. Please try to your environment.
For me it works flawlessly out of the box with the default font on Windows 7. Java JDK1.8.0_31
public class JTextFieldExample extends JFrame {
private static final long serialVersionUID = 1L;
public JTextFieldExample() {
super("TextField Test Demo");
final Container container = getContentPane();
final JTextField textField=new JTextField("hello \u05DD\u05D5\u05DC\u05E9 Hello \u05DD\u05D5\u05DC\u05E9");
// optionally set RTL
textField.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
container.add(textField);
setSize(300,100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(final String args[]) {
new JTextFieldExample();
}
}
Makes a window with a JTextField containing:
hello םולש Hello םולש
(I am sorry if I am using something strange or offensive in Hebrew. I just copied the unicode chars from another page, they claim it means "hello").
I've also tried you code in a test app and that is worked well, too.
Also Hebrew-only, English-Hebrew mixtures work well.
However you may prefer to set the RTL orientation to better match to Hebrew, and I guess in my example, the Hebrew letters are displayed in reverse order disregarding to the actual orientation.
Do the following:
check if the JTextField work well in Hebrew? If so, then there is something odd in the path returned by the file selector
check the path by priting it to the console. Locate chars which can cause problems, e.g. \-es, or broken unicode code points
dump the bytes of the string in hexa. This can reveal e.g. unicode byte ordering marks or broken unicode code points.
Question: Trying to get the same effect as the code below only with JTextArea so I want the JTextArea to be read and spelling suggestions to be recommended every time the user types a new misspelt word.
Below is the working example with 'System.in' which works well.
(Vars userField = JTextArea & dic.txt is a list of the english language for the system to use for suggestions)
CODE (1)
public SpellCheckExample() {
try {
SpellDictionary dictionary = new SpellDictionaryHashMap(new File(dic.txt));
spellCheck = new SpellChecker(dictionary);
spellCheck.addSpellCheckListener(this);
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.print("Enter text to spell check: ");
String line = in.readLine();
if (line.length() <= 0)
break;
spellCheck.checkSpelling(new StringWordTokenizer(line));
}
} catch (Exception e) {
e.printStackTrace();
}
}
What I have Been trying:
CODE (2)
public void spellChecker() throws IOException{
String userName = System.getProperty("user.home");
SpellDictionary dictionary = new SpellDictionaryHashMap(new File(userName+"/NetBeansProjects/"+"/project/src/dic.txt"));
SpellChecker spellCheck = new SpellChecker(dictionary);
spellCheck.addSpellCheckListener(this);
try{
StringReader sr = new StringReader(userField.getText());
BufferedReader br = new BufferedReader(sr);
while(true){
String line = br.readLine();
if(line.length()<=0)
break;
spellCheck.checkSpelling(new StringWordTokenizer(line));
}
}catch(IOException e){
e.printStackTrace();
}
}
March 3rd 2016 (Update)
public void spellChecker() throws IOException{
// getting context from my dic.txt file for the suggestions etc.
SpellDictionary dictionary = new SpellDictionaryHashMap(new File("/Users/myname/NetBeansProjects/LifeSaver/src/dic.txt"));
SpellChecker spellCheck = new SpellChecker(dictionary);
// jt = JTextField already defined in constructors and attemtpting to pass this into system and
InputStream is = new ByteArrayInputStream(jt.getText().getBytes(Charset.forName("UTF-8")));
//spellCheck.checkSpelling(new StringWordTokenizer(line)); ""ORIGINAL"""
// reccomending cast to wordfinder
spellCheck.checkSpelling(new StringWordTokenizer(is);
}
You don't want to try to drop console UI code into an event-driven GUI, as it will never work like that. Instead you need to use GUI events to trigger your actions, not readln's.
The first thing you must decide on is which event you wish to use to trigger your spell check. For my money, I'd get the user's input in a JTextField, not a JTextArea since with the former, we can easily trap <enter> key presses by adding an ActionListener on the JTextField. You can always use both, and then once the text is spell checked, move it to the JTextArea, but this is exactly what I'd recommend:
use a JTextField,
add an ActionListener to the JTextField to be notified whenever the field has focus and enter is pressed,
within this listener, extract the text from the JTextField, by calling getText() on the field
Then run your spell check code on extracted text,
and output the result into a nearby JTextArea.
Take a look at Concurrency in Swing for reasons why your current approach won't work, then have a look at Listening for Changes on a Document and Implementing a Document Filter for some possible solutions
As someone is bound to mention it, DON'T use a KeyListener, it's not an appropriate solution for the problem
Put simpler, Swing is a single threaded, event driven framework. So anything you do which blocks the Event Dispatching Thread, will prevent it from processing new events, including paint events, making your UI unresponsive
As an event driven environment, you need to register interested in been notified when some event occurs (this is an example of Observer Pattern) and then take appropriate actions based on those events.
Remember though, you can not make changes to a Document via a DocumentListener, so be careful there
I am new to programming and I would like some tips.
I have a program that reads from a text file using the the following method:
BufferedReader reader = new BufferedReader(new FileReader(file));
.....
This works but the problem is that some lines are long and I can't see all the text in the GUI. How should I tell Java to go to next line if length is equal to a certain amount?
Example text:
A week after Mozart died, his ghost was discovered trying to erase his music. When asked why, it said "I'm decomposing.
Instead of two lines, I want to parse it into four lines. Any help would be appreciated.
as per your comments, you are using JLabel for displaying the data.
to show multi-line text in JLabel just wrap your text in <html> tag like:
JLabel label = new JLabel("<html>your long text here ....</html>");
example:
String theReadLineFromTextFile = ....;
theReadLineFromTextFile = "<html>"+theReadLineFromTextFile+"</html>";
JLabel label = new JLabel(theReadLineFromTextFile);
//or
JLabel label = new JLabel();
label.setText(theReadLineFromTextFile);
If you can't do it in the gui, then some of the answers here will help: Wrap the string after a number of characters word-wise in Java
I'm having trouble trying to get a linebreak included in a Stringbuilder to appear in a JLabel.
I've found a couple of similar problems solved here, e.g. [here] Problems to linebreak with an int in JLabel and [here] How do I append a newline character for all lines except the last one? , along with a few others but none of them seem to work for me.
When printing to System.out, it works fine and I get a new line each time but when passed to a JLabel, everything appears as one line.
Here's the current version of the code, which has attempted to append a newline character, as well as including one in the main declaration. Neither has any effect when passed to the JLabel:
public void layoutCenter() {
JPanel central = new JPanel();
add(central, BorderLayout.CENTER);
JTabbedPane tabs = new JTabbedPane();
this.add(tabs);
// memory tab
StringBuilder mList = new StringBuilder();
memLocList = new Memory[MEM_LOCATIONS]; //Memory is a separate class
for (int i = 0; i < memLocList.length; i++) {
mList.append("\n");
memLocList[i] = null;
mList.append("Memory location: " + i + " " + memLocList[i] + "\n");
}
System.out.println(mList.toString());
JComponent memTab = makeTextPanel(mList.toString());
tabs.addTab("Memory", memTab);
}
protected JComponent makeTextPanel(String text) {
JPanel panel = new JPanel(false);
JLabel filler = new JLabel(text);
panel.add(filler);
return panel;
}
I've also tried using System.getProperty(line.separator) with similar results and can't think of anything else to try so thought I'd appeal for help here.
Thanks,
Robert.
-EDIT-
Thanks to mKorbel, changing the JLabel to a JTextPane solved it.
The two lines in question are:
JTextPane filler = new JTextPane();
filler.setText(text);
Thanks again to everyone.
JLabel isn't designated to held multilines document, there are two choices (by accepting newline or tab by default)
if document could not be decorated or styled somehow then to use JTextArea
in the case document could be decorated or styled somehow then to use JEditorPane or JTextPane
You're going to have to use <html> and <br> to get line breaks in a JLabel Swing component.
If you absolutely must use JLabel, then I suggest using one for each line.
You can make a JLabel have mulitple lines by wrapping the text in HTML tags and using br tags to add a new line.
If you news auto wrapping I suggest using a JTexrArea. You can make it uneditable and style it so it looks like a label.
You can look at this tutorial:
http://docs.oracle.com/javase/tutorial/uiswing/components/html.html
One of the example is using html to make it two lines for a JButton text. It should be very similar.
I am using this code to show text in a JTextArea:
jTextArea1.setText(jTextArea1.getText() + text + "\r\n");
jTextArea1.repaint();
But it shows an exception:
java.lang.NullPointerException
You never instantiated your JTextArea. Also, you might want to check out JTextArea#append.
jTextArea1.setText(jTextArea1.getText() + text + "\r\n");
StringBuilder sb = new StringBuilder();
if(jTextArea1.getText().trim().length() > 0){
sb.append(jTextArea1.getText().trim());
}
sb.append(text).append("\r\n");
jTextArea1.setText(sb.toString());
Above two friends gave you answer.
I want to explain it. Because first times I also met that problem. I solved that, but today solve as above code snippet.
As Jeffrey pointed out, you have to create an object instance before you call non-static methods on it. Otherwise, you will get a NullPointerException. Also note that appending a text to a JTextArea can be done easily by calling its JTextArea.append(String) method. See the following example code for more detail.
package test;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class Main {
public static void main(String[] args) {
Main m = new Main();
m.start();
}
private void start() {
JTextArea ta = new JTextArea();
ta.append("1\n");
ta.append("2\n");
ta.append("3\n");
JFrame f = new JFrame();
f.setSize(320, 200);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(ta);
f.setVisible(true);
}
}
The following code adds text to the text area. Note that the text system uses the '\n' character internally to represent newlines; for details, see the API documentation for DefaultEditorKit.
private final static String newline = "\n";
...
textArea.append(text + newline);
Source