Hot questions for Using Applets in repaint

Question:

I would like to use applet to switch between 2 "frames".

I want to use an applet to paint something and then remove it and paint something else. Is there any way to do this?

Example:

if(true){
    public void paint1(Graphics g) {
        g.setColor(Color.black);
        g.fillRect( 80,400, 20, 10 );
    }
}else
    public void paint2(Graphics g) {
        g.setColor(Color.green);
        g.fillRect( 50,440, 70, 60 );
    }
}

All attempts I've tried on this crashed the applet.

My project: Me and my friend are writing a simple code where we need to use some kind applet graphics. We made the idea to make a program where 2 characters jump up and down. problem is that we are going to have an "AI" that jumps whenever he feels like it. So a CardLayout wont work because then we are in control of everything.


Answer:

I will suggest using a CardLayout if you intend to "switch" between 2 drawings.

However, if you want to continue with what you currently have by drawing based on a condition, you may do something like this:

class DrawingSpace extends JPanel{

    private BufferedImage display;
    //Other variables, initializations, constructors not shown

    private void init(){
        display = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    }

    public void draw(){
        if(whatever){    //if whatever == true
            Graphics2D g2 = display.createGraphics();
            g2.setColor(Color.BLACK);
            g2.fillRect( 80, 400, 20, 10 );
            repaint();
        }else{
            Graphics2D g2 = display.createGraphics();
            g2.setColor(Color.GREEN);
            g2.fillRect( 50, 440, 70, 60 );
            repaint();
        }
    }

    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(display, 0, 0, width, height, null);
    }
}

Question:

I'm trying to make a simple applet with java to show two counters. To simplify the code i created a function named "suma" which is called 2 times in run(). The counters in the console works, but in the applet aren't increased. I thing the problem is in repaint(), because when i try to execute the content of "suma" in run directly the code works. The question is: Why repaint() don't works out of run()?

import java.applet.Applet;
import java.awt.Button;
import java.awt.Color;
import java.awt.Graphics;


public class HiloContador extends Applet implements Runnable{
    //Propiedades
    private Thread h1;
    private Thread h2;
    long contador1=0;
    long contador2=500;
    private Button b1,b2;

    public void start(){}

    public void init(){
        setBackground(Color.YELLOW);
        //Botones
        add(b1=new Button("Parar hilo 1"));
        add(b2=new Button("Parar hilo 2"));
        //Creación de nuevos hilos y su inicio
        h1=new Thread(this);
        h2=new Thread(this);
        h1.start();
        h2.start();
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        suma(h1,contador1);
        suma(h2,contador2);     
    }//fin de run

    public void paint(Graphics g){
        g.drawString(Long.toString((long)contador1), 80, 100);
        g.drawString(Long.toString((long)contador2), 80, 120);
    }

    public void suma(Thread h,long c){
        Thread hiloActual=Thread.currentThread();
        while(h==hiloActual){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(c);
            c++;
            repaint();
        }//fin de while     
    }   
}


Answer:

This is because when you provide a primitive type like a long to a method, you pass its value not its reference such that when you increment c in your method suma you don't actually modify the value of your variables, you just increment the provided value, use AtomicLong instead of long as parameter of your method since it will then be passed by reference as it is no more a primitive type but an object reference, then increment its internal value with incrementAndGet() and get it with get().

Your code would then be:

...
AtomicLong contador1 = new AtomicLong();
AtomicLong contador2 = new AtomicLong(500);
...

public void paint(Graphics g){
    g.drawString(Long.toString(contador1.get()), 80, 100);
    g.drawString(Long.toString(contador2.get()), 80, 120);
}

public void suma(Thread h, AtomicLong c){
    ...
        System.out.println(c);
        c.incrementAndGet();
        repaint();
    ...
}

More details about pass-by-reference/pass-by-value

Question:

I understand that the repaint() function doesn't instantly repaint the frame. However, the repaint method here is called during a recursive function and only repaints after the towerOfHanoi function is complete. Is there a to instantly call the paint function to repaint each time during an iteration of the recursive function?

public void actionPerformed(ActionEvent e) {
    if (e.getSource() == start) {
        num = number.getText().trim();  
        numDisks = Integer.parseInt(num);

        //start the tower of hanoi function catch block used because of the delay function
        repaint();

        height[0].changeHeight(numDisks);
        begin = true;
        towerOfHanoi(numDisks, 0, 2, 1);
        //repaint();
    }

}


//initialize the pegs; first thing called when applet starts
public void paint(Graphics g) {
    g.setColor(Color.BLUE);
    g.fillRect(20, 190, 560, 10); //base
    g.fillRect(70, 60, 10, 150); //first peg
    g.fillRect(300, 60, 10, 150); //second peg
    g.fillRect(530, 60, 10, 150); //third peg

    //create the painting based on the amount of disks, starting with the biggest disk. 
    //when this is repainted, it will draw the new disks in different pegs with different coordinates
    g.setColor(Color.RED);
    for (int i = 0; i < numDisks; i++) {
        g.fillRect(disks[i].xPos, disks[i].yPos, disks[i].width, 10);
    }
}

public void update(Graphics g) {
    paint(g);
}


public void towerOfHanoi(int N, int from, int to, int temp) {

    if (N == 1) {
        moveTo(from, to, N);
    }
    else {
        towerOfHanoi(N - 1, from, temp, to);
        moveTo(from, to, N);
        towerOfHanoi(N - 1, temp, to, from);
    }
}

