Как удалить элемент внутри JPanel, обозначенный ArrayList

Существует JPanel с GridLayout, который случайным образом заполняется JButtons, созданными с использованием ArrayList. Каждый элемент массива (плитка) содержит символ. Предполагалось, что это игра по удалению плиток. Однако я понял, что код, который я написал, не не работает, потому что после удаления плитки индексы других меняются.

KeyListener применяется к JPanel. Этот метод находится в моем классе Model, где сначала создается ArrayList. getChar в классе Tile просто возвращает свой символ.

public void removeChar(char typedChar) {
    for(Tile t: _al){
            if(t.getChar() == typedChar) {
                System.out.println(typedChar + " is in the game, at index " + _al.indexOf(t) + " of the array.");
                _p.remove(_al.indexOf(t));
            }

В моем коде я просто хочу удалить соответствующую плитку при вводе ее символьного ключа. Может ли кто-нибудь помочь мне увидеть лучший (ну, рабочий) способ сделать это? Мой код кажется намного более сложным, потому что ArrayList полон объектов, но эти объекты понадобятся мне позже.


person Community    schedule 19.11.2015    source источник
comment
Не удаляйте значение, просто замените его чем-то, что вы можете проверить и исключить при заполнении вашей JPanel _p.set(_al.indexOf(t), null) ‹- Вот я сделал это с null например.   -  person Yassin Hajaj    schedule 19.11.2015
comment
Предполагается, что это игра, в которой нужно удалить плитку. Я думаю, что лучшей стратегией здесь было бы полное заполнение сетки кнопками при запуске, а затем установка значков кнопок в соответствии с моделью игры. Было бы возможно использовать полностью прозрачный значок для скрытой плитки или отключить кнопку, которая по какой-либо причине не может быть выбрана.   -  person Andrew Thompson    schedule 19.11.2015
comment
Ясин, меня смущает ваш комментарий. Вы имеете в виду, что я должен установить значение каждой кнопки JButton равным _p.set(_al.indexOf(t), null)? И Эндрю, я никогда раньше не программировал, так что я не совсем понимаю, что ты имеешь в виду. По сути, моя игра должна быть клоном KeyBricks.   -  person    schedule 19.11.2015
comment
Совет: добавьте @YassinHajaj (или кого-то еще, важно @), чтобы уведомить человека о новом комментарии.   -  person Andrew Thompson    schedule 19.11.2015
comment
@MaddoxJKingsley Нет. По сути, вместо использования remove используйте set, и это не изменит длину вашего списка. Затем при заполнении JPanel кнопками проверьте, например, является ли индекс нулевым, и не рассматривайте его как другие индексы.   -  person Yassin Hajaj    schedule 19.11.2015
comment
Моя игра должна быть клоном KeyBricks, по сути Извините, я не знаком с ней. Что-нибудь вроде Chess, Морской бой или Тетрис? Я думаю, что любая из этих игр может быть создана так, как я описал. Важной вещью, которая будет неизменной для любой игры, является модель (или состояние игры), определяющая, что должно отображаться в представлении (компоненты, которые мы изменяем для отображения хода игры).   -  person Andrew Thompson    schedule 19.11.2015
comment
@YassinHajaj Ааа, теперь я понимаю, что ты имеешь в виду. На самом деле это будет очень полезно для более позднего этапа моего проекта. Хотя, просто чтобы уточнить, вы имеете в виду, что я должен использовать set в ArrayList, _al? _p — это панель JPanel, в которой находятся кнопки JButton, поэтому для нее не существует такой вещи, как set.   -  person    schedule 19.11.2015
comment
@MaddoxJKingsley Хорошо, извините, я не понял, что _p означает JPanel.   -  person Yassin Hajaj    schedule 19.11.2015
comment
@AndrewThompson В KeyBricks при вводе ключа блок с этой буквой и все окружающие его элементы того же цвета будут удалены. Это простая браузерная игра, поэтому, если вы погуглите, вы сможете увидеть быстрый пример, если хотите. Что касается модели, это то, что я пытаюсь сделать. По мере усложнения проекта и добавления нескольких шагов это стало необходимо. Я думаю, что плохо выразился, но графический интерфейс и модель данных в основном разделены.   -  person    schedule 19.11.2015


Ответы (1)


Не используйте KeyListener. Swing был разработан для использования с привязками клавиш.

Добавьте привязку клавиш к каждой кнопке. Затем, когда буква будет напечатана, кнопка будет источником события, поэтому вы можете просто удалить кнопку с панели.

Пример того, как работают привязки клавиш, см. ниже:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class CalculatorPanel extends JPanel
{
    private JTextField display;

    public CalculatorPanel()
    {
        Action numberAction = new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
//              display.setCaretPosition( display.getDocument().getLength() );
                display.replaceSelection(e.getActionCommand());
            }
        };

        setLayout( new BorderLayout() );

        display = new JTextField();
        display.setEditable( false );
        display.setHorizontalAlignment(JTextField.RIGHT);
        add(display, BorderLayout.NORTH);

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout( new GridLayout(0, 5) );
        add(buttonPanel, BorderLayout.CENTER);

        for (int i = 0; i < 10; i++)
        {
            String text = String.valueOf(i);
            JButton button = new JButton( text );
            button.addActionListener( numberAction );
            button.setBorder( new LineBorder(Color.BLACK) );
            button.setPreferredSize( new Dimension(30, 30) );
            buttonPanel.add( button );

            InputMap inputMap = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
            inputMap.put(KeyStroke.getKeyStroke(text), text);
            inputMap.put(KeyStroke.getKeyStroke("NUMPAD" + text), text);
            button.getActionMap().put(text, numberAction);
        }
    }

    private static void createAndShowUI()
    {
        JFrame frame = new JFrame("Calculator Panel");
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.add( new CalculatorPanel() );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

Итак, в вашем случае код в методе actionPerformed() действия будет выглядеть примерно так:

JButton button = (JButton)e.getSource();
JPanel parent = (JPanel)button.getParent();
parent.remove(button);
parent.revalidate();
parent.repaint();

Редактировать:

При использовании KeyListener вы можете использовать HashMap для привязки символа к соответствующей кнопке:

HashMap<Character, JButton> buttons = new HashMap<Character, JButton>();
...
buttons.put('a', aButton);
buttons.put('b', bButton);

Тогда код keyTyped() в коде KeyListener будет выглядеть примерно так:

JButton button = buttons.get( e.getKeyChar() );
panel.remove( button );
panel.revalidate();
panel.repaint();
person camickr    schedule 19.11.2015
comment
Мой профессор всегда говорит KeyListener, поэтому я думаю, что должен использовать его в своем проекте. Все всегда говорят, что Key Bindings должны использоваться для компонентов Swing здесь, но ни разу они не упоминались в моем классе. Если вместо этого я использую привязки клавиш, это избавит меня от проблемы с индексом, с которой я сталкиваюсь? - person ; 19.11.2015
comment
@MaddoxJKingsley - If I use Key Bindings instead, will that get rid of the index problem I'm having? - вы попробовали мое предложение с кодом, который я вам дал? Вы не узнаете, спрашивая. Вы учитесь, пытаясь (и иногда делая ошибки). См. редактирование для альтернативного предложения. - person camickr; 19.11.2015