Inside my borderlayout, i have JPanels which are referenced by the array theGrid. In a separate function, I want to change the look of a JPanel, so I change how the specific JPanel should be painted. The problem im having is that i dont know how i now make it paint this new version of the JPanel?
I have looked at other questions and have tried using .revalidate, .validate, .repaint(), etc on mainPanel or on contentPane, or on both but none will get the new version of the JPanel i created to be drawn on.
In the constructor below I setup the grid and how it will fit into the rest of the JFrame
public class GraphicDisplay extends JFrame {
private static int ROWS = 6;
private static int COLS = 7;
private JPanel[][] theGrid = new JPanel[ROWS][COLS];
private JPanel mainPanel = new JPanel(new GridLayout(ROWS, COLS));
private Container contentPane;
public GraphicDisplay() {
for (int i = 0; i < theGrid.length; i++) { //Initialize theGrid (with blanks)
for (int j = 0; j < theGrid[i].length; j++) {
theGrid[i][j] = new JPanel();
}
}
//add them to the JFrame
contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
JPanel boardElements = new JPanel();
boardElements.setLayout(new BoxLayout(boardElements, BoxLayout.Y_AXIS)); //vertical layout for the two parts, theGrid itself and then the
// button which goes underneath,
final int SPACE = 3;
final Color COLORCHOICE = Color.BLACK;
mainPanel.setBorder(BorderFactory.createEmptyBorder(SPACE, SPACE, SPACE, SPACE));
mainPanel.setBackground(COLORCHOICE);
JPanel[][] panels = new JPanel[ROWS][COLS];
for (int i = 0; i < panels.length; i++) {
for (int j = 0; j < panels[i].length; j++) {
panels[i][j] = new JPanel(new GridLayout(1, 1, 1, 1));
panels[i][j].setBackground(COLORCHOICE);
panels[i][j].setBorder(BorderFactory.createEmptyBorder(SPACE, SPACE, SPACE, SPACE));
mainPanel.add(panels[i][j]);
panels[i][j].add(theGrid[i][j]);
}
}
//adding the grid to the vertical layout
boardElements.add(mainPanel);
//adding the button which will go directly under the grid
boardElements.add(new JButton("Button"));
contentPane.add(boardElements, BorderLayout.CENTER);
}
The function below which is in the same class is suppose to update the grid by adding a dot at the point 3,3 (but the problem i don't see any visible change)
public void addDotToGrid() {
//theGrid[3][3] reference was added to the panels array which is part of the layout, so I would of thought by changing the value of it here would then change this JPanel on the UI
theGrid[3][3] = new JPanel() {
public void paintComponent( Graphics g) {
//g.setColor(Color.RED);
int y = 0;
int diameter = getWidth() -10;
int x = (getWidth()/2) - (diameter/2);
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
// Assume x, y, and diameter are instance variables.
Ellipse2D.Double circle = new Ellipse2D.Double(x, y, diameter, diameter);
g2d.fill(circle);
}
};
}
Main method in another class where GraphicDisplay object is created
public static void main(String[] args) {
GraphicDisplay display2 = new GraphicDisplay();
display2.setSize(600, 600);
display2.setVisible(true);
display2.addDotToGrid();
}
The problem is the grid is displayed but the addDotToGrid() does not change anything and there isn't a dot added to the gird
You're changing a JPanel held by your theGrid array, but this has no effect on the JPanels displayed in the GUI, and this gets to the key difference between a variable and a reference or object -- changing the object that a variable refers to has no effect on the object that it previously referred to. Your solution is to change the JPanel held by the grid.
One way to do this is to give all of them paintComponent methods that draw what you want, but have them controlled by a boolean, and then change the boolean variable of the panel of interest.
If this were my GUI though, I'd create a grid of JLabels and simply swap ImageIcons where and when I want -- keep it simple as possible!
For example
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
#SuppressWarnings("serial")
public class MyGridEg extends JPanel {
private static final int SPACE = 6;
private static final int ROWS = 6;
private static final int COLS = 7;
private static final int IMG_W = 80;
private static final int SML_GAP = 3;
private static final Color IMG_BACKG = new Color(240, 240, 240);
private static final String TITLE = "Click on a Cell";
private JLabel[][] labelGrid = new JLabel[ROWS][COLS];
private Icon blankIcon = createIconDisk(new Color(0, 0, 0, 0));
private Icon redIcon = createIconDisk(Color.RED);
public MyGridEg() {
MyMouse myMouse = new MyMouse();
JPanel gridHolder = new JPanel(new GridLayout(ROWS, COLS, SPACE, SPACE));
gridHolder.setBackground(Color.BLACK);
for (int i = 0; i < labelGrid.length; i++) {
for (int j = 0; j < labelGrid[i].length; j++) {
JLabel label = new JLabel(blankIcon);
label.addMouseListener(myMouse);
labelGrid[i][j] = label;
gridHolder.add(label);
}
}
gridHolder.setBorder(BorderFactory.createLineBorder(Color.black, SPACE));
JLabel titleLabel = new JLabel(TITLE, SwingConstants.CENTER);
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 20));
JButton clearButton = new JButton(new ClearAction("Clear"));
JPanel btnPanel = new JPanel();
btnPanel.add(clearButton);
setLayout(new BorderLayout());
add(gridHolder, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
add(titleLabel, BorderLayout.PAGE_START);
}
private Icon createIconDisk(Color color) {
BufferedImage img = new BufferedImage(IMG_W, IMG_W, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setBackground(IMG_BACKG);
g2.clearRect(0, 0, IMG_W, IMG_W);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(color);
int x = SML_GAP;
int y = x;
int width = IMG_W - 2 * x;
int height = IMG_W - 2 * y;
g2.fillOval(x, y, width, height);
g2.dispose();
return new ImageIcon(img);
}
private class MyMouse extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
JLabel selected = (JLabel) e.getSource();
Icon icon = selected.getIcon() == blankIcon ? redIcon : blankIcon;
selected.setIcon(icon);
}
}
private class ClearAction extends AbstractAction {
public ClearAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
for (JLabel[] labelRow : labelGrid) {
for (JLabel cell : labelRow) {
cell.setIcon(blankIcon);
}
}
}
}
private static void createAndShowGui() {
MyGridEg mainPanel = new MyGridEg();
JFrame frame = new JFrame("MyGridEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
The key to this code is that I'm not swapping out JLabels or JPanels but rather I'm keeping the JLabels the same, but am changing their state. This way if I change the state of the JLabels held by the 2D array, labelGrid, this is reflected by changes in the view, as I do in the ClearAction class that the clearButton JButton calls:
private class ClearAction extends AbstractAction {
public ClearAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
for (JLabel[] labelRow : labelGrid) {
for (JLabel cell : labelRow) {
cell.setIcon(blankIcon);
}
}
}
}
Related
I am working on Battleship project right now. I created two panels which i put in one frame. First panel is grid of buttons, and second panel is consist of draggable ship images. All I want, is when I drag the image into the certain button, it would appear on that button. In other words, i want just a simple addition of image into the JButton by dragging image into it.
Here is the full code:
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class BattleShip extends JFrame{
public BattleShip() throws IOException {
this.setResizable(false);
this.pack();
JPanel panelLeft = new JPanel();
JPanel panelRight = new JPanel();
panelLeft.setSize(500, 650);
panelRight.setSize(200,650);
panelRight.setBorder(BorderFactory.createLineBorder(Color.RED, 7));
panelRight.setBackground(Color.WHITE);
panelLeft.setLayout(new GridLayout(11,11));
panelRight.setLayout(null);
BufferedImage myPicture = ImageIO.read(new File("/home/hikmet/Desktop/595a7960d639a15d096a226d.png"));
BufferedImage[] resized = new BufferedImage[14];
for (int i = 0; i < 14; ++i) {
resized[i] = resize(myPicture, 20, 30);
}
JLabel[] img = new JLabel[14];
for (int i = 0; i < 14; ++i) {
img[i] = new JLabel((new ImageIcon(resized[i])));
}
Dimension size = img[0].getPreferredSize();
for (int i = 0; i < 14; ++i) {
panelRight.add(img[i]);
img[i].setBounds(7 + i * 50, 7, size.width, size.height);
}
JButton button[][] = new JButton[11][11];
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
button[i][j] = new JButton();
panelLeft.add(button[i][j]);
}
}
button[1][0].setText("A"); button[0][1].setText("1");
button[2][0].setText("B"); button[0][2].setText("2");
button[3][0].setText("C"); button[0][3].setText("3");
button[4][0].setText("D"); button[0][4].setText("4");
button[5][0].setText("E"); button[0][5].setText("5");
button[6][0].setText("F"); button[0][6].setText("6");
button[7][0].setText("G"); button[0][7].setText("7");
button[8][0].setText("H"); button[0][8].setText("8");
button[9][0].setText("I"); button[0][9].setText("9");
button[10][0].setText("J"); button[0][10].setText("10");
for (int i = 0; i < 14; i++) { //applying mouseEvent to each image
MouseHandler movement = new MouseHandler(img[i]);
}
this.setTitle("BattleShip");
this.setSize(700,700);
this.setLayout(new GridLayout(2,4));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.getContentPane().add(panelLeft);
this.getContentPane().add(panelRight);
}
//method for just resizing the size of image
private static BufferedImage resize(BufferedImage myPicture, int height, int width) {
Image tmp = myPicture.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage resized = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = resized.createGraphics();
g2d.drawImage(tmp,0,0,null);
g2d.dispose();
return resized;
}
//Class for handling mouseEvents
public class MouseHandler implements MouseMotionListener {
private int x, y;
public MouseHandler(JLabel img){
img.addMouseMotionListener(this);
}
#Override
public void mouseDragged(MouseEvent mouseEvent) {
mouseEvent.getComponent().setLocation((mouseEvent.getX()+mouseEvent.getComponent().getX())-x, (mouseEvent.getY()+mouseEvent.getComponent().getY())-y);
}
#Override
public void mouseMoved(MouseEvent mouseEvent) {
x = mouseEvent.getX();
y = mouseEvent.getY();
}
}
//Main class
public class Main {
public static void main(String[] args) throws IOException {
new BattleShip();
}
}
Hope someone will help me :)
You can specify the property to be dragged when you use the TransferHandler class:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DragIcon extends JPanel
{
public DragIcon()
{
setLayout( new BorderLayout(40, 20) );
TransferHandler iconHandler = new TransferHandler( "icon" );
// TransferHandler iconHandler = new TransferHandler( "text" );
MouseListener dragListener = new DragMouseAdapter();
JLabel dragLabel = new JLabel("Drag");
dragLabel.setTransferHandler( iconHandler );
dragLabel.addMouseListener(dragListener);
dragLabel.setIcon( new ImageIcon("copy16.gif") );
dragLabel.setHorizontalAlignment(JLabel.CENTER);
add(dragLabel, BorderLayout.PAGE_START);
JLabel label = new JLabel("Label");
label.setTransferHandler( iconHandler );
add(label, BorderLayout.LINE_START);
JButton button = new JButton("Button");
button.setTransferHandler( iconHandler );
add(button, BorderLayout.LINE_END);
}
private class DragMouseAdapter extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
JComponent c = (JComponent)e.getSource();
TransferHandler handler = c.getTransferHandler();
handler.exportAsDrag(c, e, TransferHandler.COPY);
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Drag Icon");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DragIcon());
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Hi I need to display a large content(its graphical data) of data in single, so I tried following code.
canvas.setPreferredSize(new Dimension(3000, 300));
canvas.setBackground(Color.blue);
JScrollPane jsp = new JScrollPane(canvas);
setPreferredSize(new Dimension(600, 500));
setLayout(new GridLayout(1, 0, 5, 0));
jsp.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener() {
#Override
public void adjustmentValueChanged(AdjustmentEvent e) {
System.out.println(e.getValue());
repaint();
}
});
add(jsp);
this is my MyCanvas class
class MyCanvas extends Canvas {
#Override
public void paint(Graphics g) {
super.paint(g);
System.out.println("paint");
g.setColor(Color.YELLOW);
for (int i = 0; i < 100; i++) {
g.drawString(""+i, i*30, 100);
// g.drawLine(10, 10, 20, 20);
}
}
}
but problem is that when I am scrolling window I cannot see full content as I expected it should print 100 numbers but not printed actually, can any one correct me?
see the result here
I recommend that you avoid mixing AWT and Swing components together (or if you absolutely must do this, then you have to make sure you understand the pitfalls and fully jump through all the necessary hoops.
Myself, I'd extend JPanel, I'd be sure that its preferredSize was where I want it, since this will determine how big it will be within the JScrollPane.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.*;
#SuppressWarnings("serial")
public class MyScrollExample extends JPanel {
private static final int MAX = 100;
private MyPanel myPanel = new MyPanel(MAX);
public MyScrollExample() {
JScrollPane scrollPane = new JScrollPane(myPanel);
scrollPane.getViewport().setPreferredSize(new Dimension(600, 200));
add(scrollPane);
}
private static void createAndShowGui() {
MyScrollExample mainPanel = new MyScrollExample();
JFrame frame = new JFrame("MyScrollExample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
#SuppressWarnings("serial")
class MyPanel extends JPanel {
private static final Color BG = Color.BLUE;
private static final Color FG = Color.YELLOW;
private static final int WIDTH_GAP = 30;
private static final int HEIGHT_GAP = 100;
private int max;
public MyPanel(int max) {
setBackground(BG);
this.max = max;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(FG);
for (int i = 0; i < max; i++) {
g.drawString("" + i, i * WIDTH_GAP, HEIGHT_GAP);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
int w = (WIDTH_GAP + 1) * max;
int h = HEIGHT_GAP * 3;
return new Dimension(w, h);
}
}
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));
}
}
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("http://i.stack.imgur.com/SNN04.png");
final BufferedImage bi = ImageIO.read(url);
SwingUtilities.invokeLater(() -> {
new CompassButtons(bi);
});
}
}
1) you have to prepare the Icons before and for every 5 JButtons (event here came from ButtonModel)
basic Icon without Focus
Icon for isRollover()
Icon for isPressed()
2) how to set Icons and to remove all "balast" from JButton
3) put these 5 JButtons to the JPanel with painted circles (RemoteSet)
Starting from this example, I got a start by changing MoveButton like this:
this.setBorderPainted(false);
You could give ControlPanel a Custom Layout Manager. I'd also add a background image and some kind of visual feedback based on the ButtonModel state, as suggested here.
I'm trying to create an applet that will produce as many ovals as the number specified within a textbox. The textbox appears, but upon hitting enter, my paintComponent does not draw. Thank you in advance.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import net.miginfocom.layout.*;
import net.miginfocom.swing.MigLayout;
import java.awt.geom.*;
public class OvalDrawer extends JApplet
{
private JLabel numberL;
private JTextField numberTF;
private NumHandler numHandler;
public static final int WIDTH = 500;
public static final int HEIGHT = 500;
//Create Layout
public void init()
{
setLayout(new MigLayout("wrap 2"));
numberL = new JLabel("Enter number of ovals to draw:");
numberTF = new JTextField(7);
add(numberL);
add(numberTF);
numHandler = new NumHandler();
numberTF.addActionListener(numHandler);
setSize(500, 500);
}
//Event Handler
public class NumHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
repaint();
}
}
//Draw Ovals
public void paintComponent (Graphics g)
{
super.paintComponents(g);
int number;
int x = 10;
int y = 30;
int width = 20;
int height = 10;
number = Integer.parseInt(numberTF.getText());
for (int i = 0; i < number; i++)
{
g.drawOval(x, y, width, height);
x += 5;
y += 5;
width += 5;
height += 5;
}
}
}
A JApplet class does not have a paintComponent method to override. Note that your compiler won't let you call the actual super method (you think you may be doing this, but you're actually calling super.paintComponents(...), a completely different method).
A bad solution is to override the JApplet's paint method, but I strongly advise you not to do this. Instead you should draw in the paintComponent method of a JPanel and then have the JApplet display that JPanel. Also, you'll want to get into the habit of using the #Override annotation to be sure that you're actually overriding methods you think are.
/* * <Applet code=PressButton2 width=600 height=600> * </Applet>
*/
import javax.swing.*; import java.awt.*; import java.awt.event.*;
class MyPanel extends JPanel {
static String s="n";
public void paintComponent(Graphics g) {
super.paintComponent(g);
if(s.equals("g"))
setBackground(Color.green);
if(s.equals("b"))
setBackground(Color.blue);
if(s.equals("c"))
setBackground(Color.white);
}
}
public class PressButton2 extends JApplet {
MyPanel panel;
MyPanel screen;
String s="n";
JButton green, clear, blue;
public void init() {
Container container = getContentPane();
panel = new MyPanel();
screen = new MyPanel();
panel.setLayout(new GridLayout(1, 3));
green = new JButton("Green");
blue = new JButton("Blue");
clear = new JButton("Clear");
green.addActionListener(new ActionEventHandler1());
blue.addActionListener(new ActionEventHandler1());
clear.addActionListener(new ActionEventHandler1());
panel.add(green);
panel.add(blue);
panel.add(clear);
container.add(panel, BorderLayout.SOUTH);
container.add(screen);
}
class ActionEventHandler1 implements ActionListener {
public void actionPerformed(ActionEvent e) {
String temp = e.getActionCommand();
if (temp.equals("Green")) {
MyPanel.s = "g";
screen.repaint();
}
if (temp.equals("Blue")) {
MyPanel.s = "b";
screen.repaint();
}
if (temp.equals("Clear")) {
MyPanel.s = "c";
screen.repaint();
}
}
}
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));
}
}
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("http://i.stack.imgur.com/SNN04.png");
final BufferedImage bi = ImageIO.read(url);
SwingUtilities.invokeLater(() -> {
new CompassButtons(bi);
});
}
}
1) you have to prepare the Icons before and for every 5 JButtons (event here came from ButtonModel)
basic Icon without Focus
Icon for isRollover()
Icon for isPressed()
2) how to set Icons and to remove all "balast" from JButton
3) put these 5 JButtons to the JPanel with painted circles (RemoteSet)
Starting from this example, I got a start by changing MoveButton like this:
this.setBorderPainted(false);
You could give ControlPanel a Custom Layout Manager. I'd also add a background image and some kind of visual feedback based on the ButtonModel state, as suggested here.