FlowLayout on top of GridLayout not working

I am trying to create a hangman game, and while it follows GREAT, but the layout design does not seem to fall into place! The alphabet is supposed to end in FlowLayout order on top of the Hangman image with the "Restart", "Help", "Add New Word" and "Exit" buttons at the bottom! What am I doing wrong?

hangman

 import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; public class Hangman extends JFrame { int i = 0; static JPanel panel; static JPanel panel2; static JPanel panel3; public Hangman() { JButton[] buttons = new JButton[26]; panel = new JPanel(new FlowLayout()); panel2 = new JPanel(); panel3 = new JPanel(); JButton btnRestart = new JButton("Restart"); btnRestart.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { } }); JButton btnNewWord = new JButton("Add New Word"); btnNewWord.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { try { FileWriter fw = new FileWriter("Words.txt", true); PrintWriter pw = new PrintWriter(fw, true); String word = JOptionPane.showInputDialog("Please enter a word: "); pw.println(word); pw.close(); } catch(IOException ie) { System.out.println("Error Thrown" + ie.getMessage()); } } }); JButton btnHelp = new JButton("Help"); btnHelp.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { String message = "The word to guess is represented by a row " + "of dashes, giving the number of letters and category of " + "the word. \nIf the guessing player suggests a letter " + "which occurs in the word, the other player writes it " + "in all its correct positions. \nIf the suggested " + "letter does not occur in the word, the other player " + "draws one element of the hangman diagram as a tally mark." + "\n" + "\nThe game is over when:" + "\nThe guessing player completes the word, or guesses " + "the whole word correctly" + "\nThe other player completes the diagram"; JOptionPane.showMessageDialog(null,message, "Help",JOptionPane.INFORMATION_MESSAGE); } }); JButton btnExit = new JButton("Exit"); btnExit.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { System.exit(0); } }); ImageIcon icon = new ImageIcon("D:\\Varsity College\\Prog212Assign1_10-013803\\images\\Hangman1.jpg"); JLabel label = new JLabel(); label.setIcon(icon); String b[]= {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"}; for(i = 0; i < buttons.length; i++) { buttons[i] = new JButton(b[i]); panel.add(buttons[i]); } panel2.add(label); panel3.add(btnRestart); panel3.add(btnNewWord); panel3.add(btnHelp); panel3.add(btnExit); } public static void main(String[] args) { Hangman frame = new Hangman(); frame.add(panel, BorderLayout.NORTH); frame.add(panel2, BorderLayout.CENTER); frame.add(panel3, BorderLayout.SOUTH); frame.pack(); frame.setVisible(true); } } 
+8
java layout-manager swing jpanel jframe
source share
2 answers

Here are some suggestions:

enter image description here

  • Use GridLayout for the top bar; in this case, zero means that the number of rows is determined by the specified number of columns and the total number of components in the layout:

     JPanel north = new JPanel(new GridLayout(0, 9)); 
  • Here is an example of how you can make your center panel a reasonable initial size; note how you can draw relative to the current size:

     JPanel center = new JPanel() { private static final int N = 256; private static final String S = "Todo..."; @Override protected void paintComponent(Graphics g) { super.paintComponent(g); int dx = (getWidth() - g.getFontMetrics().stringWidth(S)) / 2; int dy = getHeight() / 2; g.drawString(S, dx, dy); } @Override public Dimension getPreferredSize() { return new Dimension(N, N); } }; 
  • You can create your button names as follows:

     for (int i = 0; i < 26; i++) { String letter = String.valueOf((char) (i + 'A')); buttons[i] = new JButton(letter); north.add(buttons[i]); } 
  • Make your panels instance variables and start with the event dispatch thread :

     EventQueue.invokeLater(new Runnable() { @Override public void run() { Hangman frame = new Hangman(); frame.setDefaultCloseOperation(EXIT_ON_CLOSE); frame.add(frame.north, BorderLayout.NORTH); frame.add(frame.center, BorderLayout.CENTER); frame.add(frame.south, BorderLayout.SOUTH); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } }); 
+3
source share

This problem is pretty well documented if you are doing research - it seems that all panels (except CENTER one) are not recounted when resized. See How to make this FlowLayout stream in its JSplitPane? and http://www.velocityreviews.com/forums/t608472-wrap-flowlayout.html

But for a really quick fix, try changing your main method to this ... (mostly using BoxLayout as the main container)

 public static void main(String[] args) { TempProject frame = new TempProject(); Box mainPanel = Box.createVerticalBox(); frame.setContentPane(mainPanel); mainPanel.add(panel); mainPanel.add(panel2); mainPanel.add(panel3); frame.pack(); frame.setVisible(true); } 
+3
source share

All Articles