//change move to function move disks from 1st stack to the 3rd stack
public void moveTo(int from, int to, int diskNum)  {        
    System.out.println(from + "->" + to);

    //adjust the disk number to match the indexing of the way I 
    //used the disk number, as an index of arrays starting from
    //the bottom up at 0.
    if (numDisks == 1) {
        if (diskNum == 1) { diskNum = 0;}
    }
    else if (numDisks == 2) {
        if (diskNum == 1) {diskNum = 1; }
        else if (diskNum == 2) {diskNum = 0; }
    }
    else if (numDisks == 3) {
        if (diskNum == 1) { diskNum = 2;}
        else if (diskNum == 2) {diskNum = 1;}
        else if (diskNum == 3) {diskNum = 0;}
    }
    else if (numDisks == 4) {
        if (diskNum == 1) { diskNum = 3;}
        else if (diskNum == 2) {diskNum = 2;}
        else if (diskNum == 3) {diskNum = 1;}
        else if (diskNum == 4) {diskNum = 0;}
    }
    else if (numDisks == 5) {
        if (diskNum == 1) { diskNum = 4;}
        else if (diskNum == 2) {diskNum = 3;}
        else if (diskNum == 3) {diskNum = 2;}
        else if (diskNum == 4) {diskNum = 1;}
        else if (diskNum == 5) {diskNum = 0;}
    }
    else if (numDisks == 6) {
        if (diskNum == 1) { diskNum = 5;}
        else if (diskNum == 2) {diskNum = 4;}
        else if (diskNum == 3) {diskNum = 3;}
        else if (diskNum == 4) {diskNum = 2;}
        else if (diskNum == 5) {diskNum = 1;}
        else if (diskNum == 6) {diskNum = 0;}
    }
    else if (numDisks == 7) {
        if (diskNum == 1) { diskNum = 6;}
        else if (diskNum == 2) {diskNum = 5;}
        else if (diskNum == 3) {diskNum = 4;}
        else if (diskNum == 4) {diskNum = 3;}
        else if (diskNum == 5) {diskNum = 2;}
        else if (diskNum == 6) {diskNum = 1;}
        else if (diskNum == 7) {diskNum = 0;}
    }   


    //diskNum += height[from].height;
    System.out.println("Disk moving is disk # " + diskNum);
    topDisk = diskNum;

    height[from].pop();
    height[to].push();

    System.out.println("Height of Peg 1: " + height[0].height);
    System.out.println("Height of Peg 2: " + height[1].height);
    System.out.println("Height of Peg 3: " + height[2].height);
    /* we can do this the hard way and calculate the xPos and yPos
     * We might just have to create the disk1 - disk7 each with its own widths, every disk 
     * has the same height. Every disk has its own xPos and yPos.
     * when we do that, we will then need to calculate the appropriate xPos for each..
     * but how do we calculate the yPos????? 
     * yPos is calculated based on the height of the pegs...
     * So now how do we calculate what the top disk number is?
     *  
    */  


    if (from == 0 && to == 1) { //adjust the new xPos
        disks[topDisk].from0to1(); //change xPos
        if (height[1].height == 0) { //adjusts the new yPos
            disks[topDisk].yPos = 175;
        } else if (height[1].height == 1) {
            disks[topDisk].yPos = 165;
        } else if (height[1].height == 2) {
            disks[topDisk].yPos = 155;
        } else if (height[1].height == 3) {
            disks[topDisk].yPos = 145;
        } else if (height[1].height == 4) {
            disks[topDisk].yPos = 135;
        } else if (height[1].height == 5) {
            disks[topDisk].yPos = 125;
        } else if (height[1].height == 6) {
            disks[topDisk].yPos = 115;
        } else if (height[1].height == 7) {
            disks[topDisk].yPos = 105;
        }
    } else if (from == 1 && to == 2) {
        disks[topDisk].from1to2();
        if (height[2].height == 0) { //adjusts the new yPos
            disks[topDisk].yPos = 175;
        } else if (height[2].height == 1) {
            disks[topDisk].yPos = 165;
        } else if (height[2].height == 2) {
            disks[topDisk].yPos = 155;
        } else if (height[2].height == 3) {
            disks[topDisk].yPos = 145;
        } else if (height[2].height == 4) {
            disks[topDisk].yPos = 135;
        } else if (height[2].height == 5) {
            disks[topDisk].yPos = 125;
        } else if (height[2].height == 6) {
            disks[topDisk].yPos = 115;
        } else if (height[2].height == 7) {
            disks[topDisk].yPos = 105;
        }
    } else if (from == 0 && to == 2) {
        disks[topDisk].from0to2();
        if (height[2].height == 0) { //adjusts the new yPos
            disks[topDisk].yPos = 175;
        } else if (height[2].height == 1) {
            disks[topDisk].yPos = 165;
        } else if (height[2].height == 2) {
            disks[topDisk].yPos = 155;
        } else if (height[2].height == 3) {
            disks[topDisk].yPos = 145;
        } else if (height[2].height == 4) {
            disks[topDisk].yPos = 135;
        } else if (height[2].height == 5) {
            disks[topDisk].yPos = 125;
        } else if (height[2].height == 6) {
            disks[topDisk].yPos = 115;
        } else if (height[2].height == 7) {
            disks[topDisk].yPos = 105;
        }
    } else if (from == 1 && to == 0) {
        disks[topDisk].from1to0();
        if (height[0].height == 0) { //adjusts the new yPos
            disks[topDisk].yPos = 175;
        } else if (height[0].height == 1) {
            disks[topDisk].yPos = 165;
        } else if (height[0].height == 2) {
            disks[topDisk].yPos = 155;
        } else if (height[0].height == 3) {
            disks[topDisk].yPos = 145;
        } else if (height[0].height == 4) {
            disks[topDisk].yPos = 135;
        } else if (height[0].height == 5) {
            disks[topDisk].yPos = 125;
        } else if (height[0].height == 6) {
            disks[topDisk].yPos = 115;
        } else if (height[0].height == 7) {
            disks[topDisk].yPos = 105;
        }
    } else if (from == 2 && to == 0) {
        disks[topDisk].from2to0();
        if (height[0].height == 0) { //adjusts the new yPos
            disks[topDisk].yPos = 175;
        } else if (height[0].height == 1) {
            disks[topDisk].yPos = 165;
        } else if (height[0].height == 2) {
            disks[topDisk].yPos = 155;
        } else if (height[0].height == 3) {
            disks[topDisk].yPos = 145;
        } else if (height[0].height == 4) {
            disks[topDisk].yPos = 135;
        } else if (height[0].height == 5) {
            disks[topDisk].yPos = 125;
        } else if (height[0].height == 6) {
            disks[topDisk].yPos = 115;
        } else if (height[0].height == 7) {
            disks[topDisk].yPos = 105;
        }
    } else if (from == 2 && to == 1) {
        disks[topDisk].from2to1();
        if (height[1].height == 0) { //adjusts the new yPos
            disks[topDisk].yPos = 175;
        } else if (height[1].height == 1) {
            disks[topDisk].yPos = 165;
        } else if (height[1].height == 2) {
            disks[topDisk].yPos = 155;
        } else if (height[1].height == 3) {
            disks[topDisk].yPos = 145;
        } else if (height[1].height == 4) {
            disks[topDisk].yPos = 135;
        } else if (height[1].height == 5) {
            disks[topDisk].yPos = 125;
        } else if (height[1].height == 6) {
            disks[topDisk].yPos = 115;
        } else if (height[1].height == 7) {
            disks[topDisk].yPos = 105;
        }
    }
    try {
        Thread.sleep(50);
    } catch(Exception ex) {

    }
    repaint();
}

