Hot questions for Using Applets in jpanel

Question:

How do I switch between JPanels in an applet? Switching between JPanels in a JFrame is very easy and I do it like this:

        frame.remove(mainMenu); //remove the old jpanel
        frame.add(game); //add the new jpanel
        game.createImage(); //runs createVolatileImage(width, height)
                            //in the other class (JPanel)
        frame.revalidate();
        frame.repaint();
        requestFocus();

However, how do I replicate this in an applet? When I try this in an applet, I get a nullPointerException when I try to run image.getGraphics() on the image that I created in the new JPanel.


Answer:

  1. The best way to switch JPanels is to use a CardLayout (tutorial). If done correctly, this will work whether your GUI is a JFrame, JDialog, JApplet,... et.
  2. Your NullPointerException likely has nothing to do with your swapping views. To debug this will require more information on your part.
  3. It is likely due to your image variable being null, perhaps due to trying to read it in as a File rather than as a resource.

Question:

I am trying to make a GUI for a battleship game. One class is for creating the GUI itself and a second class is on top of it to manage the board in the game. My problem is that the JPanel creates twice once a mouse click happens (the mouse click is supposed to be where one is firing in the game and then marks that as a hit/miss). I'm not sure why it is creating twice. Is it because of the passing of a panel? Code below and a photo of what the code generates.

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class BattleshipApplet extends JApplet implements MouseListener {
    private final JButton playButton = new JButton("Play");
    private final JLabel msgBar = new JLabel("Click Play to start game");
    private BoardPanel panel;



    public BattleshipApplet(){
        playButton.addActionListener(this::playButtonClicked);  
        addMouseListener(this);
    }

    public void init(){
        configureGui();
    }

    private void configureGui(){
        setLayout(new BorderLayout());
        JPanel buttons = new JPanel(new FlowLayout(FlowLayout.LEFT));
        buttons.setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
        buttons.add(playButton);
        add(buttons, BorderLayout.NORTH);
        msgBar.setBorder(BorderFactory.createEmptyBorder(10,10,5,5));
        add(createBoardPanel(), BorderLayout.CENTER);
        add(msgBar, BorderLayout.SOUTH);
    }

    private BoardPanel createBoardPanel(){
        panel = new BoardPanel();
        return panel;
    }

    private void displayMessage(String msg){
        msgBar.setText(msg);
    }

    private void playButtonClicked(ActionEvent event){
        displayMessage("Play button clicked!");
    }

    public void mouseClicked(MouseEvent e) {
        panel.mouseClickedAt(e.getX(), e.getY());
        e.consume();
    }


    public void mouseEntered(MouseEvent e) {
    }


    public void mouseExited(MouseEvent e) {
    }  
    public void mousePressed(MouseEvent e) {
    }
    public void mouseReleased(MouseEvent e) {
    }   
}

The board class using JPanel

[![import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;


public class BoardPanel extends JPanel  {
    int mx, my;
    boolean rect1Clicked;
    //gamePlay a;
    public void init(){

        rect1Clicked = false;

    }

    /***Your applet shall show the status of the board before and after
     each shot, including the number of shots made and the status of
     each place (no shot or hit/miss shot). ***/
    public void paint(Graphics g){
        boolean miss = false;


        for (int i=0; i<11; i++){ 
            g.setColor(Color.blue);
            g.drawLine(20,20+i*28, 300, 20+i*28);   
        }
        for (int i=0; i<11; i++)   
            g.drawLine(20+i*28,20,20+i*28,300);

        //if inside board 
        if(rect1Clicked == true){
            g.setColor(Color.green);
            //aligns to square to check in computer board for hit/miss
            int bx =(my-20)/28;
            int by =(mx-20)/28;



            //check hit on board
            //if shot was a miss
            if(miss == true ){
                //update to white
                g.setColor(Color.white);
            }
            //if shot was a hit
            if(miss == false){
                //update to red
                g.setColor(Color.red);
            }
            //compare to line for fill
            int fillx = mx/2;
            int filly = my/2 ;
            if(mx<=47){
                fillx = 20;
            }
            if(mx>47 && mx<=75){
                fillx = 48;
            }
            if(mx>75 && mx<=103){
                fillx = 76;
            }
            if(mx>103 && mx <=131){
                fillx = 104;
            }
            if(mx>131 && mx<=159){
                fillx = 132;
            }
            if(mx>159 && mx<=187){
                fillx = 160;
            }
            if(mx>187 && mx <=215){
                fillx = 188;
            }
            if(mx>215 && mx <=243){
                fillx = 216;
            }
            if(mx>243 && mx <=271){
                fillx = 244;
            }
            if(mx>271 && mx<=299){
                fillx = 272;
            }
            if(mx>299){
                fillx = 300;
            }
            //y comparisons
            if(my<=47){
                filly = 20;
            }
            if(my>47 && my<=75){
                filly = 48;
            }
            if(my>75 && my<=103){
                filly = 76;
            }
            if(my>103 && my <=131){
                filly = 104;
            }
            if(my>131 && my<=159){
                filly = 132;
            }
            if(my>159 && my<=187){
                filly = 160;
            }
            if(my>187 && my <=215){
                filly = 188;
            }
            if(my>215 && my <=243){
                filly = 216;
            }
            if(my>243 && my <=271){
                filly = 244;
            }
            if(my>271 && my<=299){
                filly = 272;
            }
            if(my>299){
                filly = 300;
            }


            g.drawString("("+mx+","+my+")",mx,my);
            //25 describes size of square 
            g.fillOval(fillx, filly, 25, 25);

        }


    }

    public void game(BoardPanel p){
        //while game plays
    }


    public void mouseClickedAt(int x, int y){

        mx = x;
        my = y;

        //user clicked inside of board space
        if(mx>20 && mx<300 && my>20 && my<300){       

            //send to board in MainBattleship
            rect1Clicked = true;

        }
        //updates board
        repaint();
    }


}][1]][1]

I am so lost, thank you for any help!


Answer:

Suggestions:

  1. Don't override a JPanel's paint method but rather its paintComponent method as this is safer, and later when you want to do animation, will result in smoother animation.
  2. Most important you almost always need to call the super's painting method within your own, else the JPanel will not remove previous image artifacts that need to be cleaned up. So if you continue to override paint (although I recommend against, this) the first line of your override should be super.paint(g);, or if you override paintComponent then the first line should be super.paintComponent(g);, of course assuming that you're methods use a Graphics parameter named g.
  3. Also, add the MouseListener to the JPanel, not to the applet, since it is the mouse click location on the panel that matters to you.
  4. Also, use a grid of components or some math to greatly simplify your code -- that ugly list of if blocks should be replaced by a much simpler for loop, one using basic math.
  5. Consider extracting that logic discussed in the point above out of your painting method and into a model of some kind, perhaps a 2D array of boolean.
  6. You're using a lot of "magic" numbers in your code, numbers that should be changed to a combination of constants and mathematically derived numbers.
  7. Notice what happens if you click on your GUI, and then resize it, or if you minimize and then restore it -- you lose all red circles except for the last one pressed. This is another reason to use a grid of boolean or other model to hold state of the game, and then use this model when drawing your GUI.
  8. On further thinking, you might want a 2D array of an enum or an int array, since the grid cell state will likely be more than 2 values (true or false), but rather will be three values -- untested, hit, and miss, and you'll likely want to fill your oval with red if a hit or white if a miss.

For example:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.*;
import javax.swing.*;

public class GridExample {
    private static void createAndShowGui() {
        final GridPanel gridPanel = new GridPanel();

        JButton resetBtn = new JButton(new AbstractAction("Reset") {

            @Override
            public void actionPerformed(ActionEvent e) {
                gridPanel.reset();
            }
        });
        JPanel btnPanel = new JPanel();
        btnPanel.add(resetBtn);

        JFrame frame = new JFrame("GridExample");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(gridPanel);
        frame.getContentPane().add(btnPanel, BorderLayout.PAGE_END);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }
}

@SuppressWarnings("serial")
class GridPanel extends JPanel {
    private static final int ROWS = 10;
    private static final int CELL_WIDTH = 28;
    private static final int PAD = 20;
    private static final int PREF_W = ROWS * CELL_WIDTH + 2 * PAD;
    private static final int PREF_H = PREF_W;
    private static final Color GRID_COLOR = Color.blue;
    private static final Color CIRCLE_COLOR = Color.red;
    private static final int SML_GAP = 2;
    private boolean[][] grid = new boolean[ROWS][ROWS];

    public GridPanel() {
        addMouseListener(new MyMouse());
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    public void reset() {
        grid = new boolean[ROWS][ROWS]; // fills grid with false
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // draw grid:
        g2.setColor(GRID_COLOR);
        for (int i = 0; i <= ROWS; i++) {
            int x1 = PAD + i * CELL_WIDTH;
            int y1 = PAD;
            int x2 = x1;
            int y2 = PAD + CELL_WIDTH * ROWS;
            g2.drawLine(x1, y1, x2, y2);
            g2.drawLine(y1, x1, y2, x2);
        }

        // iterate through the grid boolean array
        // draw red circles if the grid value is true.
        g2.setColor(CIRCLE_COLOR);
        int w = CELL_WIDTH - 2 * SML_GAP; // width of the circle to draw
        int h = w;
        // nested for loop to go through the grid array
        for (int r = 0; r < grid.length; r++) {
            for (int c = 0; c < grid[r].length; c++) {
                if (grid[r][c]) {
                    int x = PAD + c * CELL_WIDTH + SML_GAP;
                    int y = PAD + r * CELL_WIDTH + SML_GAP;
                    g2.fillOval(x, y, w, h);
                }
            }
        }        
    }

    private class MyMouse extends MouseAdapter {
        public void mousePressed(MouseEvent e) {
            int x = e.getPoint().x;
            int y = e.getPoint().y;

            if (x < PAD || y < PAD) {
                // clicked above or to right of grid
                return;
            }

            int r = (y - PAD) / CELL_WIDTH;
            int c = (x - PAD) / CELL_WIDTH;

            // if clicked to right or below grid.
            // the < 0 part is likely unnecessary, but why not be extra safe?
            if (r >= ROWS || c >= ROWS || r < 0 || c < 0) {
                return;
            }
            grid[r][c] = true;
            repaint();
        }
    }
}

Question:

I Have a JPanel and a Applet inside a JFrame, and im tryng to align them like this:

Im almost loosing my hair on this as it seems so hard to align...

This is my actual snippet:

The JFrame is opening very small with only the button on it.

 final JFrame f = new JFrame();

    JPanel appletPanel = new JPanel();
    appletPanel.setBackground(Color.RED);

    JPanel menuPanel = new JPanel();
    menuPanel.setBackground(Color.BLUE);


    f.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();

   // f.setExtendedState(JFrame.MAXIMIZED_BOTH);
   // f.setResizable(false);
    int w = Toolkit.getDefaultToolkit().getScreenSize().width;
    int h = Toolkit.getDefaultToolkit().getScreenSize().height;

    f.setSize(Toolkit.getDefaultToolkit().getScreenSize());
    VNCApplet applet = new VNCApplet();

    menuPanel.add(new JButton("TEST"));

    appletPanel.setSize((int)(w*0.7),h);
    menuPanel.setSize((int)(w*0.3),h);

    c.gridx = 0;
    c.gridy = 0;

    f.getContentPane().add(appletPanel,c);

    c.gridx = 0;
    c.gridy = 1;


    f.getContentPane().add(menuPanel,c);

    f.pack();
    applet.init();
    applet.start();
    f.setVisible(true);

Thanks alot for the attention !


Answer:

That layout could be achieved a number of ways using a single layout (e.g. a GridBagLayout or a GroupLayout) but I'd do it as a combination of layouts. Like this:

import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;

public class AppletWithButtonsOnRight {

    private JComponent ui = null;

