Добавьте в рамку несколько фигур свинга/автомата

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

Код CrapsGame:

package crapsgame;
import java.awt.FlowLayout;
import javax.swing.*;


public class CrapsGameTester 
{

/**
 * @param args the command line arguments
 */
public static void main(String[] args) 
{
    JFrame frame = new JFrame("Craps-Game");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(false);

    final int FRAME_WIDTH = 400;
    final int FRAME_HEIGHT = 600;

    frame.setSize(FRAME_HEIGHT, FRAME_WIDTH);

    CrapsGame game = new CrapsGame();

    JPanel panel = new JPanel(new FlowLayout());
    frame.add(panel);

    Dice1Component dice1 = new Dice1Component(6);
    Dice2Component dice2 = new Dice2Component(6);
    panel.add(dice1);
    panel.add(dice2);

    String message = game.doFirstRoll();
    System.out.println(message);

    while(!game.isOver())
    { 
        message = game.rollAgain();
        System.out.println(message);
    }

    if(game.isWon())
        System.out.println("You win, big man!");
    else
        System.out.println("Loser ...");

    frame.setVisible(true);
}

}

Код Dice1:

package crapsgame;

import java.awt.*;

public class Dice1 
{
int sides;
int xCoord = 150;
int yCoord = 130;

public Dice1(int s)
{
    sides = s;
}

/**
 * 
 * @param g2 Graphics2D object used by draw method
 */
public void draw(Graphics2D g2)
{
    g2.setColor(Color.BLACK);
    g2.fillRect(xCoord, yCoord, 100, 100);
    g2.setColor(Color.WHITE);

    switch (sides)
    {
        case 1:
            g2.fillOval(xCoord + 40, yCoord + 40, 20, 20);
            break;
        case 2:
            g2.fillOval(xCoord + 15, yCoord + 15, 20, 20);
            g2.fillOval(xCoord + 65, yCoord + 65, 20, 20);
            break;
        case 3:
            g2.fillOval(xCoord + 15, yCoord + 15, 20, 20);
            g2.fillOval(xCoord + 40, yCoord + 40, 20, 20);
            g2.fillOval(xCoord + 65, yCoord + 65, 20, 20);
            break;
        case 4:
            g2.fillOval(xCoord + 15, yCoord + 15, 20, 20);
            g2.fillOval(xCoord + 15, yCoord + 65, 20, 20);
            g2.fillOval(xCoord + 65, yCoord + 15, 20, 20);
            g2.fillOval(xCoord + 65, yCoord + 65, 20, 20);
            break;
        case 5:
            g2.fillOval(xCoord + 15, yCoord + 15, 20, 20);
            g2.fillOval(xCoord + 15, yCoord + 65, 20, 20);
            g2.fillOval(xCoord + 65, yCoord + 15, 20, 20);
            g2.fillOval(xCoord + 65, yCoord + 65, 20, 20);
            g2.fillOval(xCoord + 40, yCoord + 40, 20, 20);
            break;
        case 6: 
            g2.fillOval(xCoord + 20, yCoord + 20, 20, 20);
            g2.fillOval(xCoord + 20, yCoord + 45, 20, 20);
            g2.fillOval(xCoord + 20, yCoord + 70, 20, 20);
            g2.fillOval(xCoord + 60, yCoord + 20, 20, 20);
            g2.fillOval(xCoord + 60, yCoord + 45, 20, 20);
            g2.fillOval(xCoord + 60, yCoord + 70, 20, 20);
            break;
    }
}
}

Код Dice1Component:

package crapsgame;
import java.awt.*;
import javax.swing.*;


public class Dice1Component extends JComponent
{
private int sides;

public Dice1Component(int s)
{
    sides = s;
}

public void setSide(int s)
{
    sides = s;
}

@Override
public void paintComponent(Graphics g)
{
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    Dice1 dice1 = new Dice1(sides);
    dice1.draw(g2);
}
}

Я читал, что для добавления в кадр более одного компонента необходимо использовать JPanel, но мне это тоже не подходит.


person hjalpmig    schedule 02.11.2014    source источник
comment
Мне любопытно, почему вы не рисуете оба кубика на один и тот же компонент? Также я бы не стал создавать Dice внутри метода paintComponent. Сохраните его как член класса. Имейте двух членов класса, по одному на каждую игральную кость. У вас может быть сеттер для каждой кости. Если вы планируете иметь много кубиков, то, возможно, вы можете создать Map кубиков и получить доступ к каждому из них по ключу. Но обычно я бы использовал только одну поверхность для рисования.   -  person Paul Samsotha    schedule 02.11.2014
comment
Да, как @peeskillet: подумайте о том, чтобы сделать Dice логическим классом, который умеет рисовать себя, но не классом GUI, а не классом, который расширяет компонент Swing. Рассмотрите возможность создания JPanel для рисования, который рисует все игральные кости, и избегайте создания объектов и переменных внутри paintComponent. У вас нет контроля над тем, когда и будет ли вызываться этот метод, поэтому в него не должна входить никакая программная логика, только рисование кода.   -  person Hovercraft Full Of Eels    schedule 02.11.2014


Ответы (1)


Есть пара проблем (в дополнение к упомянутым в комментариях), но они должны заставить код работать:

  • Вы должны переопределить предпочтительный размер в Dice1Component, чтобы менеджер компоновки мог зарезервировать для него правильное пространство.

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(100, 100);
    }
    
  • удалить xCoord и yCoord из Dice1. Используемые координаты относятся к компоненту, поэтому большое смещение будет пытаться рисовать за пределами области компонента.
  • Ознакомьтесь с руководством по созданию компонентов и доступу к ним. только в потоке отправки событий.
person kiheru    schedule 02.11.2014