Popup: shown only once

Hi,

I would like to show a popup if a certain condition becomes true; the problem is that the popup is shown only once, then never again:

privateboolean showingPopup;

private PopupFactory popupFactory =new PopupFactory();

private Popup popup;

public PMgmt(l){

JPanel popupPanel =new JPanel();

JLabel popupLabel =new JLabel("popup");

popupPanel.add(popupLabel);

popup = popupFactory.getPopup(this, popupPanel, 100, 100);

(...)

privateboolean isCollision(){

(...)

if (collision){

showingPopup =true;

popup.show();

returntrue;

}

else{

if (showingPopup){

popup.hide();

showingPopup =false;

}

returnfalse;

}

}

protectedvoid paintComponent(Graphics g){

super.paintComponent(g);

Graphics2D g2 = (Graphics2D) g;

if (isCollision()) (...)

(...)

The problem is that the popup is being painted only one time (if isCollision becomes true the first time), then never again. I checked the boolean variable showingPopup, this is ok.

I thought that I have to move the line

popup = popupFactory.getPopup(this, popupPanel, 100, 100);

to the popup.show(); call but this results in an infinite loop of painting the popup (leaving a grey rectangle after hiding it)...

Thanks for your help!

[2419 byte] By [SFLa] at [2007-11-27 3:22:39]
# 1

Hi. I'm not exactly sure what you're trying to do with your code, but I think I know where your problem might lie.

The hide() method in Popup will call dispose(). This means that the popup's resources are freed, and show() should not be called on it again.

I noticed from its source code that Popup itself is not a subclass of Component, instead it contains a component (a subclass of JWindow), and when you invoke show() and hide() on a popup, it in turn invokes them on that JWindow. Maybe you would do better to use JWindow directly, and invoke show() and hide() on it as necessary.

clairec666a at 2007-7-12 8:25:24 > top of Java-index,Desktop,Core GUI APIs...
# 2

Perhaps you might try:

public PMgmt(l) {

JPanel popupPanel = new JPanel();

JLabel popupLabel = new JLabel("popup");

popupPanel.add(popupLabel);

}

private boolean isCollision() {

if (collision) {

showingPopup = true;

popup = popupFactory.getPopup(this, popupPanel, 100, 100);

popup.show();

return true;

}

abillconsla at 2007-7-12 8:25:24 > top of Java-index,Desktop,Core GUI APIs...
# 3

To make my problem more clear to you I added the popup functionality to an existing sample program:

import java.awt.Color;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.Point;

import java.awt.event.MouseEvent;

import java.awt.event.MouseListener;

import java.awt.geom.GeneralPath;

import java.awt.geom.Point2D;

import java.util.ArrayList;

import java.util.List;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JPanel;

import javax.swing.Popup;

import javax.swing.PopupFactory;

import javax.swing.SwingUtilities;

import javax.swing.WindowConstants;

public class GameDemo extends JFrame {

/**

*

*/

private static final long serialVersionUID = 1;

private GamePanel panel;

public GameDemo() {

super("Click...");

setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

setSize(400,300);

panel = new GamePanel();

add(panel);

}

public static void main(String args[]) {

new GameDemo().setVisible(true);

}

}

class GamePanel extends JPanel implements MouseListener {

/**

*

*/

private static final long serialVersionUID = 1;

private List<Point2D> allPlayerCoordinates = new ArrayList<Point2D>();

private Point2D playerCurrentPosition, point;

private Point2D playerStartPosition = new Point2D.Double(0.0, 0.0);

private GeneralPath playerPath = new GeneralPath();

private boolean showingPopup;

JPanel popupPanel;

private PopupFactory popupFactory = new PopupFactory();

private Popup popup;

public GamePanel() {

addMouseListener(this);

playerPath.moveTo(playerStartPosition.getX(), playerStartPosition.getY());

allPlayerCoordinates.add(new Point2D.Double(playerStartPosition.getX(), playerStartPosition.getY()));

// popup initialization

popupPanel = new JPanel();

JLabel popupLabel = new JLabel("Popup");

popupPanel.add(popupLabel);

popupPanel.setBackground(Color.YELLOW);

popup = popupFactory.getPopup(this, popupPanel, 100, 100);

}

public void mouseClicked(final MouseEvent evt) {

if (SwingUtilities.isLeftMouseButton(evt)) {

playerCurrentPosition = new Point(evt.getX(), evt.getY());

allPlayerCoordinates.add(playerCurrentPosition);

}

if (SwingUtilities.isRightMouseButton(evt)) {

if (allPlayerCoordinates.size() > 1) {

int lastItem = allPlayerCoordinates.size() - 1;

allPlayerCoordinates.remove(lastItem);

}

}

repaint();

}

protected void paintComponent(final Graphics g) {

super.paintComponent(g);

Graphics2D g2 = (Graphics2D) g;

playerPath = new GeneralPath();

if(allPlayerCoordinates.size() > 0) {

Point2D p = allPlayerCoordinates.get(0);

playerPath.moveTo(p.getX(), p.getY());

}

for (int i = 1 ; i < allPlayerCoordinates.size(); i++) {

point = allPlayerCoordinates.get(i);

playerPath.lineTo(point.getX(), point.getY());

}

// popup if-statement

if(allPlayerCoordinates.size() > 1) {

if (point.getY() > 200) {

showingPopup = true;

// infinite loop if uncommenting the following line and commenting line #68

// popup = popupFactory.getPopup(this, popupPanel, 100, 100);

popup.show();

System.out.println("popup");

}

else {

if (showingPopup) {

popup.hide();

showingPopup = false;

System.out.println("no popup");

}

}

}

g2.draw(playerPath);

}

public void mousePressed(final MouseEvent e) {}

public void mouseReleased(final MouseEvent e) {}

public void mouseEntered(final MouseEvent e) {}

public void mouseExited(final MouseEvent e) {}

}

Just try it out... I show the popup if you click on a coordinate Y > 200px.

Thanks, thanks, thanks!

Edit: after rereading the javax.swing.Popup API I maybe know the cause: "Popups have a very small life cycle. Once you have obtained a Popup, and hidden it (invoked the hide method), you should no longer invoke any methods on it. This allows the PopupFactory to cache Popups for later use.". Does this mean that I can show a popup only once? This doesn't make sense...?

Message was edited by:

SFL

SFLa at 2007-7-12 8:25:24 > top of Java-index,Desktop,Core GUI APIs...
# 4
Yes, we know that - we pointed that out to you in fact, and the code I posted was tried in a somewhat larger pgm to demonstrate it's functioning. Did you try it?
abillconsla at 2007-7-12 8:25:24 > top of Java-index,Desktop,Core GUI APIs...
# 5
Yes, yes, I tried it :)I already solved the problem by moving the popup-code out of the paintComponent method and by creating a own popup method. My mistake was mainly the wrong use of PopupFactory.
SFLa at 2007-7-12 8:25:24 > top of Java-index,Desktop,Core GUI APIs...