I have some bits of code with a lot of help from fellow programmers in SO. First off, Thank you all for that. Now I have this code for hangman. I want the textfield to appear below the image, right now it is shooting on top of it. I have provided the link for the image in the code. but you might need to download it to avoid exception thrown. I want to keep top right corner free for timer, which I have not thought how to do yet. I need assistance in getting image and texfield in correct positions. please execute code to see how it looks currently. I tried both BorderLayout.SOUTH and BorderLayout.PAGE_END, but it did not help Thank you
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.text.MaskFormatter;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
public class HangmanGUI {
private DetailsPanel myPanel;
private ImagePanel imagePanel = new ImagePanel();
public HangmanGUI() throws ParseException {
myPanel = new DetailsPanel();
JFrame myframe = new JFrame();
// myframe.getContentPane().setLayout(new BorderLayout());
myframe.getContentPane().add(imagePanel, BorderLayout.CENTER);
myframe.getContentPane().add(myPanel, BorderLayout.SOUTH);
myframe.setTitle("Hangman Game");
// myframe.setVisible(true);
// myframe.setLocationRelativeTo(null);
myframe.pack();
myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myframe.setLocationRelativeTo(null);
myframe.setVisible(true);
}
public static void main(String[] args) throws ParseException {
new HangmanGUI();
}
}
class ImagePanel extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private static final String TITLE = "Hangman Image";
private BufferedImage image;
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public ImagePanel() {
setBorder(BorderFactory.createTitledBorder(TITLE));
try {
image = ImageIO.read(new File("http://upload.wikimedia.org/wikipedia/commons/8/8b/Hangman-0.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
add(createFormattedPanel(),BorderLayout.SOUTH);
//add(createFormattedPanel(),BorderLayout.PAGE_END);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null); // see javadoc for more info on the parameters
}
public JPanel createFormattedPanel() {
JPanel panel = new JPanel();
MaskFormatter formatter = null;
try {
JLabel label = new JLabel("Guesss");
formatter = new MaskFormatter("? ? ? ? ? ? ?");
formatter.setPlaceholderCharacter('?');
JFormattedTextField input = new JFormattedTextField(formatter);
input.setColumns(20);
panel.add(label);
panel.add(input);
} catch (java.text.ParseException exc) {
System.err.println("formatter is bad: " + exc.getMessage());
System.exit(-1);
}
return panel;
}
}
class DetailsPanel extends JPanel {
public DetailsPanel() {
setLayout(new BorderLayout());
setBorder(BorderFactory.createTitledBorder(" click here "));
//add(createFormattedPanel(), BorderLayout.PAGE_START);
JPanel letterPanel = new JPanel(new GridLayout(0, 5));
for (char alphabet = 'A'; alphabet <= 'Z'; alphabet++) {
String buttonText = String.valueOf(alphabet);
JButton letterButton = new JButton(buttonText);
letterButton.addActionListener(clickedbutton());
letterPanel.add(letterButton, BorderLayout.CENTER);
}
add(letterPanel, BorderLayout.CENTER);
}
private ActionListener clickedbutton() {
return new ActionListener() {
public void actionPerformed(ActionEvent e) {
String actionCommand = e.getActionCommand();
System.out.println("actionCommand is: " + actionCommand);
}
};
}
}
Because you're mixing custom painting and components into a single component, you are losing control over how your components are laid out.
Two solutions come to mind...
Use a JLabel
Use a
JLabel
to display the image, placing it in theCENTER
position of theImagePane
and the "formatted panel" in theSOUTH
positionSeparate your components in logic groups
Split apart your UI so that each component is isolated...
Basically, the
ImagePane
, theGuessPane
and theClickPane
are all separate components.You would then add the
ImagePane
andGuessPane
onto anotherJPanel
(usingBorderLayout
) and then add this and theClickPane
onto the main panel (using aBorderLayout
).This will give you greater control over how the individual components are laid out and can be combined.
== Example Using
JLabel
==This is a basic example of using a
JLabel
over using custom painting.The
ImagePane
andGuessPane
are added to separate panel, which is added to theCENTER
position of the frame. TheDetailsPane
is then added to theSOUTH
position of the frame...This type of separation is going to require to use some kind of model to bridge across the components.
That is, when the user makes a guess, you need to update the model, which will notify the other components (via some kind of listener API) that some change has occurred, this will allow the other UI elements to update themselves as required to meet the requirements of the model.
The model should contain the logic for the game and drive the UI.