adding the same actor multiple times to a table - libgdx

I am using this code to place an actor multiple times horizontally in a table. When I run the code, only 1 appears. Why and how do I get around this?
private void createUI(){
texture=new Texture("1.png");
ImageButton.ImageButtonStyle fibs=new ImageButton.ImageButtonStyle();
fibs.imageUp=new TextureRegionDrawable(new TextureRegion(texture));
button1= new ImageButton(fibs);
button1.setBounds(0f, 0f, texture.getWidth(), texture.getHeight());
button1.setPosition(0, 0);
scrollTable=new Table();
scrollTable.setBounds(0,0,Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
scrollTable.setPosition(0,50);
scrollTable.add(button1);
scrollTable.add(button1);
scrollTable.add(button1);
stage.addActor(scrollTable);
}

An actor contains information about how and where it should be rendered as well as what should happen when you click on it etc. Therefor you can't add the same actor multiple times to the stage. If you want to have more than one button then create more than one button.

Related

How to draw timelines in a tree table

I am writing an analyzer to visually see where my application is spending time. The interface that I am trying to achieve (see below) is something similar to a tree table with
lines or boxes to denote response time.
be a collapsible tree like graph
the ability to display metrics in the table columns (e.g., start time, cost, etc)
the ability to display the labels or description and metrics on the left and lines on the right
I create the following diagram (see below) in R -- unfortunately, although the graph production is automated, the approach is not interactive. I was wondering if you could suggest a better way -- maybe a tree table. I looked at many Swing, JavaFx tree table examples. I have not seen an example that has lines (time lines) in a tree table.
Any suggestions would be greatly appreciated. Thanks in advance.
You can show any node in a TreeTableCell using the grahic property in javaFX. This includes Rectangles.
This is a simple example of showing bars in a column using Rectangles:
// Arrays in TreeItems contain {startValue, endValue} (both positive)
TreeItem<int[]> root = new TreeItem<>(new int[]{0, 10});
root.getChildren().addAll(new TreeItem<>(new int[]{0, 5}), new TreeItem<>(new int[]{5, 10}));
TreeTableView<int[]> ttv = new TreeTableView<>(root);
// Column displaying bars based on data of TreeItem. Do not use this as
// the first column, otherwise the alignment be off depending on the
// distance to the root.
TreeTableColumn<int[], int[]> column = new TreeTableColumn<>();
column.setCellValueFactory(c -> c.getValue().valueProperty());
final double BAR_SIZE = 20;
column.setCellFactory((t) -> new TreeTableCell<int[], int[]>() {
// the bar
private final Rectangle rectangle = new Rectangle(0, 10);
{
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
// bar invisible by default
rectangle.setVisible(false);
setGraphic(rectangle);
}
#Override
protected void updateItem(int[] item, boolean empty) {
super.updateItem(item, empty);
if (!empty && item != null) {
// resize and display bar, it item is present
rectangle.setWidth((item[1] - item[0]) * BAR_SIZE);
rectangle.setTranslateX(item[0] * BAR_SIZE);
rectangle.setVisible(true);
} else {
// no item -> hide bar
rectangle.setVisible(false);
}
}
});
// add a columns new column
// add a additional empty column at the start to prevent bars being
// aligned based on distance to the root
ttv.getColumns().addAll(new TreeTableColumn<>(), column);
Things you need to do
use a data type different to int[]; the cell value factory and TreeTableCell needs to be adjusted accordingly; an example of a more complex model can be found e.g. in the oracle tutorial: https://docs.oracle.com/javase/8/javafx/user-interface-tutorial/tree-table-view.htm
Choose better colors; These colors could e.g. be stored in a Map and created if a new one is needed.
add additional colums

Libgdx create sequence action programmatically

In my libGDX application I have an actor which needs to create actions programmatically.
At the minute I am adding moveBy actions with incrementing delays in order to get the desired effect but this is very inefficient. Something like below;
actor.addAction(sequence(delay(i * DELAY), moveBy(50, 50));
If possible I would like to programmatically create one single sequence action and add moveBy actions to it as needed. Then I could just invoke a single action without having to continually add actions which is very unresourceful.
I have checked the documentation and could not find anything specific to my particular need.
I was thinking something along the lines of (pseudo code);
addPath(Vector2 path) {
paths.add(path);
}
invokePathAction() {
Action sequence = sequence();
for all paths
sequence.add(moveBy(path.x, path.y, TIME));
addAction(sequence);
}
Is something like this possible with libGDX?
Of course - there is addAction method in the SequenceAction class
MoveToAction action1 = new MoveToAction();
action1.setPosition(0, 0);
action1.setDuration(2);
MoveToAction action2 = new MoveToAction();
action2.setPosition(-500, 0);
action2.setDuration(2);
...
SequenceAction sequence = new SequenceAction();
sequence.addAction(action1);
sequence.addAction(action2);
...
actor.addAction(sequence);
if you want to clear all actions and have "empty" sequence again you can call
sequence.reset();

CCPhysicsjoint not keeping the 2 bodies intact

I want to add a particle body(say Fire) before another physics body(the arrow).
So, i am using the spring joint to keep them joined with stiffness around 20000, but still its starting the correct way and the particle-body swings away form the arrow. Here's my code:
fire part
CCParticleSystem *explosion= [CCParticleSystem particleWithFile:#"bomb.plist"];
explosion.position = ccpAdd(projectilePos, ccp(16,0));
explosion.physicsBody.mass=1.0;
explosion.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:16.0 andCenter:explosion.anchorPointInPoints];
explosion.physicsBody.type=CCPhysicsBodyTypeDynamic;
explosion.physicsBody.affectedByGravity=FALSE;
explosion.physicsBody.allowsRotation=FALSE; //so that fire flames go upwards only, and not rotate
[physicsWorld addChild:explosion];
explosion.physicsBody.collisionMask=#[];
arrow part
CCSprite *tempSprite;
tempSprite = [CCSprite spriteWithImageNamed:#"arrow3#2x.png"];
[tempSprite setScale:0.05];
[tempSprite setScaleY:0.15];
tempSprite.rotation=rotation;
tempSprite.position=dummyBow.position;
tempSprite.name=[NSString stringWithFormat:#"%#,%d",[lifeOfSprite[1] objectForKey:#"name"],[[lifeOfSprite[1] objectForKey:#"life"] intValue]];
tempSprite.physicsBody = [CCPhysicsBody bodyWithRect:(CGRect){CGPointZero, tempSprite.contentSize} cornerRadius:0]; // 1
tempSprite.physicsBody.collisionGroup = #"playerGroup";
tempSprite.physicsBody.collisionType = #"projectileCollision";
[physicsWorld addChild:tempSprite z:0];
projectile.physicsBody.mass=100;
now the joint part
[CCPhysicsJoint connectedSpringJointWithBodyA:playerBomb.physicsBody bodyB:projectile.physicsBody anchorA:ccp(1,1) anchorB:ccp(600,0) restLength:0.f stiffness:20000.f damping:60.f];
(debugDraw)
the fire should come at the front, but swings back from front by spring effect
Can anyone tell where's the problem?
Thanks in advance.

Displaying more text with one Text Input

Is it possible to display more than one text with TextField like so:
Susan 50
Bob 100
Michael 30
This is meant for leaderboard
Regards
I'd say for such a leaderboard you need two TextFields one adjacent to another, with identical defaultTextFormat properties, both set with multiline=true; wordwrap=false, and fill left one with names, and right one with scores. This way you can avoid the need of uniform-width fonts. An example:
public class Leaderboard extends Sprite {
var namesTF:TextField;
var scoresTF:TextField;
var dtf:TextFormat;
...
// this goes into the constructor
dtf=new TextFormat(...);
namesTF.defaultTextFormat=dtf;
scoresTF.defaultTextFormat=dtf;
...
public function displayScores(scores:Array):void {
// scores are objects like {name:Susan,score=200}
scores.sortOn("score",Array.NUMERIC+Array.DESCENDING);
namesTF.text='';
scores.text='';
for each (var o:Object in scores) {
namesTF.appendText(o.name+'\n');
scoresTF.appendText(o.score.toString()+'\n');
}
}
}
Adjust the interface to the means your scores are recorded.

Show "no rows found" inside a JTable row if not found entry while filtering

i have a JTable with row filter.
once fitered if i didn't get any row then i have to show a string like "Nothing found to display " inside table as first row.
please do needful.
Thanks ,
Narasimha
I needed to solve this exact problem today and wasn't able to find a good answer online. In the end I came up with my own solution, which I think may be exactly what you want. I don't know if this is too late for your project, but perhaps it can help others:
JTable.paintComponent(Graphics g) will not be called unless the table has a height that is greater than 0. This causes a problem for empty tables, so we expand the JTable height if needed so that it will always be at least the size of the JViewport that is it's parent.
JTable tableName = new JTable() {
public boolean getScrollableTracksViewportHeight() {
if(getParent() instanceof JViewport)
return(((JViewport)getParent()).getHeight() > getPreferredSize().height);
return super.getScrollableTracksViewportHeight();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(getRowCount() == 0) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
g2d.drawString("Nothing found to display.",10,20);
}
}
}
containerName.add(new JScrollPane(tableName));
To show a line of text in the multicolumn table can be quite difficult, the span AFAIK is not supported.
One possibility would be to hide all data columns (to show them later you have to memorize them somewhere) and show one column for the message.
An easier way would be to create a JPanel with CardLayout, add 2 cards - one containing table and one containing your empty data warning. If the filter returns empty result, show the card with empty warning, in other case - show the table.
If the filter has excluded all rows, the result returned by getViewRowCount() will be zero. You can update the GUI accordingly; setToolTipText() is handy if screen space is lacking.
Here's an example:
TableModel model = ...
JTable table = new JTable(model);
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);
JScrollPane pane = new JScrollPane(table);
JLabel label = new JLabel("");
...
String s = "Rows: " + sorter.getViewRowCount()
pane.setToolTipText(s);
label.setText(s);