I'm trying to set an text to text area and to scroll it to bottom, and the following code seems to not work..
TextArea logTextArea = new TextArea();
logTextArea.setValue(result , true, true);
final int scrollHeight = logTextArea.getElement().getFirstChildElement().getScrollHeight();
logTextArea.getElement().getFirstChildElement().setScrollTop(scrollHeight);
Tried also another examples with setCursorPos(), also not working. What is wrong with this example?
Related
So, I dont know if I am missing something but any way I work it or look into it I am unable to click on any buttons on the screens.
I made a dialog box with a button essentially as shown in the sample projects but when ever I try to click the button nothing happens at all.
I tried firing the onClick programmatically and it works fine, I also tested that the mouse inputs were being registered okay and they were.
I am at a total loss for any reason why this wouldnt work.
My class code is below:
public class Interactable : UICanvas
{
public void interact()
{
var skin = Skin.createDefaultSkin();
var table = stage.addElement(new Table());
table.center();
table.setFillParent(true);
table.add(talk(this.entity.name, "Stay a while and glisten", "Bye!"));
}
public Dialog talk(string title, string messageText, string closeButtonText)
{
var skin = Skin.createDefaultSkin();
var style = new WindowStyle
{
background = new PrimitiveDrawable(new Color(50, 50, 50)),
//Dims the background
stageBackground = new PrimitiveDrawable(new Color(0, 0, 0, 150))
};
var dialog = new Dialog(title, style);
dialog.getTitleLabel().getStyle().background = new PrimitiveDrawable(new Color(55, 100, 100));
dialog.pad(20, 5, 5, 5);
dialog.addText(messageText);
var exitButton = new TextButton(closeButtonText, skin);
exitButton.onClicked += butt => dialog.hide();
dialog.add(exitButton);
return dialog;
}
}
}
The interact() is called when running up to another entity and pressing "E".
Which causes everything to render properly but I can't click on the button.
Additionally:
When i try to view exitButton co-ordinates theyre always 0 no matter what although the dialog appears in the middle of the window
Monogame version: 3.7
Nez version: 0.9.2
UPDATE:
So it seems like buttons are clickable but their click box is not even nearly aligning with where the buttons are truely rendered.
UPDATE2:
It seems that the issue is that where the button is being rendered and where the actual click box is are not the same.
I have Zoomed in the camera by 2 and the camera also follows my little character around. The dialog will then appear at the X,Y in relation to the current camera view but the actual click box appears at the X,Y in terms of the TiledMap (which is not always on screen).
Not too sure how to work around this.
So! The issue I was having was I was using one renderer for the entire this (The RenderLayerRenderer.) What I have done to fix this is start another renderer (A ScreenSpaceRenderer). This allows me to use it to render UI and its XY variables do not change but are just static to the visual area.
So i ended up with two renders like so:
addRenderer(new RenderLayerRenderer(0,new int[] { (int)RenderLayerIds.First, (int)RenderLayerIds.Second, (int)RenderLayerIds.Third}));
addRenderer(new ScreenSpaceRenderer(1, new int[] { (int)RenderLayerIds.UILayer }));
Using the first for my game rendering and the bottom on just for HUD things!
This is the piece of my code.
textArea.setText(someNewText)
textArea.positionCaret(textArea.getText().length());
textArea.setEditable(true);
textArea.setScrollTop(Double.MAX_VALUE);
I use textArea.setScrollTop(Double.MAX_VALUE) to scroll textarea to the bottom (solution I found in internet). It works, but not always. I've noted that it can not work only when vertical scroll bar is not visible before calling this code and visible after the code was executed. When vertical scroll bar is visible before calling this code then scrolling to the bottom works always. How to fix it? Maybe I should make vertical scroll bar always visible? If yes, then how - I didn't find the solution.
EDIT:
This is the sample code:
public class JavaFxApp1 extends Application{
private TextArea textArea;
#Override
public void start(Stage stage) throws Exception {
Button button=new Button("Press here");
textArea=new TextArea();
VBox vbox = new VBox(button,textArea);
button.setOnAction((event)->{
textArea.appendText("###This is a very long string:some text some text some text some text some"
+ " text some text some text some text some text some text"
+ " text some text some text some text some text some text"
+ " text some text some text some text some text some text .\n");
textArea.selectEnd();
textArea.deselect();
textArea.setScrollTop(Double.MAX_VALUE);
});
textArea.setEditable(true);
textArea.setWrapText(true);
textArea.setStyle("-fx-font-size:14px;-fx-focus-color: transparent;-fx-font-family: monospace;");
Scene scene=new Scene(vbox);
stage.setTitle("SomeTitle");
stage.setScene(scene);
stage.setMinHeight(400);
stage.setMinWidth(800);
stage.show();
}
}
This is the result when I pressed button 4 times:
As you see it didn't scroll to the bottom. After I press button again (the fifth time) I have the following result:
Now, as you see it was scrolled to the bottom.
I tried to add:
ScrollPane scrollPane = (ScrollPane) textArea.lookup(".scroll-pane");
scrollPane.setVbarPolicy(ScrollBarPolicy.ALWAYS);
to make scrollbar visible always - it is visible but after 4 times anyway doesn't scroll to the bottom.
How to fix it?
if you want to scroll to the Top your code will be this way
ta.selectHome();
ta.deselect();
if you want to scroll to the Bottom your code will be this way
ta.selectEnd();
ta.deselect();
now let the TextArea worry about its visible areas
edit
maybe i didnt get your requirement, cause honestly this is the first time i have seen that method so to give an answer based on your hypothesis
Maybe I should make vertical scroll bar always visible? If yes, then how
well thats easy TextArea uses ScrollPane, when there is a visible scroll
this line TextArea.getChildrenUnmodifiable().size(); will check out to be 1, so you fish it out when you create your TextArea
TextArea.getChildrenUnmodifiable().addListener(new ListChangeListener<Node>() {
#Override
public void onChanged(javafx.collections.ListChangeListener.
Change<? extends Node> c) {
while(c.next()){
if(c.wasAdded()){
for(Node n : TextArea.getChildrenUnmodifiable()){
if(n.getClass().isAssignableFrom(ScrollPane.class)){
//just trying to be cool here ^^
ScrollPane sp = (ScrollPane) n;
sp.setVbarPolicy(ScrollBarPolicy.ALWAYS);
}
}
}
}
}
});
actually you can keep a reference to the ScrollPane and anytime you want to scroll to the bottom ScrollPane.setVvalue(1.0); to the top ScrollPane.setVvalue(0.0); etc etc.
you can get the value with ScrollPane.getVvalue().
This is a bug. See the following link https://bugs.openjdk.java.net/browse/JDK-8189732
When I was append some text dynamically to the TextArea it was wrapped correctly as follow:
But due to requirement changed I have to add some image as bullet for (in front of the) each text. Then I used GridPane to add those text with images as follow:
Code used to add components to GridPane:
// Set the GridPane empty
gridPane.getChildren().removeAll();
// Add image with each text
int index = 0;
for(String des : descriptionsList) {
HBox btnHb = new HBox();
ImageView passed = new ImageView();
passed.setImage(new Image(getClass().getResourceAsStream(GuiConstant.Image.IMAGE_PASSED)));
btnHb.getChildren().add(passed);
Text text = new Text(des);
btnHb.getChildren().add(text);
gridPane.addRow(index, btnHb);
index++;
}
Now (with GridPane) added Texts are not wrapped properly. How can I fix this issue. Thanks.
You need to set the wrappingWidth on the Text instances to be relative to the width of the GridPane. You may want to do that indirectly via the HBox instances:
btnHub.prefWidthProperty().bind(gridPane.widthProperty();
text.wrappingWidthProperty().bind(btnHub.widthProperty().subtract(passed.widthProperty().subtract(10));
I didn't actually try these changes, but they (or something very similar) should do the trick.
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 JTable inside of a JScrollPane. I am creating a custom cell editor for one of the columns of the table, and I want this editor to pop up a scrolling JList. I've done this by using a Popup to show a new JScrollPane containing the JList.
Everything is working, except for the position of the Popup. My custom component for the editor looks basically like this:
public class CustomPanel extends JPanel {
JTextField text = new JTextField();
JList list = new JList();
JScrollPane scroll = new JScrollPane(list);
Component owner = null;
public CustomPanel(Component owner) {
this.owner = owner;
add(text);
}
public void showPopup() {
Popup p = PopupFactory.getPopup(owner, scroll, getX(), getY()+getHeight());
p.show();
}
}
What is happening is that getX() and getY() are returning the position of the table cell relative to the JScrollPane holding it, and Popup is wanting absolute screen position. Even if I pass in owner the JScrollPane that they are relative to, it doesn't work. I get the same problem if I use text.getX() / text.getY().
How can I position my Popup directly below the TextBox?
Just a bit more background: The end goal is a multiple-select combobox that displays all of the selected items as a comma-separated list. If something else like this already exists, please don't hesitate to point me to it.
Edit: owner.getLocationOnScreen().y + getY() doesn't work when the scroll pane is anywhere but scrolled all the way up. However, just plain getLocationOnScreen().y DOES work. Problem solved, thank you.
You can query the absolute screen position with Component.getLocationOnScreen(). Is that what you're looking for?