равно проблема с добавлением компонентов в JPanel? - PullRequest
1 голос
/ 26 января 2010

Я делаю карточную игру, в которой карты представлены в виде JLabels с именами и некоторыми другими атрибутами, которые меняются во время игры. Я хочу определить равенство как простое сравнение полных имен (представленных полем fullName) двух карточек. Однако из-за этого возникает проблема, заключающаяся в том, что я не могу добавить одну и ту же карту дважды (поскольку у меня есть другие поля в классе карт, которые могут отличаться).

Очевидно, что JPanel проверяет equals в фоновом режиме. Затем я добавляю уникальное поле id к каждой карточке, и в классе я отслеживаю, сколько карточек такого типа я создал с помощью

    private static Map<AbstractCard, Integer> idCount = new HashMap<AbstractCard, Integer>();

и затем каждый раз, когда вызывается конструктор определенной карты, я увеличиваю значение на idCount. Но затем, если я добавлю проверку для id, а также исходный name, не только Карта сломается, но и не добавит более одной карты, если имена равны. Вот как теперь выглядит метод:

/**
 * Compares this card to the specified object. The result is true if and only if 
 * the argument is not null and is a Card object that represents the same full name
 * as this card.
 * @return true if the cards are equal, otherwise false
 */
@Override
public boolean equals(Object o)
{
    if (!(o instanceof AbstractCard))
        return false;
    else
    {
        AbstractCard c = (AbstractCard)o;
        return this.fullName.equals(c.fullName) && this.id == c.id;
    }
}

Есть мысли о том, как решить эту проблему?

РЕДАКТИРОВАТЬ: My hashCode возвращает fullName.hashCode() и в текущей версии я добавляю id.

Ответы [ 4 ]

2 голосов
/ 26 января 2010

EDIT

Я сделал следующий тест, и он работал нормально:

private class MyLabel extends JLabel {
    public MyLabel(String text) {
        super(text);
    }
    public boolean equals(Object obj) {
        return true;
    }
};


public MyPanel() {
    getContentPane().setLayout(new GridLayout());
    getContentPane().add(new MyLabel("Label 1"));
    getContentPane().add(new MyLabel("Label 2"));
    getContentPane().add(new MyLabel("Label 3"));
}

С какими проблемами вы сталкиваетесь?

Кстати: это не решит вашу проблему, но JavaDoc для equals говорит

Обратите внимание, что обычно необходимо переопределить метод hashCode всякий раз, когда этот метод переопределяется


Если карта расширяет JLabel, и вы создаете экземпляр для каждой вашей карты, вам вообще не нужно переопределять equals. Не добавляйте одну и ту же карту в два контейнера (или в один контейнер дважды). Это не будет работать и для реальных карт.

Может быть, лучше отделить класс карт от их визуализации. Рассматривали ли вы не продление вашей карты из класса свинг?

Вы можете просто переопределить toString и отобразить их в JList.

1 голос
/ 26 января 2010

HashMaps зависят от хэш-кода, чтобы найти правильное «ведро», а затем выбрать правильный элемент с помощью тестов на равенство. Если вы не переопределяете hashCode (), HashMap может не получить элемент, даже если он там есть. Вообще говоря, всегда переопределяйте equals () и hashCode () вместе.

Я, однако, призываю вас переосмыслить свой дизайн. Этот вид подсчета ссылок не очень хорошая идея. Кроме того, вы смешиваете слишком много логики и элементов модели в коде GUI. Вы должны подумать о том, чтобы адаптировать модель-представление-контроллер к проблеме. Полностью смоделируйте игру, а затем представьте модель в качестве интерфейса.

0 голосов
/ 27 января 2010

Кроме того, вам может понравиться чтение источника этой простой игры . Это вовсе не карточная игра, но класс GameButton может предложить способ использования символов Юникода для обозначения ранга и масти карты.

0 голосов
/ 26 января 2010

Я ужасно сожалею об этом, похоже, это была моя вина с самого начала. После многих отладок и печати я обнаружил, что у меня есть ссылка на панель, которая была частью другой панели, и поэтому у меня почему-то было только «действительно» 3 карты. После того, как я удалил ссылку и вместо этого сделал новую Карту, она, наконец, обнаружилась, и getComponentCount вернул 4.

Еще раз прошу прощения за трату вашего времени.

...