JAN
JAN

Reputation: 21885

Add a keyListener inside a loop ? Is it possible?

I have listener that enters this code :

        someBoolean = true;
        case FILL_POLYGON:      
        {
            if (greenLightForFilling == true)
            {
                while (someBoolean)
                {
                    fillPressed = true;
                    fillPolygon(polyFiller);
                }

            }
            break;

        }  // end FILL_POLYGON

When I hit f .

Is it possible to add another listener inside that while loop , so when the user hits f again , someBoolean would get false ?

Please notice , I already have a key-listener for entering the switch-case .

Regards

EDIT - Relevant code :

public class DrawPolygons
{
    public static void main (String[] args) throws FileNotFoundException
    {
        // attaching the menu to the frame
        final JFrame frame = new JFrame("Draw polygons");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(new DrawingPanel());
        frame.pack();
        frame.setVisible(true);
    }

}


/**
 * Main class
 * @author X2
 *
 */
class DrawingPanel extends JPanel implements MouseListener, MouseMotionListener ,KeyListener
{
    /**
     *    private variables
     */

    // dimensions of the window
    private static final long serialVersionUID = 1L;
    private static final Dimension MIN_DIM = new Dimension(300, 300);
    private static final Dimension PREF_DIM = new Dimension(500, 500);


    // Hot-keys hit by the user - used for keyboard listening
    private static final char FILL_POLYGON = 'F';
    private static final char SAVE_POLYGONS = 'S';
    private static final char LOAD_POLYGONS = 'L';
    private static final char FILL_POLYGON_LOWERCASE = 'f';
    private static final char SAVE_POLYGONS_LOWERCASE = 's';
    private static final char LOAD_POLYGONS_LOWERCASE = 'l';
    private static final String SPACE = " ";


    // boolean flags
    private boolean greenLightForFilling = false;
    private boolean polygonDone = false;
    private boolean loading = false;
    private boolean loading2 = false;
    private boolean fillPressed = false;

    // data structures

    // The dummy point tracking the mouse
    private final Point trackPoint = new Point();                    

    // The list of points making up a polygon
    private ArrayList<Point> points = new ArrayList<Point>();   

    // holds edges of current polygon
    private ArrayList<Edge> edges = new ArrayList<Edge>();  

    // array-list of vertices
    private ArrayList<Point> vertices = new ArrayList<Point>();      

    // all the polygons
    private ArrayList<Polygon> polygons = new ArrayList<Polygon>();  

    // count the vertices
    private int verticesCounter = 0;

    // hold polygon vertices for the polygon-filling
    private Vector<Point> polygon = new Vector<Point>();

    private ArrayList<Point> bigVerticesList= new ArrayList<Point>();

    static int counter = 0;
    /**
     * Setting the dimensions of the window
     */
    public Dimension getMinimumSize() { return MIN_DIM; }

    public Dimension getPreferredSize() { return PREF_DIM; }

    /**
     *  The constructor
     */
    DrawingPanel()
    {
        super();
        addMouseListener(this);
        addMouseMotionListener(this);
        addKeyListener(this);
        setFocusable(true);
        requestFocusInWindow();
    }



    /**
     *  The drawing itself 
     */
    public void paintComponent(Graphics g)
    {

        super.paintComponent(g);

        // draw previous polygons

        if (this.polygons.size() > 0)
            drawPreviousPolygons(g);


        int numPoints = points.size();
        if (numPoints == 0)
            return; // nothing to draw


        Point prevPoint = points.get(0);

        // draw polygon
        Iterator<Point> it = points.iterator();
        while (it.hasNext())
        {
            Point curPoint = it.next();
            draw(g, prevPoint, curPoint);           
            prevPoint = curPoint;
        }

        // now draw tracking line or complete the polygon
        if (polygonDone == true)
        {
            Point point0 = points.get(0);       // grab the starting point (x,y) 

            // draw the last edge between the starting point & the last point 
            draw(g, prevPoint, point0);

        }

        else  // polygonDone == false
            draw(g, prevPoint, trackPoint); 

    }



    /**
     * MouseListener interface 
     */
    public void mouseClicked(MouseEvent evt)
    {
        int x = evt.getX();
        int y = evt.getY();

        if (polygonDone == false)
        {
            Point p = new Point(x,y);       // new point 
            vertices.add(p);                // add to vertices list 
            this.verticesCounter++; 
        }


        if (verticesCounter > 1)    // create a new edge 
        {
            int verSize = vertices.size();      // grab number of vertices
            Point p1 = vertices.get(verSize - 1); // grab the last vertex 
            Point p2 = vertices.get(verSize - 2); // grab the one before last vertex 

            // create the current edge between the two points P1 and P2
            Edge currentEdge = new Edge(p1,p2);

            // add the edge to the edges list 
            if (polygonDone == false)
                this.edges.add(currentEdge);

        }

        switch (evt.getClickCount())
        {
            case 1: // single-click
                if (polygonDone == true)
                {
                    /**
                     * remove all the entries from the edges list - preparing for the next polygon  
                     */


                    // first add the last edge between the final vertex and the first vertex
                    Point p1 = null ,p2 = null;
                    if (!loading)
                    {
                        p1 = this.vertices.get(0);  // grab 1st vertex 
                        int verSize = vertices.size();                      
                        p2 = vertices.get(verSize - 1);     // grab last vertex 
                        // create the last edge between the final point & the first point 
                        Edge currentEdge = new Edge(p1,p2);

                        // add the last edge to the edges list 
                        this.edges.add(currentEdge);        
                    }


                    if (loading)
                        loading = false;

                    // create the new polygon structure with the edges 
                    Polygon poly = new Polygon(this.edges , this.vertices);

                    // add the polygon to the polygons array 
                    this.polygons.add(poly);

                    // reset edges ,reset points , reset vertices-counter , reset vertices  

                    greenLightForFilling = true;

                    verticesCounter = 0;
                    edges.clear();
                    points.clear();  
                    vertices.clear();
                    polygonDone = false;
                    repaint();
                    break;

                }
                points.add(new Point(x, y));
                repaint();
                break;

            case 2: // double-click
                polygonDone = true;
                points.add(new Point(x, y));
                repaint();
                break;

            default: // ignore anything else
                break;
        }
    }






    /**
     * MouseMotionListener interface 
     */
    public void mouseMoved(MouseEvent evt)
    {
        trackPoint.x = evt.getX();
        trackPoint.y = evt.getY();
        repaint();
    }



    /**
     * draw points and lines 
     * @param g
     * @param p1
     * @param p2
     */
    private void draw(Graphics g, Point p1, Point p2)
    {
        int x1 = p1.x;
        int y1 = p1.y;

        int x2 = p2.x;
        int y2 = p2.y;

        // draw the line
        g.setColor(Color.green.darker());
        g.drawLine(x1 + 3, y1 + 3, x2 + 3, y2 + 3);

        // now just paint the edge between those two points
        g.setColor(Color.green);
        g.fillOval(x1, y1, 8, 8);

        g.setColor(Color.black);
        g.fillOval(x2, y2, 8, 8);

        greenLightForFilling = false;       
    }





    /**
     * Run on the arrayList of the Polygons , and draw the previous polygons 
     * that we already made 
     * @param g
     */
    private void drawPreviousPolygons(Graphics g) 
    {
        int i = 0;

        while (i < this.polygons.size())
        {
            Polygon currentPoly = polygons.get(i);  // grab current polygon
            int j = 0; 

            ArrayList<Edge> edges = currentPoly.getPolygonEdges();


            // draw the edges of the polygon
            while (j < edges.size()) // run on all the edges of the polygon
            {
                Edge edgeCurrent = edges.get(j);        // grab current edge

                // drawing the edge 

                // now draw it - grab the two points that create the edge
                int x1 = edgeCurrent.getX1();
                int y1 = edgeCurrent.getY1();

                int x2 = edgeCurrent.getX2();
                int y2 = edgeCurrent.getY2();

                // draw the line first so that the points appear on top of the line ends, not below
                g.setColor(Color.green.darker());
                g.drawLine(x1 + 3, y1 + 3, x2 + 3, y2 + 3);

                // now just paint the edge between those two points
                g.setColor(Color.green);
                g.fillOval(x1, y1, 8, 8);

                g.setColor(Color.black);
                g.fillOval(x2, y2, 8, 8);

                // proceed to next edge 

                j++; 


            }

            i++;    // next polygon

        }


    }


    @Override
    public void keyTyped(KeyEvent keyEvent) 
    {
        PolygonFiller polyFiller = new PolygonFiller();
        char key = keyEvent.getKeyChar();


        switch(key)
        {
            /**
             *  Fill the polygons 
             */
            case FILL_POLYGON:      
            {
                if (greenLightForFilling == true)
                {
                    while (true)
                    {
                        fillPolygon(polyFiller);
                    }

                }
                break;

            }  // end FILL_POLYGON


            case FILL_POLYGON_LOWERCASE:
            {
                if (greenLightForFilling == true)
                {
                    fillPolygon(polyFiller);
                }
                break;              

            }

            /**
             *  save all polygons in a .scn file
             */
            case SAVE_POLYGONS :         
            {
                if (greenLightForFilling == true)
                {
                    saveWorkspace();
                } 
                break;  
            }   // end SAVE_POLYGONS



            case SAVE_POLYGONS_LOWERCASE:
            {
                if (greenLightForFilling == true)
                {
                    saveWorkspace();
                } 
                break;  
            }

            /**
             *  Delete everything & load all polygons from .scn file
             */
            case LOAD_POLYGONS:      
            {
                loadWorkspace();
                break;
            }   

            case LOAD_POLYGONS_LOWERCASE:
            {
                loadWorkspace();
                break;
            }

            default: break;  
        } // end switch


    } 

Upvotes: 2

Views: 1800

Answers (2)

Sterling Duchess
Sterling Duchess

Reputation: 2090

You can by following example:

    Component.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent e)
        {
            //Execute when button is pressed
        }
    }); 

Simply change ActionListener to whatever Listener you need. However since you already have a listener that for Key strokes you could possibly just use that one..

Upvotes: 0

arcy
arcy

Reputation: 13143

I don't see why not. There are a couple of things to consider.

The key listener itself runs on the event dispatch thread; you don't want this loop on that thread, because the code for the second keypress also runs in that thread. So the first keypress needs to start a SwingWorker or some other thread to run the fill.

I would suggest that the polygon filler either operate slowly (do a little filling and then pause somehow unless filling takes a noticeable amount of time), otherwise it is bound to complete filling before the second keypress. It may also need to 'flush' the filling output so that buffering doesn't remove the visible effect.

--- addendeum

I wouldn't create an additional keylistener, I would just use the one I had. I would have a boolean switch in that listener that indicated whether I was in "drawing mode" or not; if not, start the drawing loop and change the switch, if so, terminate the drawing loop and change the switch.

I would write a class which job it was to execute the filling loop, and make it runnable. When it was time to start the loop, I would instantiate it and run it in a SwingWorker thread. The loop would fill a little, sleep a little, and then fill a little more until done. I don't know anything about your fill loop, so you'll have to fill in here.

Your keylistener could keep a reference to the loop-filling object, and call a method on it to set the "end loop" boolean you mention. The loop in that class would check the boolean between fills.

There are many examples available on the web of how to start a SwingWorker thread that operates outside the event dispatch thread; I could create one, but you don't seem to have any specific question about it, so the general-case documentation and examples should serve. If you try it and run into a specific problem, post that question back to SO.

Upvotes: 3

Related Questions