我正在编写主菜单+网络流量监控器。我的系统运行Linux Cinnamon Mint。
问题是应用程序的标题总是出现在菜单上。
当我点击图标化窗口时,JFrame打开,JPopoupMenu出现在它上面。 当鼠标指针位于面板内部时,标题会悬停在图标化窗口上方,但是当我将其移动到菜单上时它不会消失。
未捕获鼠标指针,但它位于左侧图片中的面板内(在图标化窗口上方)和右侧菜单上方。
如果我这样做,但没有显示菜单(JFrame的窗口与菜单大小相同),标题仅在鼠标指针位于面板内时出现。
我尝试过'popupMenu.setInvoker(Component)'的不同组件,但在少数情况下问题消失,菜单失去焦点。
先感谢您的帮助。
这是我拼凑在一起的SSCCE(Main.java),因此您可以测试代码:
// To run: javac Main.java; java Main
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GraphicsEnvironment;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.WindowConstants;
/**
*
* @author Manuel Iglesias Alonso glesialo@gmail.com
*/
public class Main extends JFrame {
private final MainMenu mainMenu;
private boolean menuPopupEnabled;
public Main(ImageIcon icon, File rootMenuDirectory) {
super();
menuPopupEnabled = false;
setIconImage(icon.getImage());
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowDeiconified(WindowEvent e) {
super.windowDeiconified(e);
if (menuPopupEnabled) {
mainMenu.popup(MouseInfo.getPointerInfo().getLocation());
}
}
});
mainMenu = new MainMenu(this, rootMenuDirectory);
pack(); // Before setPreferredSize: smaller window size.
setPreferredSize(new Dimension(0, 0)); // Window is always hidden behind menu, the smaller the better.
setVisible(true);
}
private class MainMenu {
private final int panelHeight = 25;
private final int iconizedWindowWidthPanelHeightRatio = 5; // Iconized window's width / Iconized window' height
private final JFrame frame;
private final File rootMenuDirectory;
private final Rectangle graphicsBounds;
private PopupMenuInFrame popupMenu;
private class PopupMenuInFrame extends JPopupMenu {
@Override
protected void firePopupMenuWillBecomeInvisible() {
super.firePopupMenuWillBecomeInvisible();
frame.setExtendedState(JFrame.ICONIFIED);
}
}
/**
*
* @param rootMenuDirectory Directory where menu files are to be found.
*/
public MainMenu(JFrame frame, File rootMenuDirectory) {
this.frame = frame;
this.rootMenuDirectory = rootMenuDirectory;
graphicsBounds = frame.getGraphicsConfiguration().getBounds();
}
private void newMenu() {
popupMenu = new PopupMenuInFrame();
JMenuItem menuItem = new JMenuItem("1st popup menu item");
menuItem.setToolTipText("1st ToolTip");
popupMenu.add(menuItem);
menuItem = new JMenuItem("2nd popup menu item");
menuItem.setToolTipText("2nd popup menu item ToolTip");
popupMenu.add(menuItem);
menuItem = new JMenuItem("3rd A popup menu item");
menuItem.setToolTipText("menu item ToolTip");
popupMenu.add(menuItem);
menuItem = new JMenuItem("4th popup menu item");
menuItem.setToolTipText("4th popup menu item menu item ToolTip");
popupMenu.add(menuItem);
menuItem = new JMenuItem("5th popup menu item");
menuItem.setToolTipText("ToolTip");
popupMenu.add(menuItem);
menuItem = new JMenuItem("6th popup menu item");
menuItem.setToolTipText("popup menu item menu item ToolTip");
popupMenu.add(menuItem);
}
public void popup(Point mousePointerPosition) {
Point menuPosition;
newMenu();
popupMenu.setInvoker(frame.getContentPane());
menuPosition = new Point(mousePointerPosition.x, mousePointerPosition.y);
if (mousePointerPosition.x < iconizedWindowWidthPanelHeightRatio * panelHeight) { //If pointer near leftmost border (within width of iconized window).
if (mousePointerPosition.y < (panelHeight + 1)
|| mousePointerPosition.y > (graphicsBounds.height - panelHeight - 1)) { //If pointer inside a top or bottom panel
menuPosition.x = 1; // Position: near left border.
}
}
if (mousePointerPosition.y < (panelHeight + 1)) { //If pointer inside a top panel (within panel's height + 1)
menuPosition.y = panelHeight + 1; //Menu's top edge just below the panel's lower edge.
} else {
if (mousePointerPosition.y > (graphicsBounds.height - panelHeight - 1)) { //If pointer inside a bottom panel (within panel's height + 1)
menuPosition.y = graphicsBounds.height - popupMenu.getPreferredSize().height - panelHeight - 1; //Menu's lower edge just above the panel's upper edge.
}
}
frame.setLocation(menuPosition.x + 5, menuPosition.y + 5); // + 5 to make sure window is hidden behind popupMenu.
popupMenu.setLocation(menuPosition.x, menuPosition.y);
popupMenu.setVisible(true);
}
}
public static void main(String[] args) {
final ImageIcon icon;
final File rootMenuDirectory;
icon = new ImageIcon();
rootMenuDirectory = new File("");
Main frame = new Main(icon, rootMenuDirectory);
frame.setTitle("Test title");
try {
Thread.sleep(500);
} catch (Exception e) {
}
if (!GraphicsEnvironment.isHeadless()) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
frame.setExtendedState(JFrame.ICONIFIED); // Start iconified. If setExtendedState used out of run(), window's events are blocked.
frame.menuPopupEnabled = true; // Menu can pop from now on.
}
});
} else {
System.exit(1);
}
}
}
PS:我已经修改了SSCCE向菜单项添加工具提示。还有一个问题:有时(在向上和向下移动鼠标指针时,菜单项上方)工具提示似乎不完整:
没人帮忙? : - (
我差不多完成了申请。我添加了一个额外的菜单项'MainMenu:About',因此该项目是该死的vindow标题所涵盖的唯一部分(菜单操作后标题消失:子菜单,工具提示......)。 oracle的教程示例(如果我添加工具提示)也会出现工具提示不完整的问题,因此它与我的代码无关。
这是运行菜单的图片(当它位于面板的最左侧时,它将移动到图标化窗口上方:第一个启动应用程序):
应用程序向窗口管理器发送“粘性”提示,窗口出现在所有工作区中。