    AppletWithButtonsOnRight() {
        initUI();
    }

    public void initUI() {
        if (ui!=null) return;

        ui = new JPanel(new BorderLayout(4,4));
        ui.setBorder(new TitledBorder("BorderLayout(4,4)"));

        JPanel appletPanel = new JPanel(new GridLayout());
        appletPanel.setBackground(Color.RED);
        appletPanel.add(new JLabel(new ImageIcon(new BufferedImage(400, 300, BufferedImage.TYPE_INT_ARGB))));
        ui.add(appletPanel);

        JPanel menuPanel = new JPanel(new BorderLayout());
        menuPanel.setBorder(new TitledBorder("BorderLayout()"));
        ui.add(menuPanel, BorderLayout.LINE_END);

        JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 10, 10));
        buttonPanel.setBorder(new TitledBorder("GridLayout(0,1,10,10)"));
        menuPanel.add(buttonPanel, BorderLayout.PAGE_START);

        for (int i=1; i<5; i++) {
            JButton b = new JButton("Button " + i);
            b.setFont(b.getFont().deriveFont(24f));
            buttonPanel.add(b);
        }
    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception useDefault) {
                }
                AppletWithButtonsOnRight o = new AppletWithButtonsOnRight();

                JFrame f = new JFrame(o.getClass().getSimpleName());
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setLocationByPlatform(true);

                f.setContentPane(o.getUI());
                f.pack();
                f.setMinimumSize(f.getSize());

                f.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

Question:

I'm trying to finish homework given to me, I was asked to create a "painter" that paints rectangles and circles, with the ability to remove them using the minus button etc.. The last task was to make the application able to run both as an applet and an application.. I tried to follow my teacher's instructions on how to make an application to work both as an applet and an application and now the panels show on the frame only in the applet mode.

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.*;
public class HW4 extends JApplet {
private final String[] EraseComboBoxList = { "None", "All", "Rect",
        "Circle" };
private final Dimension EraseShapeColorPanelDim = new Dimension(130, 65);
private final Dimension ControlPanelDim = new Dimension(200, 600);
private final int PanelsBorderThickness = 3;
private final int ControlPanelHGap = 50;
private final int ControlPanelVGap = 20;
private final static int FrameHGap = 10;
private final static int FrameVGap = 0;
private final static Dimension FramePanelDim = new Dimension(800, 600);
private JTextArea drawnShapes = new JTextArea(11, 12);
private ArrayList<Shape> shapeList = new ArrayList<Shape>();
private static Shape tempShape;
private boolean draw = false;
ControlPanel controlPanel = new ControlPanel(); 
PainterPanel paintPanel = new PainterPanel();

public HW4() {
    tempShape = new Shape();
    setBackground(Color.LIGHT_GRAY);
    add(paintPanel, BorderLayout.CENTER);
    setANDrequestFocus();
    add(controlPanel, BorderLayout.EAST);
}
public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.add(new HW4());
    frame.setSize(FramePanelDim);
    frame.setTitle("My Painter");
    frame.setLayout(new BorderLayout(FrameHGap, FrameVGap));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.setResizable(false);
    frame.setAlwaysOnTop(true);
    frame.setVisible(true);
}

private class PainterPanel extends JPanel {

    private PainterPanel() {
        setBorder(new LineBorder(Color.GRAY, PanelsBorderThickness));
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent mouseRelease) {
                if ((Math.abs(tempShape.startX - tempShape.width) + Math
                        .abs(tempShape.startY - tempShape.height)) != 0) {
                    Shape shape = new Shape();
                    shape.color = tempShape.color;
                    shape.shape = tempShape.shape;
                    shape.filled = tempShape.filled;
                    shape.startX = tempShape.startX;
                    shape.startY = tempShape.startY;
                    shape.width = tempShape.width;
                    shape.height = tempShape.height;
                    shapeList.add(shape);
                    appendToTextArea(shape);
                }
                draw = false;
            }

            @Override
            public void mousePressed(MouseEvent mousePress) {

                tempShape.startX = mousePress.getX();
                tempShape.startY = mousePress.getY();
                tempShape.width = mousePress.getX();
                tempShape.height = mousePress.getY();
                draw = true;
            }
        });
        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent mouseDrag) {
                tempShape.width = mouseDrag.getX();
                tempShape.height = mouseDrag.getY();
                repaint();
            }
        });
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        int startX, startY, width, height;
        setANDrequestFocus();
        for (int i = 0 ; i < shapeList.size() ; i++) {
            startX = Math.min(shapeList.get(i).startX, shapeList.get(i).width);
            startY = Math.min(shapeList.get(i).startY, shapeList.get(i).height);
            width = Math.abs((shapeList.get(i).startX - shapeList.get(i).width));
            height = Math.abs((shapeList.get(i).startY - shapeList.get(i).height));
            g2d.setColor(shapeList.get(i).color);
            g2d.setStroke(new BasicStroke(3));
            if ((width != 0) && (height != 0)) {
                if (shapeList.get(i).shape.equals("Rect")) {
                    if (shapeList.get(i).filled) {
                        g2d.fillRect(startX, startY, width, height);
                    } 
                    else {
                        g2d.drawRect(startX, startY, width, height);
                    }
                } 
                else {
                    if (shapeList.get(i).filled) {
                        g2d.fillOval(startX, startY, width, height);
                    } 
                    else {
                        g2d.drawOval(startX, startY, width, height);
                    }
                }
            }
        }
        if (draw) {
        startX = Math.min(tempShape.startX, tempShape.width);
        startY = Math.min(tempShape.startY, tempShape.height);
        width = Math.abs(tempShape.startX - tempShape.width);
        height = Math.abs(tempShape.startY - tempShape.height);
        g2d.setColor(tempShape.color);
        g2d.setStroke(new BasicStroke(3));
        if ((width != 0) && (height != 0)) {
            if (tempShape.shape.equals("Rect")) {
                if (tempShape.filled) {
                    g2d.fillRect(startX, startY, width, height);
                } 
                else {
                    g2d.drawRect(startX, startY, width, height);
                }
            } 
            else {
                if (tempShape.filled) {
                    g2d.fillOval(startX, startY, width, height);
                } 
                else {
                    g2d.drawOval(startX, startY, width, height);
                }
            }
        }
    }
    }
}

