3

I'm learning Java at college and this is from my assignment. The task is to create a x by y grid of color squares that each run in a separate thread and every k ms either change it's color to a random one or average the color of it's neighbours.

Now, if I create a 30 by 30 grid everything runs fine. However, if I try it with 40 by 40, I get the following exception once when the app starts and once when I close it. Apart from that it appears to run correctly, although the grid appears to be positioned within the window slightly wrongly (it's narrower than it should be).

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.util.TimSort.mergeLo(TimSort.java:747)
    at java.util.TimSort.mergeAt(TimSort.java:483)
    at java.util.TimSort.mergeCollapse(TimSort.java:410)
    at java.util.TimSort.sort(TimSort.java:214)
    at java.util.TimSort.sort(TimSort.java:173)
    at java.util.Arrays.sort(Arrays.java:659)
    at java.util.Collections.sort(Collections.java:217)
    at javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(SortingFocusTraversalPolicy.java:136)
    at javax.swing.SortingFocusTraversalPolicy.getFocusTraversalCycle(SortingFocusTraversalPolicy.java:110)
    at javax.swing.SortingFocusTraversalPolicy.getFirstComponent(SortingFocusTraversalPolicy.java:435)
    at javax.swing.LayoutFocusTraversalPolicy.getFirstComponent(LayoutFocusTraversalPolicy.java:166)
    at javax.swing.SortingFocusTraversalPolicy.getDefaultComponent(SortingFocusTraversalPolicy.java:515)
    at java.awt.FocusTraversalPolicy.getInitialComponent(FocusTraversalPolicy.java:169)
    at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:380)
    at java.awt.Component.dispatchEventImpl(Component.java:4731)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Window.dispatchEventImpl(Window.java:2719)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:729)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:688)
    at java.awt.EventQueue$3.run(EventQueue.java:686)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:702)
    at java.awt.EventQueue$4.run(EventQueue.java:700)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:699)
    at java.awt.SequencedEvent.dispatch(SequencedEvent.java:128)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:727)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:688)
    at java.awt.EventQueue$3.run(EventQueue.java:686)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:702)
    at java.awt.EventQueue$4.run(EventQueue.java:700)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:699)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

Here's my code: The main class Symulacja:

import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.Random;

// main class
@SuppressWarnings("serial")
public class Symulacja extends JPanel {
    public Symulacja(int x, int y, int k, double p) {
        super();
        Field.delay = k;
        Field.p = p;
        Field.random = new Random();

        setLayout(new GridLayout(y, x));

        //creating Field objects and adding them to the panel
        Field fv[][] = new Field[y][];
        for (int i = 0; i<y; i++){
            fv[i] = new Field[x];
            for (int j = 0; j<x; j++){
                fv[i][j] = new Field();
                add(fv[i][j]);
            }
        }

        //setting the neighbours in all Field objects
        for (int i = 0; i<y; i++){
            for (int j = 0 ; j<x; j++){
                Field fv2[] = {fv[(i+1)%y][j], fv[(i+y-1)%y][j], fv[i][(j+1)%x], fv[i][(j+x-1)%x]};
                fv[i][j].setArr(fv2);
            }
        }

        //starting the threads
        for (int i = 0; i<y; i++){
            for (int j = 0 ; j<x; j++){
                new Thread(fv[i][j]).start();
            }
        }

    }

    public static void main(String[] args) {
        Symulacja s = new Symulacja(30,30,100,0); //works
        //Symulacja s = new Symulacja(40,40,100,0); //throws exception
        JFrame f = new JFrame();
        f.setLayout(new BorderLayout());
        f.add(s, BorderLayout.CENTER);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        f.setSize(400, 400);
    }

}

The Field class (a single grid element):

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;

@SuppressWarnings("serial")
class Field extends Canvas implements Runnable
{
    Field()
    {
        color = nextInt();
        randFlag = false;

        //zmiana koloru na losowy po kliknięciu myszą
        addMouseListener(new MouseAdapter() 
        {
            public void mouseClicked(MouseEvent e)
            {
                randFlag = true;
            }
        });
    }


    void setArr(Field[] a)
    {
        fieldArr = a;
    }


    public void run()
    {
        while (true){
            double rand = nextDouble();
            int newcolor;
            if (rand <= p || randFlag){ // losowy kolor lub kliknięcie myszą
                newcolor = nextInt();
                randFlag = false;
            }
            else{ // uśredniony kolor
                newcolor = 0;
                for (Field f: fieldArr)
                    newcolor+=f.getColor()/4;
            }

            if (newcolor!=getColor()){
                setColor(newcolor);
                repaint();
            }

            try {
                Thread.sleep((long)((nextDouble() + 0.5)*delay));
            } catch (InterruptedException e) {
                return;
            }
        }
    }


    public void paint(Graphics g)
    {
        g.setColor(new Color(getColor()));
        g.fillRect(0, 0, getWidth(), getHeight());
        g.dispose();
    }


    synchronized public int getColor()
    {
        return color;
    }


    synchronized private void setColor(int color)
    {
        this.color = color;
    }


    private int nextInt()
    {
        synchronized (random) {
            return random.nextInt();
        }
    }


    private double nextDouble()
    {
        synchronized (random) {
            return random.nextDouble();
        }
    }

    static public int delay;
    static public double p;

    Field fieldArr[];
    private int color;

    boolean randFlag;
    static Random random;
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
user697683
  • 1,423
  • 13
  • 24
  • 2
    Can you pin point the exact line and post the stacktrace, , as your code is vast! ? Somewhere the `compareTo` or `compare` method is wrong. – AllTooSir May 09 '13 at 16:32
  • @NoobUnChained I posted the full backtrace but Azad Omer edited my post and removed it for some reason... See the original revision for the full thing. – user697683 May 09 '13 at 21:22
  • I rollbacked the edit to get back the full stack trace. – JB Nizet May 09 '13 at 21:47
  • 2
    @user697683 Maybe a bug in your JVM? http://stackoverflow.com/questions/13575224/comparison-method-violates-its-general-contract-timsort-and-gridlayout – mange May 10 '13 at 00:52
  • Thanks, looks like it's the same thing. I'll try reporting it later. – user697683 May 10 '13 at 05:58

0 Answers0