1

I am making a Talisman Game, so far I have methods to create the Random Characters, and a WIP Main Menu. Now, if i call the new game (create characters) methods from the main class, its all good, but if i call it from the main manu, the JFrame get transparent and copy their background (like when a window gets stuck)

the new game method is:

public Game(int playerNum) {

    for (int i = 0; i < chars.length; i++)
    chars[i] = false;

    this.playerNum=playerNum;

    players = new Player[playerNum];
    guiChars = new Gui_Chars[playerNum];

    Card.createCards();
    Game.randomChar();
    for (int j = 0; j < playerNum; j++)
        guiChars[j].update();
}

now, the Game,randomChar() create the characters:

public static void randomChar() {
    for (int i = 0; i < playerNum; i++) {
        do {
            chooseChar = rnd.nextInt(14);
        } while (chars[chooseChar]);
        switch (chooseChar) {
            case 0: {
                players[i] = new Char_ASSASIN();
                guiChars[i] = new Gui_Chars("Player " + (i + 1) + " - "
                                + "Assasin", players[i], "Images/assassin.jpg");
                System.out.println("Player " + (i + 1) + " is an Assasin");
                chars[0] = true;
                break;
            }
            case 1: {
                players[i] = new Char_DRUID();
                guiChars[i] = new Gui_Chars("Player " + (i + 1) + " - "
                                    + "Druid", players[i], "Images/druid.jpg");
                System.out.println("Player " + (i + 1) + " is a Druid");
                chars[1] = true;
                break;
            }
            case 2: {
                players[i] = new Char_DWARF();
                guiChars[i] = new Gui_Chars("Player " + (i + 1) + " - "
                                   + "Dwarf", players[i], "Images/dwarf.jpg");
                System.out.println("Player " + (i + 1) + " is a Dwarf");
                chars[2] = true;
                break;
            }
            case 3: {
                players[i] = new Char_ELF();
                guiChars[i] = new Gui_Chars(
                         "Player " + (i + 1) + " - " + "Elf", players[i],
                                                           "Images/elf.jpg");
                System.out.println("Player " + (i + 1) + " is an Elf");
                chars[3] = true;
                break;
            }
            case 4: {
                players[i] = new Char_GHOUL();
                guiChars[i] = new Gui_Chars("Player " + (i + 1) + " - "
                                  + "Ghoul", players[i], "Images/ghoul.jpg");
                System.out.println("Player " + (i + 1) + " is a Ghoul");
                chars[4] = true;
                break;
            }
            case 5: {
                players[i] = new Char_MINSTREL();
                guiChars[i] = new Gui_Chars("Player " + (i + 1) + " - "
                            + "Minesrel", players[i], "Images/minstrel.jpg");
                System.out.println("Player " + (i + 1) + " is a Minstrel");
                chars[5] = true;
                break;
            }
            case 6: {
                players[i] = new Char_MONK();
                guiChars[i] = new Gui_Chars("Player " + (i + 1) + " - "
                                    + "Monk", players[i], "Images/monk.jpg");
                System.out.println("Player " + (i + 1) + " is a Monk");
                chars[6] = true;
                break;
            }
            case 7: {
                players[i] = new Char_PRIEST();
                guiChars[i] = new Gui_Chars("Player " + (i + 1) + " - "
                                + "Priest", players[i], "Images/priest.jpg");
                System.out.println("Player " + (i + 1) + " is a Priest");
                chars[7] = true;
                break;
            }
            case 8: {
                players[i] = new Char_PROPHETESS();
                guiChars[i] = new Gui_Chars("Player " + (i + 1) + " - "
                        + "Prophetess", players[i], "Images/prophetess.jpg");
                System.out.println("Player " + (i + 1) + " is a Prophetess");
                chars[8] = true;
                break;
            }
            case 9: {
                players[i] = new Char_SORCERESS();
                guiChars[i] = new Gui_Chars("Player " + (i + 1) + " - "
                          + "Sorceress", players[i], "Images/sorceress.jpg");
                System.out.println("Player " + (i + 1) + " is a Sorceress");
                chars[9] = true;
                break;
            }
            case 10: {
                players[i] = new Char_THIEF();
                guiChars[i] = new Gui_Chars("Player " + (i + 1) + " - "
                                  + "Thief", players[i], "Images/thief.jpg");
                System.out.println("Player " + (i + 1) + " is a Thief");
                chars[10] = true;
                break;
            }
            case 11: {
                players[i] = new Char_TROLL();
                guiChars[i] = new Gui_Chars("Player " + (i + 1) + " - "
                                  + "Troll", players[i], "Images/troll.jpg");
                System.out.println("Player " + (i + 1) + " is a Troll");
                chars[11] = true;
                break;
            }
            case 12: {
                players[i] = new Char_WARRIOR();
                guiChars[i] = new Gui_Chars("Player " + (i + 1) + " - "
                              + "Warrior", players[i], "Images/warrior.jpg");
                System.out.println("Player " + (i + 1) + " is a Warrior");
                chars[12] = true;
                break;
            }
            case 13: {
                players[i] = new Char_WIZARD();
                guiChars[i] = new Gui_Chars("Player " + (i + 1) + " - "
                                + "Wizard", players[i], "Images/wizard.jpg");
                System.out.println("Player " + (i + 1) + " is a Wizard");
                chars[13] = true;
                break;
            }
        }
    }
}

The Characters call the GUI (that recieves info from the Characters classes, but thats for sure not the problam):

