Using SWT and Java, I have a Text widget defined which is set for multi-line and wrap properties. I added a listener which will monitor any changes to the text inside this text widget, and I want the height of the widget to automatically change if the user adds a new line of text, or if the text wraps around to the next line. So, I want all of the text visible in the text widget if the user adds new text, or deletes text. Here's a sample of what I'm trying to do:
mTextValue = new Text(compositeEditor, SWT.BORDER | SWT.WRAP | SWT.MULTI);
mTextValue.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
mTextValue.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
mTextValue.addListener(SWT.Modify,new Listener()
{
protected int lines=1;
public void handleEvent(Event e)
{
Text text = (Text) e.widget;
int newlines = text.getLineCount();
if (newlines!=lines)
{
lines=newlines;
height = lines*16;
width = 240;
text.setSize(width,height);
text.getShell().pack(true);
}
}
});
Now, this seems to work ok if I add a single line of text and press the return key to add the next line. The text widget grows in height when I add lines of text, and shrinks in height when I remove lines. Just as I want. But, when I have text that wraps around and I try to add a new line, the text widget is resized in width also. I want to keep the width fixed, and only self adjust the height.
Can anyone offer a suggestion to how I can have the text widget self adjust its height to fit all of the entered text, but keep the width of the text widget always fixed at a prescribed value?
Thanks.
It may be because pack() re-computes the preferred size. I don't see any direct way to set the prefered width to constant. But you may try overriding computeSize method so that you pass fixed width as hint to super class.
i.e
public Point computeSize(int wHint,
int hHint,
boolean changed)
{
return super.computeSize(240, hHint, changed);
}
Related
I am using Java JDK 1.6 and have a problem using JTextPane to show text with a monospaced font. As soon as I add a UTF8-character like 😂, the line height in the textpane is reduced (for all the text already in the pane and also all text added later). How can I avoid this? I would like to have the normal line height.
Here is some sample code:
class AttributedTextPane extends JTextPane
{
private DefaultStyledDocument defaultStyledDocument;
protected AttributedTextPane()
{
this.defaultStyledDocument = new DefaultStyledDocument();
this.setDocument(defaultStyledDocument);
this.setContentType("text/plain");
...
}
}
...
This pane is integrated into an JInternalFrame. Creating the panel and setting the desired monospaced font:
Font font = new Font("DejaVu Sans Mono", Font.PLAIN, 11);
AttributedTextPane pane = new AttributedTextPane();
pane.setFont(font);
To display the desired text, I call pane.setText(...); As soon as I add the UTF8 character, the line height changes, see screenshot at http://i.imgur.com/Fq7XBJB.png. Is there a way to avoid that the line height is changed?
Thanks, Deejay
You could try setting/forcing a line height like so:
MutableAttributeSet jTextPaneSet = new SimpleAttributeSet(pane.getParagraphAttributes());
StyleConstants.setLineSpacing(jTextPaneSet, 1.5f); //replace float 1.5f with your desired line spacing/height
Source:
http://docs.oracle.com/javase/8/docs/api/javax/swing/JTextPane.html#setParagraphAttributes(javax.swing.text.AttributeSet,%20boolean)
https://docs.oracle.com/javase/7/docs/api/javax/swing/text/StyleConstants.html#setLineSpacing(javax.swing.text.MutableAttributeSet,%20float)
Old question but I have been struggling with it for some time, though with a JTextArea. The solution is to have either a VM param -Di18n=true or put the i18n property in the document.
My test code:
import javax.swing.JTextArea;
public class Test {
public static void main(String[] argv) {
JTextArea ta = new JTextArea();
//ta.getDocument().putProperty("i18n", Boolean.TRUE);
ta.setText("A");
System.out.println(ta.getPreferredSize()); // - height 16 without i18n and using default font, 15 with i18n
ta.setText("\ud8ff\udc05"); // surrogate pair
System.out.println(ta.getPreferredSize()); // - height 15
ta.setText("A");
System.out.println(ta.getPreferredSize()); // - height 15
}
}
When i18n is not enabled and the document is appended, the elements that are created are PlainView/WrappedPlainView that return the height based on the FontMetrics height.
When i18n is enabled the elements are PlainParagraph that contain GlyphView that calculates the height differently.
When i18n is not enabled and the document is appended with a surrogate pair then due to SwingUtilities2.isComplexLayout returning true, the i18n property is automatically set to true for the document and then all elements are created as PlainParagraph containing GlyphView that return the different (always smaller?) height.
i have done a small test on LibGdx, on Multi-line Label, it seems that i cant get the wrapped line's height. Following is the code. Theoretically, height for aLebel should be > bLabel. But the result appear the same.
code:
aLabel.setText("this is a super long long long text that need wrapping."); // line wrapped into 3 lines
aLabel.setWrap(true);
aLabel.setWidth(470);
doLog("aLabel.getHeight(): " + aLabel.getHeight());
bLabel.setText("this is short."); // unwrapped line
bLabel.setWrap(true);
bLabel.setWidth(470);
doLog("bLabel.getHeight(): " + bLabel.getHeight());
result:
aLabel.getHeight(): 45.0
bLabel.getHeight(): 45.0
Do anyone have any idea how to get the actual multi-line height in LibGdx? Thanks in advance.
I had this issue for years and accidentally solved it by setting the width and packing the label twice. Note that multiline labels were never intended to figure out their own width, so you have to set them externally, preferably from it's parent.
public Label createLabel() {
// Create label and set wrap
Label label = new Label("Some long string here...", skin);
label.setWrap(true);
// Pack label
label.pack(); // This might not be necessary, unless you're changing other attributes such as font scale.
// Manual sizing
label.setWidth(textWidth); // Set the width directly
label.pack(); // Label calculates it's height here, but resets width to 0 (bug?)
label.setWidth(textWidth); // Set width again
return label;
}
LibGDX version used: 1.6.4
Pack sizes the widget to its pref size, nothing more. Pref width of a label with wrapping is 0.
Label label = new Label(...);
label.setWrap(true);
label.setWidth(123);
label.setHeight(label.getPrefHeight());
I had the same issue and it seems there doesn't exist a method in Label class to solve this. Also, I agree with you, the getHeight() method should return the real height of the Actor, so I don't know if that's a bug or there is a reasoning behind that behaviour.
Anyways, how I solved the issue is by using BitmapFont's getWrappedBounds method. It's not short, but for your example it would be the following:
doLog("aLabel.getHeight(): " + aLabel.getStyle().font.getWrappedBounds(aLabel.getText(), aLabel.getWidth()).height);
This could be done by adding a restriction to the cell that contains the Label in the Table:
Label label = new Label("Example", new Label.LabelStyle(font, Color.WHITE));
label.setWrap(true);
Table table = new Table();
table.add(label).width(WITH);
For more information about how to use Table go to: https://github.com/libgdx/libgdx/wiki/Table
I have a Label component which can contain a very long text. Label support wrapping:
Label label = new Label( composite, SWT.WRAP | SWT.LEFT );
So when I decrease the width of the parent Composite - just resize it with mouse - the text is wrapped correctly, but the height of the parent Composite is not changed so some part of my Label get hidden.
I tried to add a resize listener to parent composite:
expandBar.addListener( SWT.Resize, new Listener() {
public void handleEvent( Event e ) {
Point p = label.computeSize( SWT.DEFAULT, SWT.DEFAULT ) // compute size of the text
int h = p.y; // ! THIS value doesn't change
// despite text in label became wrapped
// now set expandBar current item's height = h;
}
} );
Is there a way to compute the height of the component with regards to wrapping?
If no, are there SWT components/layouts which change its size dynamically if the child is getting wrapped?
In my application i have 2 types of editfields. One of them behaves like single line editfield, the other behaves like multi-line editfield (editarea). In this screen i have one header, one editfield and one editarea. When i enter some text to editfield, it clips the text and cursor. But, when i enter some text to editarea which includes a tailed character(y,g,q,p) editareas height is changing and editfieldact normal. If i dont enter tailed characters stuation does not change.
Here is my editarea class:
public class EditAreaField extends HorizontalFieldManager{
private net.rim.device.api.ui.component.EditField editArea;
public EditAreaField (){
// some code;
editArea.setPadding(25, 10, 0, 10);
}
public int getPreferredHeight() {
int height = Math.max(editArea.getHeight(), textFont.getHeight());
return height + editArea.getPaddingTop();
}
}
label1 -> editfield
label2 -> editarea
this is because you are making the size to change by using
int height = Math.max(editArea.getHeight(), textFont.getHeight());
instead of this try to give some fixed height. for example
height= Graphics.getScreenHeight()/5;
or you can also use setExtent inside the sublayout method of the manager
protected void sublayout(int maxWidth, int maxHeight)
{
layoutChild(_editField, _editField.getPreferredWidth(), _editField.getPreferredHeight());
setPositionChild(_editField, xpos,ypos);
setExtent(preferredHeight,preferredWidth);
}
I think it will work.
Please let me know
About the cursor painting - you did override drawFocus or/and onFocus or/and onUnfocus and don't repaint properly sometime.
See subject title.
I have a method in Java that draws a TextBlock element:
public void drawTextBlock(String text) {
Element textBlock = new Element("TextBlock", Ns.getDefaultNamespace());
textBlock.setAttribute(new Attribute("Text", text));
}
However, the Width of the TextBlock must be exactly as wide as the width of the text I give to it.
How would this be done?
You don't need to set the width. Unless the HorizontalAlignment is Stretch (which is the default) The width of a TextBlock automatically adjusts to the size of the text it contains (as long as there is enough space to contain the TextBlock of course). So you just need to set the HorizontalAlignment to Left, Right or Center