This question already has answers here:
Multiline text in JLabel
(11 answers)
Closed 8 years ago.
I want JLabel text in multiline format otherwise text will be too long. How can we do this in Java?
If you don't mind wrapping your label text in an html tag, the JLabel will automatically word wrap it when its container's width is too narrow to hold it all. For example try adding this to a GUI and then resize the GUI to be too narrow - it will wrap:
new JLabel("<html>This is a really long line that I want to wrap around.</html>");
I recommend creating your own custom component that emulates the JLabel style while wrapping:
import javax.swing.JTextArea;
public class TextNote extends JTextArea {
public TextNote(String text) {
super(text);
setBackground(null);
setEditable(false);
setBorder(null);
setLineWrap(true);
setWrapStyleWord(true);
setFocusable(false);
}
}
Then you just have to call:
new TextNote("Here is multiline content.");
Make sure that you set the amount of rows (textNote.setRows(2)) if you want to pack() to calculate the height of the parent component correctly.
I suggest to use a JTextArea instead of a JLabel
and on your JTextArea you can use the method .setWrapStyleWord(true) to change line at the end of a word.
It is possible to use (basic) CSS in the HTML.
MultiLine Label with auto adjust height.
Wrap text in Label
private void wrapLabelText(JLabel label, String text) {
FontMetrics fm = label.getFontMetrics(label.getFont());
PlainDocument doc = new PlainDocument();
Segment segment = new Segment();
try {
doc.insertString(0, text, null);
} catch (BadLocationException e) {
}
StringBuffer sb = new StringBuffer("<html>");
int noOfLine = 0;
for (int i = 0; i < text.length();) {
try {
doc.getText(i, text.length() - i, segment);
} catch (BadLocationException e) {
throw new Error("Can't get line text");
}
int breakpoint = Utilities.getBreakLocation(segment, fm, 0, this.width - pointerSignWidth - insets.left - insets.right, null, 0);
sb.append(text.substring(i, i + breakpoint));
sb.append("<br/>");
i += breakpoint;
noOfLine++;
}
sb.append("</html>");
label.setText(sb.toString());
labelHeight = noOfLine * fm.getHeight();
setSize();
}
Thanks,
Jignesh Gothadiya
Related
I've been working on project which finds the next occurrence by clicking on button of specific word, but it keeps throwing exceptions ?!
public void highlightnext(JTextComponent textareafield,String pattern) {
textareafield.getHighlighter().removeAllHighlights();
//highlighting
try {
hilit = textarea.getHighlighter();
painter = new DefaultHighlighter.DefaultHighlightPainter(HILIT_COLOR);
Document doc=textarea.getDocument();
String area=doc.getText(0, doc.getLength());
if (pos>area.length())
return;
pos=(area.toUpperCase().indexOf(pattern.toUpperCase(),pos));
pos=(area.toUpperCase().indexOf(pattern.toUpperCase(),pos+1));
hilit.addHighlight(pos,pos+pattern.length(), painter);
System.out.println(pos);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
pos=(area.toUpperCase().indexOf(pattern.toUpperCase(),pos));
pos=(area.toUpperCase().indexOf(pattern.toUpperCase(),pos+1));
Don't convert the data to upper case each time that is not efficient. Convert the text once into a String and then use those two strings in your code.
Not sure why you have two statements. You only need one to do the search.
You need to check the value of "pos" to make sure it is not "-1"
Here is some example code. It finds all occurrences of the text:
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
public class TextAndNewLinesTest extends JFrame
{
public TextAndNewLinesTest()
throws Exception
{
String text =
"one two three four five\r\n" +
"one two three four five\r\n" +
"one two three four five\r\n" +
"one two three four five\r\n" +
"one two three four five\r\n";
JTextPane textPane = new JTextPane();
textPane.setText(text);
JScrollPane scrollPane = new JScrollPane( textPane );
getContentPane().add( scrollPane );
Highlighter.HighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter( Color.cyan );
String search = "three";
int offset = 0;
int length = textPane.getDocument().getLength();
text = textPane.getDocument().getText(0, length);
//text = textPane.getText();
while ((offset = text.indexOf(search, offset)) != -1)
{
try
{
textPane.getHighlighter().addHighlight(offset, offset + 5, painter); // background
offset += search.length();
}
catch(BadLocationException ble) {}
}
}
public static void main(String[] args)
throws Exception
{
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new TextAndNewLinesTest();
frame.setTitle("Text and New Lines - Problem");
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.setSize(400, 120);
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
If you only want to find one occurrence at a time, then basically you would change the "while" statement to an "if" statement.
I tried looking up this question, but most of the answers are that the file path is wrong, but that's most likely not the case. The file works the 1st time I use it.
I am making a battleships game, and use JLabels to show ships on map. I want to make a button to rotate ship from horizontal to vertical but it's icon disappears when I try to change it.
When I run this constructor code:
public Ship(int size, String direction, boolean active, Client c,
ClientGUI cg) {
this.c = c;
this.cg = cg;
health = size;
this.active = active;
this.direction = direction;
file = "img/" + Integer.toString(health) + direction + ".png"; // String
try {
System.out.println(file);
tx = ImageIO.read(new File(file)); // BufferedImage
} catch (IOException e) {
e.printStackTrace();
}
texture = new JLabel(new ImageIcon(tx));
if (direction.equals("v"))
texture.setBounds(0, 0, 40, 40 * size);
else
texture.setBounds(0, 0, 40 * size, 40);
texture.setVisible(true);
}
everything works and I can see the image.
But then I try to rotate it, using pretty much the same code:
void rotate() {
if (direction.equals("h")) {
direction = "v";
file = "img/" + Integer.toString(health) + direction + ".png";
try {
System.out.println(file);
tx = ImageIO.read(new File(file));
} catch (IOException e) {
e.printStackTrace();
}
texture.setBounds(0,0,40, 40 * size);
texture.setIcon(new ImageIcon(tx));
} else {
direction = "h";
file = "img/" + Integer.toString(health) + direction + ".png";
try {
System.out.println(file);
tx = ImageIO.read(new File(file));
} catch (IOException e) {
e.printStackTrace();
}
texture.setIcon(new ImageIcon(tx));
texture.setBounds(0,0,40 * size, 40);
}
cg.repaint(); // not sure if I need to do this
}
and it disappears...
I tried placing two ships, one is rotated, it's just missing the JLabel or the icon on JLabel.
If you update the JLabel texture by calling a method which changes it's state, it may or may not be updated immediately unless you call texture.repaint() or texture.paintAll(texture.getGraphics()), or some similar method.
Also, I would look into using a LayoutManager for whatever upper level component you are using to hold your grid of JLabels. If you use a GridLayout of your game board and either:
set the JLabel's preferred size with texture.setPreferredSize(Dimension) and call frame.pack() once when setting up your game; or
set the JLabel's size with label.setSize(Dimension) once and don't pack your JFrame
You will only need to set the size of the JLabel once, not every time you set a new ImageIcon to the label. Because, Ideally your game shouldn't be doing any extra work that it doesn't have to so it performs faster.
I would also recommend maintaining every possible ImageIcon as static fields in your class, rather than accessing them from the file every time. That way, you read them once from a static initializing method, which then reach ship can directly access when changing the direction.
I want to make a button to rotate ship from horizontal to vertical
You can use the Rotated Icon class to do the rotation for you.
I have a JTextArea in which i want to display messages aligned to right or left, depending on a variable I pass along with the message. Can I do that?
What did I do wrong? Nothing gers added to the text pane when i run my GUI
battleLog = new JTextPane();
StyledDocument bL = battleLog.getStyledDocument();
SimpleAttributeSet r = new SimpleAttributeSet();
StyleConstants.setAlignment(r, StyleConstants.ALIGN_RIGHT);
try {
bL.insertString(bL.getLength(), "test", r);
} catch (BadLocationException e1) {
e1.printStackTrace();
}
Not with a JTextArea.
You need to use a JTextPane which supports different text and paragraph attributes. An example to CENTER the text:
JTextPane textPane = new JTextPane();
textPane.setText("Line1");
StyledDocument doc = textPane.getStyledDocument();
// Define the attribute you want for the line of text
SimpleAttributeSet center = new SimpleAttributeSet();
StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER);
// Add some text to the end of the Document
try
{
int length = doc.getLength();
doc.insertString(doc.getLength(), "\ntest", null);
doc.setParagraphAttributes(length+1, 1, center, false);
}
catch(Exception e) { System.out.println(e);}
if("left".equals(input)){
setAlignmentX(Component.LEFT_ALIGNMENT);
}
Have a try!
Pretty straightforward issue. My Java AWT (not Swing) label is simply not showing up. Most of the following code isn't even being used (for debugging this issue).
Just a note: this is within a Frame's constructor (and yes I have added several other panels and such that work just fine). Secondly, the frame's layout has been set to null.
I'm stumped.
File inf = new File("instructions.txt");
Label ilb;
if(inf.exists())
{
Log.v("Loading instructions");
try
{
FileInputStream fis = new FileInputStream(inf);
byte[] insb = new byte[65535];
fis.read(insb);
fis.close();
String inst = new String(insb);
ilb = new Label("test", Label.LEFT);
File fntfile = new File("font/pf_tempesta_seven.ttf");
Font infnt = null;
try {
FileInputStream ffis = new FileInputStream(fntfile);
infnt = Font.createFont(Font.TRUETYPE_FONT, ffis);
ffis.close();
} catch (FontFormatException e) {
Log.e("Could not format LCD font!", e);
} catch (IOException e) {
Log.e("Could not read LCD font file!", e);
}
if(infnt == null)
infnt = new Font("Trebuchet MS", Font.PLAIN, 8);
else
infnt = infnt.deriveFont(8.0f);
//ilb.setFont(infnt);
//ilb.setForeground(new Color(123, 123, 123));
//ilb.setPreferredSize(new Dimension(350, 400));
//ilb.setSize(350, 400);
//ilb.setLocation(580, 190);
Log.d("adding label");
add(ilb);
} catch(IOException e) {
Log.e("Could not read instructions!", e);
}
}else
Log.w("Instructions file not found!");
1) for todays GUI use Swing JComponents (starts with J) rather than prehistoric AWT Label
2) for your issue could be better use JTextArea with method append()
3) you have got issues with Concurency (in Swing) AWT / Swing is single threaded and all output to the GUI must be wrapped into invokeLater
4) for better help sooner you have edit your question with SSCCE
As #JBNizet suggested, null layouts don't work with all AWT components.
I was thrown off since my Panels were positioned just fine with a null layout on my Frame, whereas Labels require a basic layout in order to display. I was tempted to go as far as saying all other components had the same 'feature', but another part of my code proved that point wrong:
// Load Image
Log.v("Loading header image");
_iBG = new ImageIcon("img/hpcount_top_bg.png").getImage();
// Set size
setSize(1024, 152);
setPreferredSize(new Dimension(1024, 152));
// Set position
setLocation(0, 0);
// Set visible
setVisible(true);
// Set layout
setLayout(null);
// Add children
add(new Exit()); // Exit extends java.awt.Button
The above code (which is located within the constructor of a class extending java.awt.Panel) works perfectly.
My workaround is to put the label inside another Panel with a layout (messy, but it works) and position that panel within the Frame absolutely to achieve the same effect.
Is it possible to create one jxl.WritableCellFormat attribute which contains Font, NumberFormat, BackgroundColor and Border?
This works:
public static final NumberFormat numberformatter = new NumberFormat("#,###0.00");
public static final WritableFont defaultfont = new WritableFont(WritableFont.TAHOMA, 10);
public static final WritableCellFormat numberCellFormat = new WritableCellFormat(defaultfont, numberformatter); '
but I can't get borders and colors, thought same kind of cell is needed many times when creating sheets.
You can set the border and background via the WritableCellFormat.setBorder() and WritableCellFormat.setBackground() methods after having instanciated your cell.
You can see the API there.
If you have to do that a lot, you can make a helper function like this :
public static makeCell(NumberFormat format, WritableFont font, Color backgrd, Border border){
final WritableCellFormat result = new WritableCellFormat(defaultfont, numberformatter);
result.setBorder(border);
result.setBackground(backgrd);
return result;
}
You Can do this by 2 steps
Create a WritableFont
Create a WritableCellFormat with WritableFont,NumberFormats as a parameter
Attaching the code snippet
int fontSize = 8;
WritableFont wfontStatus = new WritableFont(WritableFont.ARIAL, fontSize);
wfontStatus.setColour(Colour.BLACK);
wfontStatus.setBoldStyle(WritableFont.BOLD);
WritableCellFormat fCellstatus = new WritableCellFormat(wfontStatus, NumberFormats.TEXT); // You can use any NumberFormats I have used TEXT for my requirement
try {
fCellstatus.setWrap(true);
fCellstatus.setBorder(Border.ALL,BorderLineStyle.THIN);
fCellstatus.setAlignment(Alignment.CENTRE);
fCellstatus.setBackground(Colour.YELLOW);
}
catch (WriteException e) {
e.printStackTrace();
}