private class ControlPanel extends JPanel implements ActionListener {
    private JComboBox<String> eraseComboBox = new JComboBox<String>(EraseComboBoxList);
    private JPanel erasePanel;
    private JScrollPane scrollPane = new JScrollPane(drawnShapes,
            JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
            JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    private JPanel shapePanel;
    private JRadioButton shapeRect = new JRadioButton("Rect", true);
    private JRadioButton shapeCircle = new JRadioButton("Circle");
    private JPanel colorPanel;
    private JRadioButton colorRed = new JRadioButton("Red");
    private JRadioButton colorBlue = new JRadioButton("Blue", true);
    private JCheckBox fillCheckBox = new JCheckBox("Fill");
    private ControlPanel() {
        createControlPanel();
    }
    public void createControlPanel() {
        setLayout(new FlowLayout(FlowLayout.CENTER, ControlPanelHGap,
                ControlPanelVGap));
        setPreferredSize(ControlPanelDim);
        createErasePanel();
        createShapePanel();
        createColorPanel();
        createFillCheckBox();
        addKeyListeners();
        drawnShapes.setEditable(false);
        add(erasePanel);
        add(shapePanel);
        add(colorPanel);
        add(fillCheckBox);
        add(scrollPane);
        setBorder(new LineBorder(Color.GRAY, PanelsBorderThickness));
    }
    public void createErasePanel() {
        erasePanel = new JPanel();
        erasePanel.setBorder(new TitledBorder("Erase"));
        eraseComboBox.setToolTipText("Please select which type of shapes you would like to remove");
        eraseComboBox.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (eraseComboBox.getSelectedItem().equals("Rect")) {
                    for (int i = 0; i < shapeList.size(); i++) {
                        if ((shapeList.get(i).shape).equals("Rect")) {
                            shapeList.remove(i);
                            --i;
                        }
                    }
                    removeReWriteTextArea();
                    paintPanel.repaint();
                }
                if (eraseComboBox.getSelectedItem().equals("Circle")) {
                    for (int i = 0; i < shapeList.size(); i++) {
                        if ((shapeList.get(i).shape).equals("Circle")) {
                            shapeList.remove(i);
                            --i;
                        }
                    }
                    removeReWriteTextArea();
                    paintPanel.repaint();
                }
                if (eraseComboBox.getSelectedItem().equals("All")) {
                    for (int i = 0; i < shapeList.size(); i++) {
                            shapeList.remove(i);
                            --i;
                    }
                    removeReWriteTextArea();
                    paintPanel.repaint();
                }
            }
        });
        erasePanel.add(eraseComboBox);
        erasePanel.setPreferredSize(EraseShapeColorPanelDim);
    }
    public void createShapePanel() {
        shapePanel = new JPanel();
        shapePanel.setBorder(new TitledBorder("Shape"));
        ButtonGroup shapeGroup = new ButtonGroup();
        shapeGroup.add(shapeRect);
        shapeGroup.add(shapeCircle);
        shapeRect.setMnemonic('R');
        shapeCircle.setMnemonic('C');
        shapeRect.addActionListener(this);
        shapeCircle.addActionListener(this);
        shapePanel.add(shapeRect);
        shapePanel.add(shapeCircle);
        shapePanel.setPreferredSize(EraseShapeColorPanelDim);
    }
    public void createColorPanel() {
        colorPanel = new JPanel();
        colorPanel.setBorder(new TitledBorder("Color"));
        ButtonGroup colorGroup = new ButtonGroup();
        colorGroup.add(colorRed);
        colorGroup.add(colorBlue);
        colorRed.setMnemonic('e');
        colorBlue.setMnemonic('B');
        colorBlue.addActionListener(this);
        colorRed.addActionListener(this);
        colorPanel.add(colorRed);
        colorPanel.add(colorBlue);
        colorPanel.setPreferredSize(EraseShapeColorPanelDim);
    }
    public void createFillCheckBox() {
        fillCheckBox.setMnemonic('F');
        fillCheckBox.addActionListener(this);
    }
    public void addKeyListeners() {
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_MINUS) {
                    if (shapeList.size() > 0) {
                    shapeList.remove(shapeList.size()-1);
                    shapeList.trimToSize();
                    removeReWriteTextArea();
                    paintPanel.repaint();
                    }
                }
            }
        });
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        tempShape.shape = "Rect";
        if (shapeCircle.isSelected()) {
            tempShape.shape = "Circle";
        }
        tempShape.color = Color.BLUE;
        if (colorRed.isSelected()) {
            tempShape.color = Color.RED;
        }
        tempShape.filled = false;
        if (fillCheckBox.isSelected()) {
            tempShape.filled = true;
        }
    }
}

private class Shape {
    private boolean filled = false;
    private Color color = Color.BLUE;
    private String shape = "Rect";
    private int startX, startY, width, height;
    public String getColorString() {
        if (color == Color.RED) {
            return "Red";
        }
        else {
            return "Blue";
        }
    }
}
private void setANDrequestFocus() {
    controlPanel.setFocusable(true);
    controlPanel.requestFocusInWindow();
}
public void removeReWriteTextArea() {
    drawnShapes.setText(null);
    for(int i = 0; i < shapeList.size(); i++) {
        appendToTextArea(shapeList.get(i));
    }
}
public void appendToTextArea(Shape shape) {
    String append = shape.shape + ", " + shape.getColorString() + ", " + "fill = " + shape.filled;
            drawnShapes.append(append + "\n");
}
}

Answer:

The simplistic solution is:

public static void main(String[] args) {
    JFrame frame = new JFrame();
    JApplet hw4 = new HW4();
    hw4.init();
    hw4.start();
    frame.add(hw4);
    frame.setSize(FramePanelDim);
    frame.setTitle("My Painter");
    //frame.setLayout(new BorderLayout(FrameHGap, FrameVGap));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    //frame.setResizable(false);
    //frame.setAlwaysOnTop(true);
    frame.setVisible(true);
    frame.pack();
}

Note that:

  1. 'adding an applet to a frame' is not the best way to go about creating an hybrid. It is better to create the GUI in a JPanel that is added to the JApplet or JFrame (or another JPanel or a JDialog or..) as needed.
  2. We should not try to create a constructor for an applet, and if we do, we should beware the fact that it is not called on the EDT.
  3. Please refer the teacher to Why CS teachers should stop teaching Java applets.

Question:

first post here so forgive me if this is the absolute wrong thing but I'm in a tiny bit of a pickle. - My computer science class has us making our own game/program from scratch, but our teacher specifically ignored the existence of swing and said that it was out of his realm to teach it so from my readings it seems as if a game is almost out of the question, with what I've written so far my main sprite and debugging information flickers violently on key input. Is there a way around this?

I know JPanel/JFrame/Swing would fix this, but we weren't taught it and all I've read so far is confusing me to no end, if someone would be able to help me convert my code to use it that would be amazing as I learn easier from dissecting it.. Which may seem a bit dodgy but it really is the easiest way to learn from. My code so far is;

public class GameThing extends Applet implements KeyListener {

    Image rightsprite, picture;
    Image leftsprite, picture2;
    Image spritedead, picture3;
    Image background, picture4;

    boolean left;
    boolean dead;
    boolean wall;
    boolean menu;

    int widthX, heightY;
    int bgx, bgy;
    String sr = " ";
    char ch = '*';
    Graphics bufferGraphics;
    Image offscreen;
    Dimension dim;

    @Override
    public void init() {
        rightsprite = getImage(getDocumentBase(), "SpriteRight.png");
        leftsprite = getImage(getDocumentBase(), "SpriteLeft.png");
        spritedead = getImage(getDocumentBase(), "Sprite.png");
        background = getImage(getDocumentBase(), "Background.png");
        requestFocus();
        addKeyListener(this);
        left = false;
        menu = true;
        setSize(600, 380);
        dim = getSize();
        offscreen = createImage(dim.width, dim.height);
        bufferGraphics = offscreen.getGraphics();
        bgx = 0;
        bgy = 0;
    }

    public void pause(final int delay) { // PAUSE COMMAND LIFTED FROM RAY
        // waits a while
        try {
            Thread.sleep(delay);
        } catch (InterruptedException e) {
            return;
        }
    }

    public GameThing() { // SPRITE INITIAL SPAWN LOCATION
        widthX = 100;
        heightY = 300;
    }

    @Override
    public void paint(final Graphics g) { // DRAW MAIN CHARACTER SPRITE AND BACKGROUND
        bufferGraphics.setColor(Color.black); // DRAW GROUND (REPLACE WITH BLOCKS SOON)
        bufferGraphics.drawRect(0, 334, 500, 50);
        bufferGraphics.setColor(Color.green);
        bufferGraphics.fillRect(0, 335, 500, 50);
        g.drawImage(offscreen, 0, 0, this);
        if (menu == true) {
            pause(500);
            g.drawString("Side Scroller Test.", 180, 250);
            pause(1500);
            menu = false;
        }

        if (left == false) { // LEFT KEY MOVEMENT COMMANDS
            g.drawImage(rightsprite, widthX, heightY, this);
            g.drawString("Sprites Current X Location is: " + widthX, 20, 30);
            g.drawString("Sprites Current Y Location is: " + heightY, 20, 50);
            g.drawString("Background X location is: " + bgx, 20, 90);
            g.drawString("Currently: " + sr, 20, 70);

        }

        if (left == true) { // RIGHT KEY MOVEMENT COMMANDS
            g.drawImage(leftsprite, widthX, heightY, this);
            g.drawString("Sprites Current X Location is: " + widthX, 20, 30);
            g.drawString("Sprites Current Y Location is: " + heightY, 20, 50);
            g.drawString("Background X location is: " + bgx, 20, 90);
            g.drawString("Currently: " + sr, 20, 70);
        }

        if (dead == true) { // COMMANDS TO EXECUTE WHEN MAIN CHARACTER DIES
            widthX = 506;
            heightY = 314;
            g.drawImage(spritedead, widthX, heightY, this);
            pause(500);
            g.setColor(Color.white);
            g.drawRect(widthX, heightY, widthX, heightY);
            g.fillRect(widthX, heightY, widthX, heightY);
            pause(500);
            widthX = 100;
            heightY = 300;
            bgx = 0;
            left = true;
            dead = false;
        }

    }

    @Override
    public void update(final Graphics g) { // KEEPS BACKGROUND STATIC
        paint(g);
    }

    public void keyPressed(final KeyEvent e) {
        sr = "blank!";
        ch = '1';
        if (e.getKeyCode() == 39) {
            sr = "Moving Right!";
            widthX = widthX + 7;

            if (widthX <= 121) {
                bgx = bgx;
            } else {
                bgx = bgx - 7;
            }

            left = false;

            if ((widthX > 490) && (heightY > 300)) { // FALL DEATH

                sr = "You Died!";
                widthX = 900;
                heightY = 900;
                dead = true;
            }

            if (widthX == 499) {
                heightY = heightY + 7;
            }
        }

        if (widthX == 2) {
            wall = true;
        }

        if (e.getKeyCode() == 37) {

            if (wall == true) {
                sr = "Wall!";
                if (widthX > 2) {
                    wall = false;
                }
            }
            if (wall == false) {
                sr = "Moving Left!";
                widthX = widthX - 7;
                if (bgx >= 0) {
                    bgx = bgx;
                } else {
                    bgx = bgx + 7;
                }
                left = true;
            }
        }

        if (e.getKeyCode() == 38) {
            sr = "Jumping!";
        }
        repaint();
    }