Answer:

repaint() sends an instruction to repaint the screen once the UI thread becomes available. If you aren't already, I would suggest doing all of your transformations in a different thread, then repaint() will refresh the screen relatively quickly (as the UI thread isn't doing anything).

Question:

What I am looking to do is have the user to be able to change perspectives from a KeyListener. If the user hits the specified key, than the perspective should change. Any ideas?

Even if I override the methods they still do not work. I have also tried KeyAdapter

package com.development.gameOne.environment.component;

import java.applet.Applet;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

import com.development.gameOne.environment.applet.drawing.Perspective;
import com.development.gameOne.environment.applet.perspectives.p1.FirstPerspective;
import com.development.gameOne.environment.applet.perspectives.p2.SecondPerspective;

public class Component extends Applet implements KeyListener {

    private static final long serialVersionUID = 1L;
    private Dimension size = new Dimension(1280, 720);

    private ArrayList<Perspective> perspectives = new ArrayList<Perspective>();
    private boolean running = true;
    private boolean switchPerspective = false;

    public Component() {
        setPreferredSize(size);
        loadPerspectives();
        addKeyListener(this);
        setFocusable(true);
        setVisible(true);
        start();
    }

    private void loadPerspectives() {
        perspectives.add(new FirstPerspective());
        perspectives.add(new SecondPerspective());
    }

    public static void main(String[] args) {
        new Component();
    }

    @Override
    public void paint(Graphics g) {
        while (running) {
            for (Perspective p : perspectives) {
                System.out.println(p.getPerspective());
                while (!switchPerspective) {
                    System.out.println("Rendering");
                    p.start(g);
                    sleep(100);
                }
                switchPerspective = false;
            }
            sleep(10);
        }
    }

    public static void sleep(int renderSpeed) {
        try {
            Thread.sleep(renderSpeed);
        }
        catch (Exception e) {}
    }

    public void keyPressed(KeyEvent e) {
        switch(e.getKeyCode()){
        case KeyEvent.VK_SHIFT:
            System.out.println("KeyPressed");
            switchPerspective = true;
            break;
        }
    }



    public void keyTyped(KeyEvent e) { }

    public void keyReleased(KeyEvent e) {}

}

The program runs, but doesn't switch perspectives. I cannot seem to get the KeyListener to work at all. I really have no idea what to do.


Answer:

I don't think the issue is with your KeyListener, but is with your paint process

@Override
public void paint(Graphics g) {
    while (running) {
        for (Perspective p : perspectives) {
            System.out.println(p.getPerspective());
            while (!switchPerspective) {
                System.out.println("Rendering");
                p.start(g);
                sleep(100);
            }
            switchPerspective = false;
        }
        sleep(10);
    }
}

This will block the Event Dispatching Thread, preventing it from ever been able to process new events coming into the system

Take a look at Painting in AWT and Swing for details about how painting works in AWT.

The (simple) solution, in this case, would be to provide a other Thread which handles the timing between updates and simple call repaint when you want the UI updated.

A better solution would be take take advantage of the a BufferStrategy instead. It still require a Thread, but stops you from breaking the painting chain.

As a side note. AWT Applets are woefully out-of-date and were replaced by JApplet before 2000. Having said that, I would recommend against using applets at all, as they have enough problems which only increases the difficulty of starting development and focus on something like a JPanel added to an instance of a JFrame instead.

Take a look at Performing Custom Painting and Creating a GUI With JFC/Swing

I'd also drop the use of KeyListener as soon as you can in favour of Swing's Key bindings API. See How to Use Key Bindings for more details

I'd also avoid calling your applet Component, there already is a class called Component and this is just going to confuse matters...

And applets, definitely, should not have a main method. They are expected to be loaded by the browser directly and have a different, defined, life cycle.

Question:

This is a simple rock, paper, scissors appelet. there are 3 variables keeping track of wins, losses, and ties. Then there is a label that is meant to display them. When I used the debugger the repaint method is being called so I don't understand why this portion of the applet isn't updating.

import java.awt.Font;
import java.awt.Graphics;

import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.JButton;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Random;