public Gui_Chars(String character,Player player,String path) {

    super(character);
    setVisible(true);
    setSize(430, 420);

    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
    revalidate();
}

i deleted the unimportant part of the code, the problam happens without it too... and for the end, this is the MainMenu:

public class MainMenu extends JFrame implements ActionListener {

    private static final long serialVersionUID = 1L;
    JLabel num;
    JButton add, sub, start;
    private int i = 2;
    JFrame j ;
    Game game;

    JLayeredPane jp1,jp2,jp3;

    public MainMenu() {

        j= new JFrame("Talisman");
        j.setVisible(true);
        j.setSize(300, 300);
        j.setDefaultCloseOperation(EXIT_ON_CLOSE);

        jp1 = new JLayeredPane();
        jp2 = new JLayeredPane();
        jp3 = new JLayeredPane();   

        JPanel playerNum = new JPanel(new GridBagLayout());
        JPanel startPanel = new JPanel(new GridBagLayout());

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(30, 30, 30, 30);

        add = new JButton("+1");
        sub = new JButton("-1");
        start = new JButton("Start");

        start.setPreferredSize(new Dimension(100, 100));

        num = new JLabel("" + i);
        num.setFont(new Font("Serif", Font.BOLD, 40));

        gbc.gridy = 0;
        playerNum.add(add, gbc);
        add.addActionListener(this);
        add.setActionCommand("add");

        gbc.gridy = 1;
        playerNum.add(num, gbc);

        gbc.gridy = 2;
        playerNum.add(sub, gbc);
        sub.addActionListener(this);
        sub.setActionCommand("sub");

        startPanel.add(start, gbc);
        start.addActionListener(this);
        start.setActionCommand("start");

        jp1.add(new ContentPanel());
        jp2.add(playerNum);
        jp3.add(startPanel);

        jp1.setLayer(new ContentPanel(), 1);
        jp2.setLayer(playerNum, 2);
        jp3.setLayer(startPanel, 2);

        j.add(playerNum, BorderLayout.WEST);
        j.add(startPanel, BorderLayout.EAST);

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String act = e.getActionCommand();

        if (act.equals("start")) {
            j.setVisible(false);
            j.dispose();
            game = new Game(i);
            game.startGame();

            //JFrame j = new JFrame();
            //j.setVisible(true);
            //j.setSize(300, 300);
        }
    }
}

I'm very sorry for the long code, but I tried to sit on it for hours in the debug and could not find the problam. I'll be super gratefull if someone will help me understand whats happening... Thanks again, and sorry for the long code...

nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
Yuval3210
  • 193
  • 4
  • 14
  • As far as I can tell, as I understood, when you restart, it seems you had disposed your `JLayer` but you forgot to remove them from the said `JFrame` so each time you call the `startGame()` function, it keeps on adding the controls on top of the previous one, hence the effect that you are getting. Rather add `frame.removeAll()` at the start of your `startGame()` method or else do that inside the `actionPerformed(...)` method before calling `startGame()`, that might can solve the issue, I guess :-) – nIcE cOw May 15 '12 at 16:33
  • The JLayers were just something i tried, i didnt really out them in action, and the problam also happend before them... I tired to removeAll() and still the same outcome. thanks for your help, any more ideas? – Yuval3210 May 15 '12 at 17:51
  • So Sorry, in the absence of the working code, it's hard to tell the reason sometimes :( Ohho, you are disposing the current `JFrame` on which you are working , inside your `actionPerformed()` method, isn't that right you need to change that part, and do something that makes sense. Or else try this thing too, after writing dispose(), again call the constructor of your `MainMenu()` class, that might can start a new `JFrame` i guess. – nIcE cOw May 15 '12 at 17:54
  • But is there logic that it workes if i call the exact same class from the main class, and not if i call it from the main manu? – Yuval3210 May 15 '12 at 17:56
  • See [The Use of Multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/a/9554657/418556) – Andrew Thompson May 15 '12 at 18:05
  • For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson May 16 '12 at 05:55
  • From what I can see, random char may never return. The for loop at the start of the method will always find chars[x] as false. Whe you call this from within the ETD, you are causing the GUI thread to stop. If this is your intended design, you are going to need to multiu thread the solution – MadProgrammer Jul 10 '12 at 17:44

1 Answers1

0

From looking at your code, it suggest to me that you do not understand Swings paint subsystems.

The most important point, is NEVER do any long or blocking operations within Swing's Event Dispatching Event (ETD).

The reason why it worked when you called it in Main is actually a fluke. Java makes no guarantee about what thread will execute the Main method. You got lucky and it wasn't the ETD. When launching a Swing application you must always do as follows

EventQueue.invokeLater(new Runnable() {
    public void run() {
        // Your launch code here
    }
}

Obviously, only include UI related code in there.

The reason it doesn't work now, is you are executing a blocking piece of code from within your action listener which is preventing the ETD from updating the screen.

for (int i = 0; i < chars.length; i++)
    chars[i] = false;

.
.
.

public static void randomChar() {
    for (int i = 0; i < playerNum; i++) {
        do {
            chooseChar = rnd.nextInt(14);
        } while (chars[chooseChar]); // This is never true...

Which is been called from

game = new Game(i);

You will want to change your games model to allow for the "randomChar" method to be called from a thread context other then the ETD. I'd suggest (for ease), something like SwingWoker (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html)

From your code sample, I can not see where "chars[x]" is ever set to true...

In fact, you may want to read the entire Concurrency in Swing tutorial...

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366