JPopupPanel закрывается при нажатии на его JPopupMenu
У меня есть JPopupPanel
появляется при нажатии кнопки.
это JPopupPanel
имеет JPopupMenu
который появляется при щелчке правой кнопкой мыши, показывая различные варианты. Когда левая кнопка нажата, чтобы выбрать один из этих параметров в PopupMenu, PopupPanel на мгновение закрывается, оставляя PopupMenu самостоятельно, и когда кнопка отпускается, PopupMenu также исчезает (как и ожидалось), но действие не отображается в PopupPanel, так как он уже закрыт.
Как я могу избежать закрытия JPopupPanel при выборе одного из параметров JPopupMenu?
Спасибо
2 ответа
Я столкнулся с этой проблемой сам, когда устанавливал пользовательское JPopupMenu на JCommandButton. Для вашего JCommandButton я обнаружил, что это поможет предотвратить преждевременное удаление родительского всплывающего окна:
this.putClientProperty(BasicCommandButtonUI.DONT_DISPOSE_POPUPS, true);
Если вместо этого вам нужно, чтобы при выборе JPopupMenu JMenuItem родительская всплывающая панель оставалась открытой, у вас есть пара вариантов. Проблема связана с неработающей связью JPopupMenu в цепочке контейнеров предков, на которую опирается пользовательский интерфейс. Вместо getParent () вам нужно вернуть getInvoker ().
1:
изменить исходный код библиотеки в BasicPopupPanelUI.WindowTracker.eventDispatched (). Либо измените вызовы SwingUtilities.getAncestorOfClass (), чтобы использовать SwingXUtilities.getAncestorOfClass (), который учитывает этот особый случай. Или реализовать логику самостоятельно.
if(parent instanceof JPopupMenu) parent = ((JPopupMenu)parent).getInvoker()
2:
Добавить этот код в виджет (CustomButton?)
final JPopupMenu popper = new JPopupMenu(){ //hack
@Override public Container getParent(){
StackTraceElement ste = Thread.currentThread().getStackTrace()[2];
if(ste.getClassName().equals(SwingUtilities.class.getName()))
return CustomButton.this.getParent();
return super.getParent();
}
};
Я выбрал #2, так как у меня есть проблемы с изменением сторонних библиотек.
Извините, у меня нет опыта использования JPopupPanel. Таким образом, я могу предложить только простой взлом.
Я подозреваю, что вы можете сделать что-то подобное, как в моем примере (ниже), где я "игнорирую" скрывающееся всплывающее меню при выборе опции.
Мой подход здесь состоит в том, чтобы повторно показать всплывающее меню на выбор опции. Поэтому, возможно, вы можете попытаться переоткрыть панель, когда она скрывается.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
public class JPopupMenuIgnoreOptionCloseOnClick extends JPanel
{
private static final long serialVersionUID = 1L;
private JPopupMenu popup = new JPopupMenu("Oi I am popup");
private MouseListener mL = new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent e)
{
System.out.println("mL mousePressed e.isP="+e.isPopupTrigger());
super.mousePressed(e);
showPopup(e);
}
@Override
public void mouseReleased(MouseEvent e)
{
System.out.println("mL mouseReleased e.isP="+e.isPopupTrigger());
super.mouseReleased(e);
showPopup(e);
}
private void showPopup(MouseEvent e)
{
if(e.isPopupTrigger())
{
prevLocation = e.getPoint();
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
};
private Point prevLocation = null;
private MouseListener optionML = new MouseAdapter()
{
@Override
public void mouseReleased(MouseEvent e)
{
System.out.println("optionML mouseReleased prevLocation="+prevLocation);
e.consume();
popup.show(JPopupMenuIgnoreOptionCloseOnClick.this, prevLocation.x,prevLocation.y);
}
};
public JPopupMenuIgnoreOptionCloseOnClick()
{
addMouseListener(mL);
JMenuItem opt1 =new JMenuItem("Option 1");
opt1.addMouseListener(optionML);
popup.add(opt1);
JMenuItem opt2 =new JMenuItem("Option 2");
opt2.addMouseListener(optionML);
popup.add(opt2);
JMenuItem opt3 =new JMenuItem("Option 3");
opt3.addMouseListener(optionML);
popup.add(opt3);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JPopupMenuIgnoreOptionCloseOnClick p = new JPopupMenuIgnoreOptionCloseOnClick();
p.setPreferredSize(new Dimension(400, 400));
JPanel contentPane = new JPanel();
contentPane.setBackground(Color.CYAN);
contentPane.add(p);
JFrame f = new JFrame();
f.setContentPane(contentPane);
f.setSize(800, 600);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
});
}
}