public class JRockPaperScissors extends JApplet {
    JLabel lblDescision = new JLabel("descision");
    JLabel lblWinner = new JLabel("winner");
    JLabel lblTally = new JLabel("tally");
    int tally_user = 0;
    int tally_comp = 0;
    int tally_ties = 0;



/**
 * Create the applet.
 */
public JRockPaperScissors() {
        setSize(500,500);
        getContentPane().setLayout(null);



    JLabel lblRockPaperScissors = new JLabel("Rock, Paper, Scissors");
    lblRockPaperScissors.setBounds(95, 50, 280, 48);
    getContentPane().add(lblRockPaperScissors);
    Font arial_1 = new Font("Arial", Font.BOLD, 25);
    lblRockPaperScissors.setFont(arial_1);

    JLabel lblChooseOneButton = new JLabel("Choose one button");
    lblChooseOneButton.setBounds(10, 93, 146, 25);
    getContentPane().add(lblChooseOneButton);
    Font arial_2 = new Font("Arial", Font.BOLD, 15);
    lblChooseOneButton.setFont(arial_2);

    JButton btnRock = new JButton("Rock");
    btnRock.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            determine_winner(0);
            repaint();
        }
    });
    btnRock.setBounds(166, 95, 89, 23);
    getContentPane().add(btnRock);

    JButton btnPaper = new JButton("Paper");
    btnPaper.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            determine_winner(1);
        }
    });
    btnPaper.setBounds(265, 95, 89, 23);
    getContentPane().add(btnPaper);

    JButton btnScissors = new JButton("Scissors");
    btnScissors.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            determine_winner(2);
        }
    });
    btnScissors.setBounds(361, 95, 89, 23);
    getContentPane().add(btnScissors);

    JLabel lblresults = new JLabel("------Results------");
    lblresults.setBounds(20, 114, 126, 25);
    getContentPane().add(lblresults);
    Font arial_3 = new Font("Arial", Font.BOLD, 15);
    lblresults.setFont(arial_3);

    lblDescision.setBounds(30, 150, 311, 14);
    getContentPane().add(lblDescision);

    lblWinner.setBounds(20, 175, 146, 14);
    getContentPane().add(lblWinner);

    JLabel lblTally = new JLabel("You:" + tally_user + "    Computer:" + tally_comp + 
            "    Ties:"+ tally_ties);
    lblTally.setBounds(20, 214, 201, 30);
    getContentPane().add(lblTally);


}

public void determine_winner(int user_choice){
    Random random = new Random();
    int computer_choice = random.nextInt(3);
    if(user_choice == 0 ){
        if(computer_choice ==0){
            lblDescision.setText("You picked Rock --- Computer picked Rock");
            lblWinner.setText("Winner: Tie");
            tally_ties +=1;
        }
        else if(computer_choice ==1){
            lblDescision.setText("You picked Rock --- Computer picked Paper");
            lblWinner.setText("Winner: Computer");
            tally_comp +=1;

        }
        else if(computer_choice ==2){
            lblDescision.setText("You picked Rock --- Computer picked Scissors");
            lblWinner.setText("Winner: You");
            tally_user +=1;

        }
    }
    else if(user_choice == 1){
        if(computer_choice ==0){
            lblDescision.setText("You picked Paper --- Computer picked Rock");
            lblWinner.setText("Winner: You");
            tally_user +=1;
        }
        else if(computer_choice ==1){
            lblDescision.setText("You picked Paper --- Computer picked Paper");
            lblWinner.setText("Winner: Tie");
            tally_ties +=1;
        }
        else if(computer_choice ==2){
            lblDescision.setText("You picked Paper --- Computer picked Scissors");
            lblWinner.setText("Winner: Computer");
            tally_comp +=1;
        }
    }
    else if(user_choice == 2){
        if(computer_choice ==0){
            lblDescision.setText("You picked Scissors --- Computer picked Rock");
            lblWinner.setText("Winner: Computer");
            tally_comp +=1;
        }
        else if(computer_choice ==1){
            lblDescision.setText("You picked Scissors --- Computer picked Paper");
            lblWinner.setText("Winner: You");
            tally_user +=1;
        }
        else if(computer_choice ==2){
            lblDescision.setText("You picked Scissors --- Computer picked Scissors");
            lblWinner.setText("Winner: Tie");
            tally_ties +=1;
        }
    }
revalidate();
repaint();
}

}

Answer:

  • Issue number 1: You never change the text in the tally JLabel, lblTally. In other words, for the text in this JLabel and similar components to change you must specifically call, lblTally.setText(someNewString);
  • Issue number 2: you're also shadowing the lblTally variable -- you're re-declaring and re-initializing the variable in the constructor, meaning that the JLabel object displayed in the GUI is not the same as the one that the class field refers to -- don't do this. Declare the variable and initialize it with a valid reference only once.

Other side issues (issues not directly related to your problem) are:

  • You're using a null layout. You will want to avoid use of null layout and use of setBounds(...) for component placement as this makes for very inflexible GUI's that while they might look good on one platform look terrible on most other platforms or screen resolutions and that are very difficult to update and maintain.
  • Your applet has no init() method, the method that should get the applet up and running.
  • There is no need to call revalidate() or repaint() after changing text in a JLabel.

In a nut shell, what you're doing is this:

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

public class JRockPaperEtc extends JApplet {
   private static final String FORMAT_TXT = "Tally: %03d";
   private int tally = 0;
   private JLabel lblTally = new JLabel(String.format(FORMAT_TXT, tally));

   @Override
   public void init() {
      JPanel mainPanel = new JPanel();

      // *** Variable Shadowing here
      JLabel lblTally = new JLabel("Tally: 000");
      mainPanel.add(lblTally);

      JButton button = new JButton(new AbstractAction("Push") {

         @Override
         public void actionPerformed(ActionEvent e) {
            tally++;
            // *** lblTally's text is never changed
         }
      });
      mainPanel.add(button);

      add(mainPanel);
   }
}

When you should be doing this:

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

public class JRockPaperEtc2 extends JApplet {
   private static final String FORMAT_TXT = "Tally: %03d";
   private int tally = 0;
   private JLabel lblTally = new JLabel(String.format(FORMAT_TXT, tally));

   @Override
   public void init() {
      JPanel mainPanel = new JPanel();

      // lblTally = new JLabel("Tally: 000"); // *** no shadowing
      mainPanel.add(lblTally);

      JButton button = new JButton(new AbstractAction("Push") {

         @Override
         public void actionPerformed(ActionEvent e) {
            tally++;
            lblTally.setText(String.format(FORMAT_TXT, tally));
            // *** lblTally's text is now changed
         }
      });
      mainPanel.add(button);

      add(mainPanel);
   }
}

Also, you ask:

so what would you do instead of set bounds? I'm just starting to learn gui apps so excuse me if this is a very in depth question.