    public void keyTyped(final KeyEvent e) {
        ch = e.getKeyChar();
        repaint();
    }

    public void keyReleased(final KeyEvent e) {
    } // key released
}

ps: Jumping with the up key has been a problem too, I can't simply add to the Y variable and then subtract as it just goes so fast it's as if it never moved.. The basics of a sidescroller are a lot more than I ever expected..


Answer:

I edited your code:

public class GameThing extends Applet {

    // External resources
    BufferedImage rightSprite, leftSprite, spriteDead, backgroundImg;

    // Game data
    int state = 1; //0 = left, 1 = right, 2 = dead

    // Geometry
    int locX = 100, locY = 300;
    int bgX = 0, bgY = 0;
    int groundX = 0, groundY = 334, groundW = 500, groundH = 50;
    int appletW = 600, appletH = 480;
    int wallW = 20, wallH = 40, wallX = 20, wallY = groundY - wallH;
    final int STEP_SIZE = 7;

    // Information
    final String X_LOC_STR = "Sprites Current X Location is: ";
    final String Y_LOC_STR = "Sprites Current Y Location is: ";
    final String STATE_STR = "Currently: ";
    final String X_BG_STR = "Background X location is: ";
    String stateString = "";

    // Double buffering
    Image offscreen;
    Graphics bufferGraphics;
    Dimension dim;

    // GUI components
    Panel gamePanel;
    Panel statusPanel = new Panel();
    Label xLocLabel = new Label();
    Label yLocLabel = new Label();
    Label stateLabel = new Label();
    Label xBGLocLabel = new Label();

    @Override
    public void init() {

        // Load images
        try {
            rightSprite = ImageIO.read(new File(getClass().getResource("SpriteRIght.png").getPath()));
            leftSprite = ImageIO.read(new File(getClass().getResource("SpriteLeft.png").getPath()));
            spriteDead = ImageIO.read(new File(getClass().getResource("SpriteDead.png").getPath()));
            backgroundImg = ImageIO.read(new File(getClass().getResource("Background.png").getPath()));
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Set the panel that displays data
        statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.Y_AXIS));
        statusPanel.add(xLocLabel);
        statusPanel.add(yLocLabel);
        statusPanel.add(stateLabel);
        statusPanel.add(xBGLocLabel);

        // Create the panel that draws the game and specify its behavior
        gamePanel = new Panel() {

            // Reduces flickering
            @Override
            public void update(Graphics g) {

                paint(g);
            }

            // DRAW MAIN CHARACTER SPRITE AND BACKGROUND
            @Override
            public void paint(Graphics g) {

                bufferGraphics.clearRect(0, 0, dim.width, dim.width);
                bufferGraphics.drawImage(backgroundImg, bgX, bgY, this);
                bufferGraphics.setColor(Color.BLACK); // DRAW GROUND (REPLACE WITH BLOCKS SOON)
                bufferGraphics.drawRect(groundX, groundY, groundW, groundH);
                bufferGraphics.setColor(Color.GREEN);
                bufferGraphics.fillRect(groundX, groundY + 1, groundW, groundH);
                bufferGraphics.setColor(Color.RED);
                bufferGraphics.fillRect(wallX, wallY, wallW, wallH);

                switch (state) {
                    case 0: bufferGraphics.drawImage(leftSprite, locX, locY, this);
                            break;
                    case 1: bufferGraphics.drawImage(rightSprite, locX, locY, this);
                            break;
                    case 2: bufferGraphics.drawImage(spriteDead, locX, locY, this);
                            // After death wait a bit and reset the game
                            EventQueue.invokeLater(new Runnable() {

                                @Override
                                public void run() {

                                    pause(2000);
                                    reset();
                                }
                            });
                            break;
                }
                g.drawImage(offscreen, 0, 0, this);
            }
        };

        // Set the applet window
        setLayout(new BorderLayout());
        add(statusPanel, BorderLayout.PAGE_START);
        add(gamePanel);

        // Set double buffering
        setSize(appletW, appletH);
        dim = getSize();
        offscreen = createImage(dim.width, dim.height);
        bufferGraphics = offscreen.getGraphics();

        // Set the panel that draws the game
        gamePanel.addKeyListener(new Controls());
        gamePanel.requestFocusInWindow();

