2015-10-11 7 views
2

Я хочу написать настольную игру, используя LibGDX, и во время игры я хочу, чтобы добавить или удалить строки/столбцы на этой доске. Во-первых, я сделал несколько тестов, чтобы подготовиться к этому. Вот код:Ошибка при удалении строки из таблицы Libgdx

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(); 
    } 

Как вы можете видеть здесь, я создаю отдельную кнопку и таблицу и заполнить ее с помощью кнопок. Затем после нажатия кнопки я хочу удалить первую строку этой таблицы, а также переместить остальные строки вверх. Это работает, но только один раз (для первого ряда), затем (со вторым щелчком) Я получил это исключение:

Exception in thread "LWJGL Application" java.lang.IndexOutOfBoundsException: index can't be >= size: 70 >= 70 

Не знаю, что делать и как это исправить. Надеюсь, ты поможешь мне в этом.

UPDATE

Спасибо за ответ; мой код будет выглядеть так:

// 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--; 

Кроме того, я получил подобный массив в логической модели и хочу изменить состояние таблицы пользовательского интерфейса на основе этого массива. Так подходит ли этот подход или я должен что-то изменить?

ответ

0

Работая со столом таким образом, это немного громоздко, по крайней мере, я не знаю лучше. Быстрое исправление для вашего кода будет:

// 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++; 
} 

Но если вы хотите, чтобы удалить полные строки, я хотел бы использовать VerticalGroup и добавить каждую строку там, так что вы можете непосредственно получить доступ к строке и удалить его из VerticalGroup. Если вы используете фиксированный размер для кнопок, он также будет правильно выравниваться.

table2.getCells() 

Возвращает массив, это означает, что мы теперь действуем на этом массиве, а НЕ в таблице2 больше!

Это означает, что если вы выполните это: table2.getCells(). RemoveIndex (0); Он просто удалит эту ячейку из массива. Это не обновляет таблица2 как целостного объекта, а только клетки массив этой таблицы (так как ни одна копия этого массива не возвращается)

Другими словами, вы делаете это:

Array<Cell> table2Cells = table2.getCells(); 

Cell tableCell = table2Cells.removeIndex(0); 

tableCell.clearActor(); 

Таким образом, вы удалите ячейку из массива ячеек таблицы2, а затем вы очищаете содержимое ячеек (в этом случае актер). Но вы не обновляете таблицу, чтобы отразить изменения удаленной ячейки, таблица2 все еще «думает» о том, что ячейка существует, но вы ее удалили.

Таким образом, вы получаете индексную ошибку, потому что этап рисует таблицу, и таблица хочет нарисовать ячейку, которая больше не существует.

Итак, если вы хотите создать какую-то доску для игры, лучшим способом было бы кодировать свой собственный класс, который обеспечивает требуемые функции.

Обходной будет то, что вы сбросить таблицу и заполнить ее еще раз:

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(); 

Таким образом, первая ячейка будет содержать первую кнопку и так далее, так как внутренние значения таблицы правильно обновляются.

+0

Спасибо за переигровку и помощи. Может быть, я должен попробовать с этими VerticalGroups ... однако подумайте, что добавлять/удалять строки и столбцы было бы проще с ними? Также ваш ответ не полностью оправдает мои ожидания, потому что элементы отдыха не изменяют свои индексы, поэтому в этом массиве я получил от getCells(), элемент 7 все еще имеет индекс 7, несмотря на то, что раньше не было никаких элементов. Я думаю, что это может вызвать проблемы, когда я хотел бы добавить строку раньше. Таким образом, в основном то, что я хочу достичь, является «динамической» доской, чтобы я мог добавлять/удалять столбцы и строки. –

+0

«Стол», похожий на bejeweled или что-то в этом роде? Тогда вы не должны использовать этот класс Table, поскольку он предназначен для целей пользовательского интерфейса. Я вскоре обновлю свой ответ, чтобы добавить несколько объяснений. –

0

Речь идет о строке() вы используете - до первой строки нет строки ячейки (отмеченной строки() метод), и именно поэтому он не вызывает ошибку, но при удалении второй оно делает.

Сравнить с table2 без каких-либо строк, чтобы проверить это:

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 мы знаем, где проблема лежит, но это не решение (хорошо, может быть, какое-то решение это :)). Вместо жестких удаление индексов ячеек таблицы вы должны работать на Актерах таблицы, используя следующий код:

for(int i = 0 ; i <columns; ++i){ 
     table2.removeActor(table2.getChildren().first()); 
    } 
Смежные вопросы