Instead of setBounds(), use layout managers to handle all the layout heavy lifting for you. Google the Swing layout manager tutorial and have a look.

Question:

I am trying to program a basic plotter using Applets. I need to use Applets specifically.

For the polt I have created a separate Canvas, but I have encountered a problem I cannot solve. When I draw any graph for the first time, it is drawn nicely. However, the canvas is not being repainted properly afterwards - I see in the debugging screen that the repaint() method was called and the paint() is invoked, but no graphics are updated.

Here is the code:

public class MyCanvas extends Canvas{
int w,h;   //width and height
int samples;
ArrayList<Double> eqValues = new ArrayList<>();
MyCanvas(int wi, int he) //constructor
{ w=wi; h=he;
    setSize(w,h); //determine size of canvas
    samples=wi-20;
}
public void paint(Graphics g)
{
    int y0=0, y1; //previous and new function value
    g.setColor(Color.yellow);
    g.fillRect(0,0,w,h);   //clear canvas
    g.setColor(Color.black);
    if (eqValues.size()>0) { // draw new graph
        for (int t = 1; t <= samples; t = t + 1) {
            y1 = eqValues.get(t).intValue();
            g.drawLine(10 + t - 1, h  - y0, 10 + t, h  - y1);
            y0 = y1;
        }
    }
    System.out.println("Repainted");
    /*g.drawLine(10,10,10,h-10);   //y-axis
    g.drawLine(10,h/2,w-10,h/2); //x-axis
    g.drawString("P",w-12,h/2+15);
    g.drawString("P/2",w/2-13,h/2+15);
    g.drawLine(w-10,h/2-2,w-10,h/2+2); //horizontal marks
    g.drawLine(w/2, h/2-2,w/2, h/2+2);*/
}

public void drawSine(double amp, double xCoef, double phase){
    for (int j=0;j<=samples;j++){
        eqValues.add(amp*Math.sin(xCoef*Math.PI*j/samples + Math.PI*phase/180)+0.5+h/2);
    }
    repaint();
    System.out.println("Got sine vals");
}

public void drawFOeq(double sc, double fc){
    for (int j=0;j<=samples;j++){
        eqValues.add(sc*j+fc);
    }
    repaint();
    System.out.println("Got FO eq vals");
}
}

Thanks in advance!


Answer:

The problem is when you add values to the ArrayList: you are putting them after the ones already in the ArrayList (with the add(Double) method). If you just want to clear the plot and draw a new function use the clear() method in the ArrayList of values before adding the new ones:

public void drawSine(double amp, double xCoef, double phase) {
    eqValues.clear();    //this clear the ArrayList
    ......
    repaint();
    ......
}

public void drawFOeq(double sc, double fc){
    eqValues.clear();    //this clear the ArrayList
    ......
    repaint();
    ......
}

If you want to plot multiple functions you have to create different ArrayList or, even better, store in the ArrayList all points (for example with java.awt.Point):

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;

public class MyCanvas extends Canvas {

    int w, h; // width and height
    int samples;
    ArrayList<Point> eqValues = new ArrayList<>();              //Point constructor receives 2 int arguments: x and y; however, his methods getX() and getY() return double values

    // constructor
    MyCanvas(int wi, int he) {
        w = wi;
        h = he;
        setSize(w, h);                                          // determine size of canvas
        samples = wi - 20;
    }

    public void paint(Graphics g) {
        int x1, y0, y1;                                         // previous and new function value

        g.setColor(Color.yellow);
        g.fillRect(0, 0, w, h);                                 // clear canvas

        g.setColor(Color.black);
        if (eqValues.size() > 0) {                              // draw new graph
            y0 = (int) Math.round(eqValues.get(0).getY());      // first line must start at the first point, not at 0,h
            for (Point p : eqValues) {                          // iterates over the ArrayList
                x1 = (int) Math.round(p.getX());
                y1 = (int) Math.round(p.getY());
                g.drawLine(10 + x1 - 1, h - y0, 10 + x1, h - y1);
                y0 = y1;
            }
        }

        System.out.println("Repainted");

    }

    public void drawSine(double amp, double xCoef, double phase) {
        for (int j = 0; j <= samples; j++) {
            eqValues.add(new Point(j, (int) Math
                    .round(amp * Math.sin(xCoef * Math.PI * j / samples + Math.PI * phase / 180) + 0.5 + h / 2)));
        }
        repaint();
        System.out.println("Got sine vals");
    }

    public void drawFOeq(double sc, double fc) {
        for (int j = 0; j <= samples; j++) {
            eqValues.add(new Point(j, (int) Math.round(sc * j + fc)));
        }
        repaint();
        System.out.println("Got FO eq vals");
    }
}

Question:

Please help me how to make this eye move or to make it blink using repaint, thread and implements runnable. I don't know where to place the right codes to make it work. Please help me guys! Thank you! Here is the code:

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

public class Pucca extends Applet {

public Pucca(){
setSize(700, 700); }

//paint method
public void paint(Graphics g){

Color white = new Color(255,255,255);
g.setColor(white);
g.fillOval(600, 100, 125, 125); //left white fill eye

g.setColor(Color.BLA­CK);
g.drawOval(600, 100, 125, 125); // left big black line eye

g.setColor(white);
g.fillOval(700, 100, 125, 125); //right white fill eye

g.setColor(Color.BLA­CK);
g.drawOval(700, 100, 125, 125); //right big black line eye

Color blue = new Color(0, 160, 198);
g.setColor(blue);
g.fillOval(635, 130, 51, 51); // left blue fill eye

g.setColor(Color.BLA­CK);
g.drawOval(635, 130, 50, 50); // left black small line eye

g.setColor(blue);
g.fillOval(735, 130, 51, 51); // right blue fill eye

g.setColor(Color.BLA­CK);
g.drawOval(735, 130, 50, 50); // right black small line eye

g.setColor(Color.BLA­CK);
g.fillOval(650, 145, 20, 20); // left black iris 

g.setColor(Color.BLA­CK);
g.fillOval(750, 145, 20, 20); // right black iris

}
}

