Add a complex image in the panel, with buttons around it in one customized user interface
icons, java, jbutton, layout-manager, swing
Solution
- Use a 3x3 `GridLayout`
- For each of the 9 cells get a subimage:
- For every second component, add a label with the subimage.
- For every other component, add a `JButton` from which the space is removed. Use the subimage as icon, but you'll need alternate icons to indicate focus, activation etc. This example puts a red border around the 'pressed' icon.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.net.URL;
import javax.imageio.ImageIO;
public class CompassButtons {
public CompassButtons(BufferedImage bi) {
int w = bi.getWidth();
int h = bi.getHeight();
int step = w / 3;
JPanel p = new JPanel(new GridLayout(3, 3));
p.setBackground(Color.BLACK);
int count = 0;
for (int ii = 0; ii < w; ii += step) {
for (int jj = 0; jj < h; jj += step) {
// This is it - GET THE SUB IMAGE
Image icon = bi.getSubimage(jj, ii, step, step);
if (count % 2 == 1) {
JButton button = new JButton(new ImageIcon(icon));
// make it transparent
button.setContentAreaFilled(false);
// remove border, indicate press using different icon
button.setBorder(null);
// make a 'pressed' icon..
BufferedImage iconPressed = new BufferedImage(
step, step, BufferedImage.TYPE_INT_ARGB);
Graphics g = iconPressed.getGraphics();
g.drawImage(icon, 0, 0, p);
g.setColor(Color.RED);
g.drawRoundRect(
0, 0,
iconPressed.getWidth(p) - 1,
iconPressed.getHeight(p) - 1,
12, 12);
g.dispose();
button.setPressedIcon(new ImageIcon(iconPressed));
button.setActionCommand("" + count);
button.addActionListener((ActionEvent ae) -> {
System.out.println(ae.getActionCommand());
});
p.add(button);
} else {
JLabel label = new JLabel(new ImageIcon(icon));
p.add(label);
}
count++;
}
}
JPanel center = new JPanel(new GridBagLayout());
center.setBackground(Color.BLACK);
center.add(p);
JOptionPane.showMessageDialog(null, center);
}
public static void main(String[] args) throws Exception {
URL url = new URL("https://i.stack.imgur.com/SNN04.png");
final BufferedImage bi = ImageIO.read(url);
SwingUtilities.invokeLater(() -> {
new CompassButtons(bi);
});
}
}
Problem
How can i have this image like below into the `slavePanel` and on top of that JPanel adjust the `JButtons` which looks like the image but having buttons correctly wrapped around? (Right now they are shaped in 1 row, 4 column) ``` // // Shot Gun mover up/down/left/right, middle on is for zoom // public void GunMover(JPanel configPanel) throws IOException { // Master Panel - holds everything JPanel masterPanel = new Panel(); masterPanel.setLayout(new SpringLayout()); // Slave Panel - with image background JPanel slavePanel = new Panel(); slavePanel.setLayout(new SpringLayout()); // Row 1 final JButton ptzLeft = new JButton("<"); masterPanel.add(ptzLeft, BorderLayout.WEST); // Row 2 final JButton ptzRight = new JButton(">"); masterPanel.add(ptzRight, BorderLayout.CENTER); // Row 3 final JButton ptzUp = new JButton("^"); masterPanel.add(ptzUp, BorderLayout.WEST); // Row 4 final JButton ptzDown = new JButton("down"); masterPanel.add(ptzDown, BorderLayout.CENTER); // How do i add slavePanel this background and add all the JButtons // According to that image shape? // Layout the panel. SpringUtilities.makeCompactGrid(masterPanel, 1, 4, //rows, cols 6, 6, //initX, initY 6, 6); configPanel.setLayout(new GridLayout(0,1)); configPanel.add(masterPanel); } ``` Follow up: Excellent one from `Andrew Thompson` + at-least my broken method ``` package test; import java.awt.*; import java.awt.font.FontRenderContext; import java.awt.font.TextLayout; import javax.swing.*; public class New extends JFrame { private static final long serialVersionUID = 1L; private ImageIcon errorIcon = (ImageIcon) UIManager.getIcon("OptionPane.errorIcon"); private Icon infoIcon = UIManager.getIcon("OptionPane.informationIcon"); private Icon warnIcon = UIManager.getIcon("OptionPane.warningIcon"); public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { New t = new New(); } }); } public New() { setLayout(new BorderLayout()); JPanel slavePanel = new NewPanel(); slavePanel.setLayout(new GridLayout(0, 2, 4, 4)); add(slavePanel); JButton button = new JButton(); button.setBorderPainted(false); button.setBorder(null); button.setFocusable(false); button.setMargin(new Insets(0, 0, 0, 0)); button.setContentAreaFilled(false); button.setIcon((errorIcon)); button.setRolloverIcon((infoIcon)); button.setPressedIcon(warnIcon); button.setDisabledIcon(warnIcon); slavePanel.add(button); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pack(); setVisible(true); } } package test; import java.awt.*; import java.io.IOException; import java.io.InputStream; import javax.imageio.ImageIO; import javax.swing.*; import javax.swing.border.Border; public class NewPanel extends JPanel { private Image imageGui; private static Dimension screen; public NewPanel() { try { imageGui = ImageIO.read( (InputStream) NewPanel.class.getResourceAsStream( "/image/ptz.png")); } catch (IOException e) { e.printStackTrace(System.err); } Border border = BorderFactory.createEmptyBorder(11, 11, 11, 11); setOpaque(true); setBorder(border); setFocusable(true); setSize(getPreferredSize()); revalidate(); repaint(); setVisible(true); } public void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(imageGui, 0, 0, imageGui.getWidth(null), imageGui.getHeight(null), null); revalidate(); repaint(); } @Override public Dimension getPreferredSize() { return new Dimension(imageGui.getWidth(null), imageGui.getHeight(null)); } } ```