I'm using GridPane for my JavaFX layout, and I always use width percentages for ColumnConstraints, but in one specific case it seems it does not work: when I set the width percentage of a ColumnConstraints inside an array.
My code:
ColumnConstraints[] myColumns = Factory.createColumns(3);
myColumns[0].setPercentWidth(35);
myColumns[1].setPercentWidth(12);
myColumns[2].setPercentWidth(53);
devicePane.getColumnConstraints().setAll(myColumns);
The array comes from my utility method for column creation using equally divided sizes:
public static final ColumnConstraints[] createColumns(int count) {
ColumnConstraints[] columns = new ColumnConstraints[count];
ColumnConstraints column = new ColumnConstraints(1, 10, Double.MAX_VALUE);
column.setPercentWidth(100/count);
column.setFillWidth(true);
column.setHgrow(Priority.ALWAYS);
column.setHalignment(HPos.CENTER);
for(int i = 0; i < count; i++) {
columns[i] = column;
}
return columns;
}
Result:
Columns with old width percentage
But the expected is:
Columns with right width percentage
You're just creating a single ColumnConstraints object. This makes it impossible to assign different values to the percentWidth property. You need to create seperate objects for this purpose:
public static final ColumnConstraints[] createColumns(int count) {
ColumnConstraints[] columns = new ColumnConstraints[count];
for(int i = 0; i < count; i++) {
ColumnConstraints column = new ColumnConstraints(1, 10, Double.MAX_VALUE);
column.setPercentWidth(100/count); // do we still need this?
column.setFillWidth(true);
column.setHgrow(Priority.ALWAYS);
column.setHalignment(HPos.CENTER);
columns[i] = column;
}
return columns;
}
Related
I have the following method in one of my classes called Board. Board has an array of 120 Squares, which is another class from my program.
public class Board{
private Square[] square = new Square[120];
...
Each Square has an int row and an int column.
public class Square extends JButton{
public int row;
public int column;
...
The method itself is supposed to figure out what the row and column is for every Square inside
void setSquares() {
int ones;
int tenths;
Square s = new Square();
Insets squareMargin = new Insets(5, 5, 5, 5);
s.setMargin(squareMargin);
for (int i = 0; i < square.length; i++){
ones = getNdigit(i, 1);
tenths = getNdigit(i, 2);
//set row && set column
if ((tenths >= 2 && tenths <= 9) && (ones >= 1 && ones <= 8)){
s.row = tenths - 1;
s.column = ones;
} else{
s.row = 0;
s.column = 0;
}
square[i] = s;
System.out.println(square[0].toString());
}
So at the end of the method, I expect that square[34] has a row of 2 and a column of 4. However, the actual result is always the same as where the for loop ended (square[34] has a row and column of 0).
If the for loop was changed to
for (int i = 0; i < 55; i++){
then square[34] has a row of 4 and a column of 4.
You are creating only one instance of Square and use it throughout the for loop. Move the instantiation inside the for loop so each instance stored will be different.
To answer your question in the comment:
Square s = new Square();
Allocates some space in memory to store the Square instance (where you can set values to its members). so now s references that space in memory.
square[i] = s;
so now square[i] references that same space (thus having the same member values). so for every i all square[i] references to the same place (the same instance of Square). But if you allocate s one each iteration then s will reference a new square and each square[i] will reference a different Square instance
I'm trying to create a bunch of the same objects (Grass) with a loop in different spaces. I have a grid and I want it to fill up the entire grid with different colors.
So I have this code so far:
public stage() {
super(null);
cast = new Cast();
cast.setBounds(10, 10, cast.getWidth(), cast.getHeight());
this.add(grid);
for (int i = 0; i <= 19; i++) {
obj = new Object[] {
new Grass (cast.cells[i][i])
};
}
}
This obviously doesn't work and only makes a colored cell in the last spot of the grid. Is there anyway to make a loop for objects in every spot?
Your code is going to create an new Object[1] 20 times. That Array will contain an instance of Grass. Try this instead.
public stage() {
super(null);
cast = new Cast();
cast.setBounds(10, 10, cast.getWidth(), cast.getHeight());
this.add(grid);
Object obj[] = new Object[20];
for (int i = 0; i <= 19; i++) {
obj[i] = new Grass (cast.cells[i][i])l
}
}
}
I want to write a board game using LibGDX and during a game I want make it possible to add or remove rows / columns on that board. First, I made some tests to prepare myself to that. Here is the code :
public class Test extends Game {
Skin skin;
Stage stage;
Texture texture1;
static int columns = 7;
static int rows = 12;
Window window2;
Table table2;
ArrayList<ArrayList<TextButton>> buttons;
#Override
public void create () {
skin = new Skin(Gdx.files.internal("data/uiskin.json"));
buttons = new ArrayList<ArrayList<TextButton>>();
for(int i = 0 ; i< rows; ++i)
{
buttons.add(new ArrayList<TextButton>());
for( int k = 0; k < columns; ++k)
{
buttons.get(i).add(new TextButton(("ASD" + i + k), skin));
}
}
texture1 = new Texture(Gdx.files.internal("data/badlogicsmall.jpg"));
TextureRegion image = new TextureRegion(texture1);
stage = new Stage(new ScreenViewport());
Gdx.input.setInputProcessor(stage);
ImageButtonStyle style = new ImageButtonStyle(skin.get(ButtonStyle.class));
style.imageUp = new TextureRegionDrawable(image);
ImageButton iconButton = new ImageButton(style);
window2 = new Window("Dialog2", skin);
window2.getTitleTable().add(new TextButton("X", skin)).height(window2.getPadTop());
window2.setSize(300, 400);
table2 = new Table();
for(int i = 0 ; i< rows; ++i)
{
for( int k = 0; k < columns; ++k)
{
table2.add(buttons.get(i).get(k));
}
table2.row();
}
ScrollPane pane= new ScrollPane(table2,skin);
pane.setScrollbarsOnTop(false);
pane.setFadeScrollBars(false);
window2.add(iconButton).row();
window2.add(pane);
stage.addActor(window2);
iconButton.addListener(new ChangeListener() {
public void changed (ChangeEvent event, Actor actor) {
new Dialog("Some Dialog", skin, "dialog") {
protected void result (Object object) {
System.out.println("Chosen: " + object);
if((Boolean) object )
{
for(int i = 0 ; i <columns; ++i){
table2.getCells().removeIndex(0).getActor().remove();}
}
}
}.text("Are you enjoying this demo?").button("Yes", true).button("No", false).key(Keys.ENTER, true)
.key(Keys.ESCAPE, false).show(stage);
}
});
}
#Override
public void render () {
Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
stage.draw();
}
As you can see here, I'm creating a standalone button and a table and fill it with buttons. Then after button clicked I want to remove first row of that table and also move rest of rows up. It works but only once (for first row), then (with second click) I got this exception :
Exception in thread "LWJGL Application" java.lang.IndexOutOfBoundsException: index can't be >= size: 70 >= 70
Don't know what to do and how to fix it. Hope you can help me with this.
UPDATE
Thanks for reply; my code looks like this now :
// initialization
for(int i = 0 ; i< rows; ++i)
{
for( int k = 0; k < columns; ++k)
{
table2.add(new TextButton(("ASD" + i + k), skin));
}
table2.row();
}
// sample operation - remove left column
for(int i = 0 ; i <rows; ++i){
table2.removeActor( table2.getChildren().get(i*columns-i) );
}
columns--;
Also, I got similar Array in logical model and want to change state of UI table based on that array. So is this approach correct or should I change something?
The issue is about row() you are using - before the first row there is no row cell (marked with row() method) and that's why it does not cause error but when removing the second one it does.
Compare with table2 without any rows to test it:
for(int i = 0 ; i< rows; ++i)
{
for( int k = 0; k < columns; ++k)
{
table2.add(buttons.get(i).get(k));
}
//table2.row(); - we don't want any rows!
}
Ok we know where problem lays but it is not the solution (ok maybe some solution it is:) ). Instead of hard removing indexes of Table cells you should operate on Actors of table using following code:
for(int i = 0 ; i <columns; ++i){
table2.removeActor( table2.getChildren().first() );
}
Working with a table in such a way is a bit cumbersome, at least I don't know better. A quick fix for your code would be:
// Global field
int removedRows = 0;
// In your listener
System.out.println("Chosen: " + object);
if ((Boolean) object)
{
for (int i = 0; i < columns; ++i)
{
table2.getCells().get(i + columns * removedRows).clearActor();
}
removedRows++;
}
But if you want to remove complete rows, I would use a VerticalGroup and add each row there, so you can directly access a row and remove it from the VerticalGroup. If you use a fixed size for the buttons then it will align properly, too.
table2.getCells()
Returns an Array, this means we now operate on that Array and NOT the table2 anymore!
This means if you execute this:
table2.getCells().removeIndex(0);
It will just remove that cell from the array. This does NOT update the table2 as a complete object, just the cells array of that table (since no copy of that array is returned)
In other words you are doing this:
Array<Cell> table2Cells = table2.getCells();
Cell tableCell = table2Cells.removeIndex(0);
tableCell.clearActor();
So you delete the cell from the table2 cell array, and then you clear the cells contents (actor in this case). But you are not updating the table to reflect the changes of the removed cell, table2 still "thinks" that the cell is there, but you deleted it.
Thus you get the index error, because the stage draws the table, and the table wants to draw a cell that no longer exists.
So if you want to create some kind of board for a game the best way would be to code your own class that provides the functionality you desire.
A workaround would be that you reset the table and fill it again:
int table2Rows = table2.getRows();
table2.reset();
// Omit the first row
for (int i = rows - table2Rows + 1; i < rows; ++i)
{
for (int k = 0; k < columns; ++k)
{
table2.add(buttons.get(i).get(k));
}
table2.row();
}
table2.layout();
Thus the first cell will contain the first button and so on, since the table internal values are properly updated.
I need to change the column width size of my JTable. Please look at the following code which will use to display values. But I don't know how to maximize the width of the table column.
please let me know how to configure my code.
public void displayTable(JTable table){
Vector columns = new Vector(getIndividual(0).chromosomeColumnCount()+1);
columns.add("Staff Names");
for(int i=0; i<getIndividual(0).chromosomeColumnCount(); i++){
columns.add(RosterManager.getDay(i));
}
Vector data = new Vector();
Vector row;
for(int row1=0; row1<getIndividual(0).ChromosomeRowSize(); row1++){
row = new Vector(getIndividual(0).chromosomeColumnCount());
row.add(RosterManager.getNurse(row1).getEmpName());
for(int col=0; col<getIndividual(0).chromosomeColumnCount(); col++){
row.add(getIndividual(0).getShift(row1, col).getShiftName());
}
data.add(row);
}
DefaultTableModel tableModel = new DefaultTableModel(data, columns);
table.setModel(tableModel);
}
setPreferredWidth(27) can be used. Inside the method you have to add a dimension.
Something like this:
//table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
TableColumn column = null;
for (int i = 0; i < cols.length; i++) {
column = table.getColumnModel().getColumn(i);
if(i == 0 ) column.setPreferredWidth(10);
}
Im using this method to change the width of columns of JTables. Just add this to your displayTable() method.
your_table_name.getColumnModel().getColumn(0).setPreferredWidth(50);
your_table_name.getColumnModel().getColumn(1).setPreferredWidth(100);
JTableName.getColumn(Object identifier).setWidth(WIDTH);
JTableName.getColumn(Object identifier) will return the column and set Width will change its width.
in my Java source i must execute following lines very often:
vecX = EigenMat.multiply(vecX);
vecY = EigenMat.multiply(vecY);
EigenMat is a N x N Matrix with N~40
vecX/vecY is a N x 1 vector (intern a RealMatrix to)
I used the "Sampler" from VisualFM to find some hotspots in my code and
org.apache.commons.math3.linear.Array2DRowRealMatrix.<init>()
org.apache.commons.math3.linear.Array2DRowRealMatrix.multiply()
have a very high runtime.
I'm not a java professional but i think every multiplication a new vector is created. Can i reassign the old one?
Maybe i should switch to JBLAS to speed it up?
Matyro
Edit:
Single core only
i think every multiplication a new vector is created
Yes, it is. Source code of multiply():
public Array2DRowRealMatrix multiply(final Array2DRowRealMatrix m) {
// Safety check.
MatrixUtils.checkMultiplicationCompatible(this, m);
final int nRows = this.getRowDimension();
final int nCols = m.getColumnDimension();
final int nSum = this.getColumnDimension();
final double[][] outData = new double[nRows][nCols];
// Will hold a column of "m".
final double[] mCol = new double[nSum];
final double[][] mData = m.data;
// Multiply.
for (int col = 0; col < nCols; col++) {
// Copy all elements of column "col" of "m" so that
// will be in contiguous memory.
for (int mRow = 0; mRow < nSum; mRow++) {
mCol[mRow] = mData[mRow][col];
}
for (int row = 0; row < nRows; row++) {
final double[] dataRow = data[row];
double sum = 0;
for (int i = 0; i < nSum; i++) {
sum += dataRow[i] * mCol[i];
}
outData[row][col] = sum;
}
}
return new Array2DRowRealMatrix(outData, false);
}
Input vector m is copied, as stated in a comment Copy all elements of column "col" of "m" so that will be in contiguous memory.
Can i reassign the old one?
Yes, you can perform the multiplication by yourself, writing two loops. Use getData() to get a reference to the underlying double[][] data.