Answer:

When it comes to animation, everything becomes variable. You also have a lot of repeated code (seriously, if you can paint one eye, you can paint lots).

The first thing you need to is make all the values of the eye as variable as possible.

The follow makes the eye size and position variable and the iris and pupil a scaled value of the eye size, which makes the whole process simpler to animate.

Next, you need an updated loop, which can update the state of the values you want to change. To keep it simple, I've set it up so that the pupil has a variable offset, which is changed over time.

import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;

public class Pucca extends Applet {

    public Pucca() {
        setSize(700, 700);
        Thread t = new Thread(new Runnable() {
            private int xDelta = -1;
            private int yDelta = 0;
            private int blinkCount = 0;

            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(40);
                    } catch (InterruptedException ex) {
                    }

                    xOffset += xDelta;
                    double irisSize = eyeSize.width * irisScale;
                    double range = ((eyeSize.width - irisSize) / 2);
                    if (xOffset <= -range) {
                        xOffset = -(int) range;
                        xDelta *= -1;
                    } else if (xOffset >= range) {
                        xOffset = (int) range;
                        xDelta *= -1;
                    }
                    blinkCount++;
                    if (blink && blinkCount > 10) {
                        blink = false;
                        blinkCount = 0;
                    } else if (blinkCount > 25) {
                        blink = true;
                        blinkCount = 0;
                    }
                    repaint();
                }
            }
        });
        t.setDaemon(true);
        t.start();
    }

    private boolean blink = false;

    private int xOffset, yOffset = 0;
    private Dimension eyeSize = new Dimension(125, 125);
    private Point left = new Point(20, 20);
    private Point right = new Point(left.x + 100, left.y);
    private double irisScale = 0.4;
    private double pupilScale = 0.16;

//paint method
    @Override
    public void paint(Graphics g) {
        super.paint(g);

        paintEye(g, new Rectangle(left, eyeSize));
        paintEye(g, new Rectangle(right, eyeSize));

    }

    protected void paintEye(Graphics g, Rectangle bounds) {

        Color white = new Color(255, 255, 255);

        if (blink) {
            g.setColor(Color.YELLOW);
        } else {
            g.setColor(white);
        }
        g.fillOval(bounds.x, bounds.y, bounds.width, bounds.height); //left white fill eye

        g.setColor(Color.BLACK);
        g.drawOval(bounds.x, bounds.y, bounds.width, bounds.height); // left big black line eye

        if (!blink) {
            Color blue = new Color(0, 160, 198);

            paintEyePartAt(g, bounds, irisScale, blue);
            paintEyePartAt(g, bounds, pupilScale, Color.BLACK);
        }
    }

    private void paintEyePartAt(Graphics g, Rectangle bounds, double delta, Color color) {

        int width = (int) (bounds.width * delta);
        int height = (int) (bounds.height * delta);

        g.setColor(color);
        g.fillOval(
                xOffset + bounds.x + ((bounds.width - width) / 2),
                yOffset + bounds.y + ((bounds.height - height) / 2),
                width, height); // left blue fill eye
        g.setColor(Color.BLACK);
        g.drawOval(
                xOffset + bounds.x + ((bounds.width - width) / 2),
                yOffset + bounds.y + ((bounds.height - height) / 2),
                width,
                height); // left blue fill eye
    }
}

This complicates things, as painting can occur for any number of reasons, many of which you don't have control over or will be notified about, so you should be very careful about where and when you change values.

You should also have a look at Java Plugin support deprecated and Moving to a Plugin-Free Web and Why CS teachers should stop teaching Java applets.

Applets are simply a dead technology and given the inherent complexities involved in using them, you should instead focus you should probably attention towards window based programs.

Personally, I'd start with having a look at Painting in AWT and Swing and Performing Custom Painting

Question:

I want to create a Rubber-banding line using applet. Here is my code:

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

public class RubberLines extends Applet implements MouseMotionListener {
    public void init() {
        addMouseMotionListener(this);
    }    
    public void mouseDragged(MouseEvent e) {
        draw=true;
        X.add(e.getX());
        Y.add(e.getY());
        System.out.println(X.get(0));
        System.out.println("mouse is being dragged at location (" + e.getX() + ", " + e.getY() + ")");
    }    
    public void mouseMoved(MouseEvent e) {
        System.out.println("mouse is being moved at location (" + e.getX() + ", " + e.getY() + ")");
    }     
    public void paint(Graphics g) {
                initX=X.get(0);
                initY=Y.get(0);
                finalX=X.get(X.size()-1);
                finalY=Y.get(Y.size()-1);
                //g.drawLine(0, 0, 100, 100);
                if(draw)
        g.drawLine(initX, initY, finalX, finalY);
        g.setColor(Color.green);
           System.out.println(initX);
           System.out.println(finalY); 

           //repaint();    
    }   
    int initX,initY;
    int finalX,finalY;
    Vector<Integer> X=new Vector<Integer>();
    Vector<Integer> Y=new Vector<Integer>();
    boolean draw=false;    
}

However, the line didn't show up when I dragged the mouse until I change the size of applet(which means repaint). But when I added repaint(), the applet just repaints itself non-stop.

How to understand this repaint() and how to fix the problem please?


Answer:

But when I added repaint(), the applet just repaint itself non-stop.

Don't invoke repaint() in a painting method.

Instead add the repaint() to the mouseDragged() method because this is where the event is generated.

Also, don't forget to invoke super.paint() in your painting method.

Question:

I was trying to recreate the catan hexagonal grid and I am new to applet and swing. I am not clear with the concept of paint(). I have found out that graphics method drawPolygon must be used for drawing hexagon and I implemented a grid like structure and the values from the arraylist are populated there and refreshed so I removed them after they are drawn using drawString method causing me index out of bounds and I thought is cause of some other issues. But finally I noticed that the grid is refreshing again and again I am clueless as I do not understand the concept. Since the paint method is called my hexagonal grid is rendered continuously and please check and help me how to effectively correct this issue. I have the method to get the values from the arraylist and populate it in the hexagon grid.

    package catan.board.game.utilities;

public class Utilities {

    public static int[] getInitialXPoints(int increment){
        final int[] xPoints = { 0 + increment, 45 + increment, 90 + increment, 90 + increment, 45 + increment,
                0 + increment };
        return xPoints;

    }
    public static int[] getInitialYPoints(int increment){
        final int[] yPoints = { 45 + increment, 0 + increment, 45 + increment, 90 + increment, 135 + increment,
                90 + increment };
        return yPoints;
    }

    public static int[] getMoreXPoints(int[] xPoints, int increment) {
        //System.out.println("The x points before the increment[" + increment + "]-->" + Arrays.toString(xPoints));
        int[] newXPoints = new int[xPoints.length];
        for (int i = 0; i < xPoints.length; i++)
            newXPoints[i] = xPoints[i] + increment;
        //System.out.println("The x points after the increment[" + increment + "]-->" + Arrays.toString(newXPoints));
        return newXPoints;
    }

    public static int[] getMoreYPoints(int[] yPoints, int increment) {
        //System.out.println("The y points before the increment[" + increment + "]-->" + Arrays.toString(yPoints));
        int[] newYPoints = new int[yPoints.length];
        for (int i = 0; i < yPoints.length; i++)
            newYPoints[i] = yPoints[i] + increment;
        //System.out.println("The y points after the increment[" + increment + "]-->" + Arrays.toString(newYPoints));
        return newYPoints;
    }


}


    package catan.board.game;

    import java.applet.Applet;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Polygon;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Random;
    import java.util.concurrent.ConcurrentHashMap;

    import catan.board.game.utilities.Utilities;

    public class CatanBoardApplet extends Applet {

        private static final long serialVersionUID = 1L;
        static final int HEX_CONSTANT = 840;
        int xOval = 720;
        int yOval = 60;
        int widthOval = 600;
        int heightOval = 600;
        int nPoints = 6;
        int angle = 45;
        int gridSpace = 20;
        int row = 3;
        int maxLength = 5;
        int[] xPoints = Utilities.getInitialXPoints(0);
        int[] yPoints = Utilities.getInitialYPoints(0);

        static ConcurrentHashMap<Integer, Integer> expectedHexValuesMap = new ConcurrentHashMap<Integer, Integer>();
        static ConcurrentHashMap<Integer, Integer> actualHexValuesMap = new ConcurrentHashMap<Integer, Integer>();
        static ArrayList<Integer> hexValueList = new ArrayList<Integer>();

        @Override
        public void init() {
            System.out.println("Init");
            setHexNumbers();
            Graphics g = getGraphics();
            System.out.println("graphics--->" + g);
        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            g.drawString("Welcome to the Dripura's catan game", 200, 20);
            g.draw3DRect(30, 30, 1300, 650, true);
            g.drawOval(xOval, yOval, widthOval, heightOval);
            g.setColor(new Color(42, 179, 231));
            g.fillOval(xOval, yOval, widthOval, heightOval);
            drawHexagonalGrid();
            rollDice();
        }

        private void rollDice() {

            System.out.println("rolldice");

        }

        private static void setHexNumbers() {
            expectedHexValuesMap.put(2, 1);
            expectedHexValuesMap.put(12, 1);
            expectedHexValuesMap.put(3, 2);
            expectedHexValuesMap.put(4, 2);
            expectedHexValuesMap.put(5, 2);
            expectedHexValuesMap.put(6, 2);
            expectedHexValuesMap.put(7, 0);
            expectedHexValuesMap.put(8, 2);
            expectedHexValuesMap.put(9, 2);
            expectedHexValuesMap.put(10, 2);
            expectedHexValuesMap.put(11, 2);

            actualHexValuesMap.put(2, 0);
            actualHexValuesMap.put(12, 0);
            actualHexValuesMap.put(3, 0);
            actualHexValuesMap.put(4, 0);
            actualHexValuesMap.put(5, 0);
            actualHexValuesMap.put(6, 0);
            actualHexValuesMap.put(7, 0);
            actualHexValuesMap.put(8, 0);
            actualHexValuesMap.put(9, 0);
            actualHexValuesMap.put(10, 0);
            actualHexValuesMap.put(11, 0);

            Random r = new Random();
            int min = 2;
            int max = 12;
            while (!expectedHexValuesMap.equals(actualHexValuesMap)) {
                int hexValue = r.nextInt((max - min) + 1) + min;
                System.out.println("value--->" + hexValue);
                if (hexValue != 0 && actualHexValuesMap.get(hexValue) < expectedHexValuesMap.get(hexValue)) {
                    hexValueList.add(hexValue);
                    actualHexValuesMap.put(hexValue, actualHexValuesMap.get(hexValue) + 1);
                }
                System.out.println("actualHexValuesMap: " + actualHexValuesMap);
            }
            System.out.println("hexValueList: " + hexValueList);
            System.out.println("hexValueList size: " + hexValueList.size());

        }

        private void placeNumbers(Graphics g, Polygon p, boolean flag) {
            int x = p.getBounds().x + 30;
            int y = p.getBounds().y + 50;
            int width = p.getBounds().width / 3;
            int height = p.getBounds().width / 3;
            g.drawOval(x, y, width, height);
            g.setColor(Color.WHITE);
            // g.setColor(new Color((int)(Math.random() * 0x1000000)));
            g.fillOval(x, y, width, height);
            g.setColor(Color.BLACK);
            System.out.println(hexValueList);
            if (flag) {
                int hexValue = hexValueList.get(0);
                g.drawString("" + hexValue, x + 10, y + 20);
                hexValueList.remove(0);
                flag = false;
            }
        }

        private Graphics drawHexagonalGrid() {
            System.out.println("Drawing the hexagonal grid");
            Graphics g = getGraphics();
            System.out.println("graphics---->" + g);
            Boolean isValidHex = true;
            // row 1 - three grids
            Polygon p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 45),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 20), nPoints);
            //
            g.drawPolygon(p);
            g.setColor(Color.GREEN);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 135),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 20), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.BLUE);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 225),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 20), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.RED);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            // row 2 - four grids
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 0),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 110), nPoints);

            g.drawPolygon(p);
            // System.out.println(Arrays.toString(p.xpoints) + " " +
            // Arrays.toString(p.ypoints));
            g.setColor(Color.GRAY);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 90),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 110), nPoints);

            g.drawPolygon(p);
            // System.out.println(Arrays.toString(p.xpoints) + " " +
            // Arrays.toString(p.ypoints));
            g.setColor(Color.ORANGE);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 180),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 110), nPoints);

            g.drawPolygon(p);
            // System.out.println(Arrays.toString(p.xpoints) + " " +
            // Arrays.toString(p.ypoints));
            g.setColor(Color.YELLOW);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 270),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 110), nPoints);

            g.drawPolygon(p);
            // System.out.println(Arrays.toString(p.xpoints) + " " +
            // Arrays.toString(p.ypoints));
            g.setColor(Color.YELLOW);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            // row 3 - five grids
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT - 45),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 200), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.PINK);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 45),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 200), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.GREEN);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 135),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 200), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.BLACK);
            g.fillPolygon(p);
            placeNumbers(g, p, !isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 225),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 200), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.GRAY);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 315),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 200), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.RED);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            // row 4 - four grids
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 0),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 290), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.GRAY);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 90),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 290), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.RED);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 180),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 290), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.PINK);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 270),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 290), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.GREEN);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            // row 5 - three grids
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 45),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 380), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.YELLOW);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 135),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 380), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.ORANGE);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 225),
                    Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 380), nPoints);

            g.drawPolygon(p);
            g.setColor(Color.GRAY);
            g.fillPolygon(p);
            placeNumbers(g, p, isValidHex);
            // repaint();
            return g;
        }

    }

Answer:

You must not modify your hexValueList list while painting.

A program does not decide when a component’s paint method is called. The system is in control of that.

Your paint method can be called for many different reasons, all beyond your control. Some possible reasons are:

  • User moves the window
  • User iconifies or deiconifies the window
  • User moves another window in front of your window
  • User brings your window to the front
  • User moves the mouse over your component
  • User locks or blanks the screen
  • User scrolls the web page containing the applet
  • User reloads the web page containing the applet

It is possible for painting to occur many times per second. Or, it may occur only occasionally.

Since you have no control over the timing of calls to your paint method, you must only have drawing logic in it. If you remove values from a List, those values won’t be available during subsequent calls to the paint method.

This is why you must not modify your hexValueList list in the placeNumbers method, since that method is called by drawHexagonalGrid which is called by paint.

Instead of removing numbers from hexValueList, iterate through it, using that List’s iterator() method, and pass each iterated int value as a parameter to placeNumbers:

private void placeNumbers(Graphics g, Polygon p, boolean flag, int hexValue) {
    int x = p.getBounds().x + 30;
    int y = p.getBounds().y + 50;
    int width = p.getBounds().width / 3;
    int height = p.getBounds().width / 3;
    g.drawOval(x, y, width, height);
    g.setColor(Color.WHITE);
    // g.setColor(new Color((int)(Math.random() * 0x1000000)));
    g.fillOval(x, y, width, height);
    g.setColor(Color.BLACK);
    if (flag) {
        g.drawString("" + hexValue, x + 10, y + 20);
    }
}

private Graphics drawHexagonalGrid() {
    Iterator<Integer> hexValueIterator = hexValueList.iterator();

    System.out.println("Drawing the hexagonal grid");
    Graphics g = getGraphics();
    System.out.println("graphics---->" + g);
    boolean isValidHex = true;
    // row 1 - three grids
    Polygon p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 45),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 20), nPoints);
    //
    g.drawPolygon(p);
    g.setColor(Color.GREEN);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 135),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 20), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.BLUE);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 225),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 20), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.RED);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    // row 2 - four grids
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 0),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 110), nPoints);

    g.drawPolygon(p);
    // System.out.println(Arrays.toString(p.xpoints) + " " +
    // Arrays.toString(p.ypoints));
    g.setColor(Color.GRAY);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 90),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 110), nPoints);

    g.drawPolygon(p);
    // System.out.println(Arrays.toString(p.xpoints) + " " +
    // Arrays.toString(p.ypoints));
    g.setColor(Color.ORANGE);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 180),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 110), nPoints);

    g.drawPolygon(p);
    // System.out.println(Arrays.toString(p.xpoints) + " " +
    // Arrays.toString(p.ypoints));
    g.setColor(Color.YELLOW);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 270),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 110), nPoints);

    g.drawPolygon(p);
    // System.out.println(Arrays.toString(p.xpoints) + " " +
    // Arrays.toString(p.ypoints));
    g.setColor(Color.YELLOW);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    // row 3 - five grids
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT - 45),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 200), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.PINK);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 45),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 200), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.GREEN);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 135),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 200), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.BLACK);
    g.fillPolygon(p);
    placeNumbers(g, p, !isValidHex, 0);
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 225),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 200), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.GRAY);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 315),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 200), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.RED);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    // row 4 - four grids
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 0),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 290), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.GRAY);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 90),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 290), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.RED);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 180),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 290), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.PINK);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 270),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 290), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.GREEN);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    // row 5 - three grids
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 45),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 380), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.YELLOW);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 135),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 380), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.ORANGE);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    p = new Polygon(Utilities.getMoreXPoints(xPoints, HEX_CONSTANT + 225),
            Utilities.getMoreYPoints(yPoints, (HEX_CONSTANT / 9) + 380), nPoints);

    g.drawPolygon(p);
    g.setColor(Color.GRAY);
    g.fillPolygon(p);
    placeNumbers(g, p, isValidHex, hexValueIterator.next());
    // repaint();
    return g;
}

Now the painting logic only reads hexValueList, without modifying it, so it won’t matter how often the paint method is called.

I also removed flag = false; since it has no purpose. flag is a method parameter, so changing its value inside the method has no effect outside of the method.