        updateLabels();
    }   

    // PAUSE COMMAND LIFTED FROM RAY (who is Ray?)
    // waits a while
    public void pause(int delay) {

        try {
            Thread.sleep(delay);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // Set to start parameters
    public void reset() {

        locX = 100; locY = 300;
        bgX = 0;
        state = 1;
        gamePanel.repaint(); // These 2 lines automatically restart the game
        updateLabels();      // Remove if you want to stay on the death screen until next press
    }

    public void updateLabels() {

        xLocLabel.setText(X_LOC_STR + locX);
        yLocLabel.setText(Y_LOC_STR + locY);
        stateLabel.setText(STATE_STR + stateString);
        xBGLocLabel.setText(X_BG_STR + bgX);
    }

    private class Controls extends KeyAdapter {

        public void keyPressed(KeyEvent e) {

            switch (e.getKeyCode()) {

                case KeyEvent.VK_RIGHT:
                    stateString = "Moving Right!";
                    locX += STEP_SIZE;
                    state = 1;
                    if (locX > 121)
                        bgX -= STEP_SIZE;
                    // FALL DEATH
                    if ((locX > 490) && (locY > 300)) {
                        stateString = "You Died!";
                        state = 2;
                    }
                    // Start fall
                    if (locX == 499)
                        locY += STEP_SIZE;
                    // Check wall collision
                    if (locX >= wallX && locX <= wallX + wallW) {
                        locX -= STEP_SIZE;
                        stateString = "Wall!";
                    }
                    break;

                case KeyEvent.VK_LEFT:
                    stateString = "Moving Left!";
                    locX -= STEP_SIZE;
                    state = 0;

                    if (bgX < 0) 
                        bgX += STEP_SIZE;
                    // Check wall collision
                    if (locX >= wallX && locX <= wallX + wallW) {
                        locX += STEP_SIZE;
                        stateString = "Wall!";
                    }
                    break;

                case KeyEvent.VK_UP:
                    // Implement jumping
                    stateString = "Jumping!";
                    break;
            }

            // Repaint the game panel and update the data panel
            gamePanel.repaint();
            updateLabels();
        }
    }
}

Start by testing and understanding the changes:

  • I created a separate panel for the current data display and one for the game (which gets repainted).
  • I added a few help functions.
  • I made a lot of syntax changes (e.g. multiple if else replaced by switch, VK_UP instead of 37 and such).
  • Better to have all values in one place and read them from there instead of spreading them in various places (still needs a bit of work but it will change when advancing with the code).
  • Make constant values (values that don't change) final.
  • In Java conventions, constants are named with uppercase and underscore (_) (so Color.RED, not Color.red).
  • Better to use @Override when overriding methods even when the compiler understands it.
  • Do not block the event dispatch thread (EDT) with sleep or expensive computations. Methods like paint key events are meant to execute quickly. I used invokeLater to pause only after the EDT finished processing all queued events. (I understand that this threading subject comes as a bomb from nowhere, just bear with me).

Looking forward for the current state of the code (no new features):

  • state should probably be an enum or something close to it instead of random numbers.
  • Using Shape for drawn objects instead of specifying their parameters during painting.

Double buffering implementation notes:

You create an off-screen Image object offscreen and a Graphics object to draw on it - bufferGraphics. Insidepaint, you use only bufferGraphics for the drawings. You in fact draw on offscreen even though the paint belongs to gamePanel (or any other object and its paint), slightly confusing. When you finish drawing everything off-screen, you throw it all in one go onto the screen with g.drawImage(offscreen...) which uses gamePanel's Graphics object g.

The idea is like drawing everything on a paper and then putting it in front of the camera instead of drawing bit by bit on the camera, or something like that...

Currently, the off-screen image is the size of the whole applet and not just the game panel, but it makes little difference.

Relevant differences from a Swing approach:

  • Replace Label with JLabel, Panel with JPanel etc.
  • Swing components automatically implement double buffering (see JComponent's setDoubleBuffered and isDoubleBuffered). Remove all of those off-screen shenanigans and draw directly with Graphics g. No need to override update also.
  • Painting in Swing is done in paintComponent and not in paint.
  • Swing runs from its own thread and not from the EDT (not automatically, but easily done). There are some benefits to this I won't get into right now.
  • Key events are better handled by key bindings (Swing only) rather than the key listener. This manifests in responsiveness, native environment independence and more (e.g. concurrent key events).

Question:

I have following two classes whose basical purpose to create an array of objects...

class MovieInfo
    { private String movieTitle;
      private String movieRating;
      private String movieImg;
      private String movieShowTimes;
      private static double adultPrice;
      private static double childPrice;
    MovieInfo(String title, String rating, String img, String showTimes)
      { 
         movieTitle = title;
          movieRating = rating;
         movieImg = img;
         movieShowTimes = showTimes;

      }
    /*....sets gets methods.... */
    }

    ///////////////////////////////
    class MovieList
    {

      MovieInfo[] mList;

      public void createList()
      {

         mList = new MovieInfo[22];

      mList[0] = new MovieInfo("A United Kingdom","PG","A_United_Kingdom.jpg","yyyn");
     mList[1] = new MovieInfo("Amitiville The Awakening","18A","AmitivilleAwakening.jpg","yyyn");
     mList[2] = new MovieInfo("Arrival","14A","arrival.jpg","yyyy");
     mList[3] = new MovieInfo("Baywatch","14A","baywatch.jpg","yyyy");
     mList[4] = new MovieInfo("Beauty and the Beast","PG","Beauty_and_the_Beast.jpg","yyyn");
  }
} 

I also have JList which is attached to JPanel and radio buttons.. And my problem is that I can not get how to display name of the movie from mList[0] on this JList when I click 1st rbutton, name of the movie from mList[1] when I click 2nd rbutton and etc....

Yes I know that I need to register listener for my rbuttons and group them and add ItemStateChange (just did not want to add too much code here)... I am asking here about logic after the lines of

    if(e.getSource() instanceof JRadioButton)
   { 

Please help! Any ideas will be highly appreciated!


Answer:

You could write a custom CellRenderer, as shown in the docs.

For example, having a Movie bean and a MoviesListCellRenderer which extends DefaultListCellRenderer you could end up with something like this:

public class JListCards {
    private JFrame frame;
    private JPanel radiosPane;
    private JRadioButton[] radios;
    private String[] radiosNames = {"Movie", "Classification", "Price"};
    private JList <Movie> moviesList;
    private ButtonGroup group;

    private Movie[] movies = new Movie[] {
        new Movie("Happy Feet", "AA", 10),
        new Movie("Star Wars", "B12", 15),
        new Movie("Logan", "C", 20)
    };

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new JListCards().createAndShowGui());
    }

    public void createAndShowGui() {
        frame = new JFrame(getClass().getSimpleName());

        radiosPane = new JPanel(new GridLayout(1, 3));
        radios = new JRadioButton[3];
        group = new ButtonGroup();

        for (int i = 0; i < radios.length; i++) {
            radios[i] = new JRadioButton(radiosNames[i]);
            radios[i].addActionListener(listener);
            radiosPane.add(radios[i]);
            group.add(radios[i]);
        }

        radios[0].setSelected(true);
        moviesList = new JList<Movie>(movies);
        moviesList.setCellRenderer(new MoviesListCellRenderer(0));

        frame.add(moviesList);
        frame.add(radiosPane, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    ActionListener listener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            for (int i = 0; i < radios.length; i++) {
                if (e.getSource().equals(radios[i])) {
                    moviesList.setCellRenderer(new MoviesListCellRenderer(i));
                    break;
                }
            }
        }
    };

    class MoviesListCellRenderer extends DefaultListCellRenderer {
        private int attribute;

        public MoviesListCellRenderer(int attribute) {
            this.attribute = attribute;
        }

        @Override
        public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            if (value instanceof Movie) {
                Movie movie = (Movie) value;
                switch (attribute) {
                    case 0:
                        setText(movie.getMovieName());
                        break;
                    case 1:
                        setText(movie.getClassification());
                        break;
                    default:
                        setText(String.valueOf(movie.getPrice()));
                        break;
                }
            }
            return this;
        }
    }

    class Movie {
        private String movieName;
        private String classification;
        private double price;

        public Movie(String movieName, String classification, double price) {
            super();
            this.movieName = movieName;
            this.classification = classification;
            this.price = price;
        }

        public String getMovieName() {
            return movieName;
        }
        public void setMovieName(String movieName) {
            this.movieName = movieName;
        }
        public String getClassification() {
            return classification;
        }
        public void setClassification(String classification) {
            this.classification = classification;
        }
        public double getPrice() {
            return price;
        }
        public void setPrice(double price) {
            this.price = price;
        }
    }
}

Which as you can see, changes the cell renderer based on the radio selected, this code can still be improved but should give you an idea:

Question:

I have written a Java XML Parser as an Applet. It is looking and functioning well enough in this form.

My Question, Is if I want to run this without a browser, how Would I properly wrap it to run as an executable?

GUI.java

--------------


import java.applet.*;
import java.awt.*;
import java.awt.event.*;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class GUI extends JPanel implements ActionListener 
{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private Parser xmlEditor;
    private String startTimeValue;
    private String endTimeValue;

    public GUI(){
        init();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                new GUI();
            }
        });
    }
    public void init() {

        this.setXmlEditor(new Parser("C:\\Users\\Administrator\\workspace\\XMLParser\\src\\test.xml"));

        add(new Label("Start Time"));

        startTimeValue = xmlEditor.getStartTimeValue();
        endTimeValue = xmlEditor.getEndTimeValue();


        startTime = new TextField(startTimeValue);

        add(new Label("End Time"));
        endTime = new TextField(endTimeValue);

        save = new Button("save");
        save.addActionListener(this);


        add(startTime);
        add(endTime);
        add(save);

    }

    public void actionPerformed(ActionEvent e) 
    {

        System.out.println(endTime.getText());



        xmlEditor.updateStartTimeValue(startTime.getText());
        xmlEditor.updateEndTimeValue(endTime.getText());

        System.out.println(e);
        System.exit(0);



    }

    public Parser getXmlEditor() {
        return xmlEditor;
    }

    public void setXmlEditor(Parser xmlEditor) {
        this.xmlEditor = xmlEditor;
    }

    TextField startTime, endTime;
    Button save;
}

