2016-08-14 3 views
0

J'implémente un jeu où le joueur peut placer une pièce en faisant un clic droit sur le plateau de jeu et en choisissant l'une des pièces parmi un menu contextuel. En mode "hot seat", les deux joueurs utilisent la même interface utilisateur, ce qui permet d'afficher différentes instances de menu. Le problème est que l'appel de la méthode JMenuItem.show entraîne le rendu incorrect du mauvais menu, puis son remplacement rapide par le bon menu (vous pouvez dire que les icônes utilisées dans les entrées de menu ont des couleurs de fond différentes pour chaque lecteur). Je peux aggraver le problème en ajoutant Thread.sleep(1000) immédiatement après avoir appelé show. Ensuite, cliquez avec le bouton droit de la souris sur le menu de l'autre joueur précédemment affiché (ou seulement sur l'arrière-plan de la bonne taille, sur la toute première invocation) pendant une seconde, suivi d'un rafraîchissement du menu.Comment rendre un JPopupMenu immédiatement?

Y at-il un moyen de rendre le menu correct immédiatement?

Vous ne savez pas si cela est important, mais il n'y a aucun appel à repaint n'importe où dans le rappel de traitement de clic dans la branche isPopupTrigger.

Edit: ajout d'un exemple dans Scala

import java.awt.event._ 
import javax.swing._ 

object MenuDemo extends App { 
    val frame = new JFrame() 
    frame.setTitle("Menu Demo") 
    frame.setSize(600, 400) 
    frame.setLocation(0, 0) 
    frame.addWindowListener(new WindowAdapter { 
    override def windowClosing(e: WindowEvent): Unit = System.exit(0) 
    }) 

    var index = 0 
    def tick() = index = (index + 1) % 2 

    def makeMenuItem(i: Int) = { 
    val menuItem = new JMenuItem("item in menu #" + i) 
    menuItem.addActionListener(new ActionListener { 
     override def actionPerformed(e: ActionEvent): Unit = tick() 
    }) 
    menuItem 
    } 

    def makeMenu(i: Int) = { 
    val menu = new JPopupMenu() 
    menu.add(makeMenuItem(i)) 
    menu 
    } 

    val menus: Seq[JPopupMenu] = Seq(0, 1).map(i => makeMenu(i)) 

    def showMenu(e: MouseEvent): Unit = { 
    menus(index).show(e.getComponent, e.getX, e.getY) 
    Thread.sleep(1000) 
    } 

    val panel = new JPanel() 
    panel.add(new JLabel("right click me")) 

    panel.addMouseListener(new MouseAdapter { 
    override def mousePressed(e: MouseEvent): Unit = { 
     if (e.isPopupTrigger) showMenu(e) 
    } 

    override def mouseReleased(e: MouseEvent): Unit = { 
     if (e.isPopupTrigger) showMenu(e) 
    } 
    }) 

    frame.getContentPane.add(panel) 
    frame.setVisible(true) 
} 

Edit 2

Je ne vois que ce comportement sur un Mac. Sous Windows, le délai se produit avant l'affichage du menu.

+1

Pensez à poster un [mcve] qui reproduit le problème. – copeg

+0

'Yat-il un moyen de rendre le menu correct immédiatement?' - C'est le comportement par défaut, le problème est avec votre code. Lisez la section du tutoriel Swing sur [Appeler un menu contextuel] (http://docs.oracle.com/javase/tutorial/uiswing/components/menu.html#popup) pour un exemple de travail – camickr

Répondre

0

Il semble que les éléments du menu puissent être réorganisés après l'appel de la méthode show. Par exemple javax.swing.event.PopupMenuListener.popupMenuWillBecomeVisible peut réinitialiser les éléments de menu en fonction du contexte.

Si tel est le cas, vous pouvez éviter le scintillement en affichant deux occurrences différentes de menu contextuel et d'appel sur l'une d'entre elles en fonction du contexte.

+0

C'est exactement ce que j'avais : deux menus, pas de réorganisation (sauf activation et désactivation des entrées individuelles). – StokedOver9k