Reputation: 21885
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
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
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