While trying things with Swing and JFRame etc, I am not getting properly layout, or am opening multiple windows. Can anyone provide assistance? The second Panel Keeps replacing the First. Id like to really try to learn how to place multiple components inside an executable jar is the goal.

SwingPaintDemo.java
import java.awt.Label;
import java.awt.TextField;

import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.JFrame;

public class SwingPaintDemo {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        System.out.println("Created GUI on EDT? "+
                SwingUtilities.isEventDispatchThread());
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        f.setVisible(true);


        Parser myParser = new Parser("C:\\Users\\Administrator\\workspace\\XMLParser\\src\\test.xml");

        JPanel top = new JPanel();
        top.add(new Label("Start Time"));

        TextField startTimeField = new TextField(myParser.getStartTimeValue());
        top.add(startTimeField);
        f.getContentPane().add(top);

        JPanel bottom = new JPanel();
        bottom.add(new Label("End Time"));
        TextField endTimeField = new TextField(myParser.getEndTimeValue());
        bottom.add(endTimeField);
        f.getContentPane().add(bottom);



        f.pack();

    }
}

Answer:

JFrame uses a BorderLayout by default, where as a JPanel uses a FlowLayout

Instead of rebuilding the UI in the JFrame, simply add an instance of GUI to it, since you've already defined the functionality in a JPanel, this makes it easily reusable.

public class SwingPaintDemo {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        System.out.println("Created GUI on EDT? "+
                SwingUtilities.isEventDispatchThread());
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(new GUI());

        f.pack();
        f.setVisible(true);

    }
}

FYI: You should never reference src in any path element, src won't exist once the program is built and packaged. This is also doubly concerning for applets, as applets run in a tight security model, which prevents them from accessing the file system by default.

Instead, you should be using Class#getResource or Class#getResourceAsStream, depending on your needs.

this.setXmlEditor(new Parser(getClass().getResource("/test.xml")));

for example. You may need to change your Parser to accept either a URL and/or InputStream as well

Question:

I'm learning basics of Java Applet and Swings. I'm trying a simple code. I want to change the color of my panel when a button is clicked. Here's the code:

SimpleGui.java

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class SimpleGui implements ActionListener {
    JFrame frame;
    JButton button;

    public static void main(String[] args) {
        SimpleGui gui = new SimpleGui();
        gui.go();
    }

    public void go() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        button = new JButton("changes colour");
        button.addActionListener(this);

        MyPanel drawPanel = new MyPanel();

        frame.getContentPane().add(BorderLayout.SOUTH,button);
        frame.getContentPane().add(BorderLayout.CENTER,drawPanel);

        frame.setSize(300, 300);
        frame.setVisible(true);
    }

    //event handling method
    public void actionPerformed(ActionEvent event) {
        frame.repaint();
        button.setText("color changed");
    }
}

class MyPanel extends JPanel {

    public void paintCompenent(Graphics g) {
        g.setColor(Color.green);
        g.fillRect(20, 50, 100, 100);
    }
}

I added some println statements to debug and I found out that paintComponent method is not called. Can you please correct me. Where I am making mistake. Is my entire implementation is wrong?


Answer:

paintComponent must be protected (see here).

change your code to :

class MyPanel extends JPanel {
     protected void paintComponent(Graphics g) {
        g.setColor(Color.green);
        g.fillRect(20, 50, 100, 100);
    }
}  

Result: