• Custom Swing Menu Bar with WebLike Appearance & Behavior


    http://blogs.oracle.com/geertjan/entry/custom_swing_menu_bar_with

    ——————————————————————————————————————————————————————————————————

    Yesterday you saw how to provide a highly customized menu bar in a NetBeans Platform application. Let's now take it a few steps further. We imagine that our requirements have changed, we now need to provide a Login feature from our menu bar and we need the menus to resemble hyperlinks, both in terms of appearance and in terms of behavior. In the end, we'll have a menu bar that looks like this:

    Indeed, our application is going to pick up a few idioms from the web! To show some more detail, when you click on "User Name" above, you will see this, i.e., menu items for logging in/out of the application:

    And when you move your mouse over one of the hyperlinks, the underlying menu items are shown:

    So, to achieve the above result, we need to customize the menus in the menu bar, create the Login feature, and add the Login feature to the menu bar.

    Seriously, it's all reasonably trivial to do.

    First create a new JPanel named "LoginPanel". Add two JLabels, one named "welcomeLabel" and the other "userNameLabel". In the second label, i.e., "userNameLabel", add a "down arrow" icon and pass "SwingConstants.LEFT" to the label's "setHorizontalTextPosition". And here's the constructor of my LoginPanel, where the JPopupMenu is constructed:

    public LoginPanel() {
        initComponents();
        setOpaque(false);
        JMenuItem signInItem = new JMenuItem("Sign In");
        signInItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //do something here
            }
        });
        JMenuItem signOutItem = new JMenuItem("Sign Out");
        signOutItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //do something here
            }
        });
        menu.add(signInItem);
        menu.add(signOutItem);
    }
    I.e., make sure to setOpaque to "false" so that the underlying image bleeds through your JPanel. Then add two menu items to a JPopUpMenu that you've defined somewhere in your LoginPanel:
    JPopupMenu menu = new JPopupMenu();
    Finally, add a MouseListener to the second JLabel, i.e., to "userNameLabel". When the mouse is pressed on the second JLabel, let this happen:

    menu.show(evt.getComponent(), evt.getX(), evt.getY());
    OK, the LoginPanel is done. Now you need to add it to your own custom menu bar. Here's the rewritten constructor of my menu bar. Take note of the fact that I'm using MigLayout to add the LoginPanel and the menus to the menu bar. Also take note of the fact that I'm using HTML to style the text of the menus and that there's a mouse listener on the menus that will cause the menu items to appear when the mouse moves over the menus:

    public MyMenuBar() {
        FileObject menuFolder = FileUtil.getConfigFile("Menu");
        FileObject[] menuKids = menuFolder.getChildren();
        setLayout(new MigLayout("align right"));
        JPanel p = new LoginPanel();
        add(p, "span, align right");
        for (final FileObject menuKid : FileUtil.getOrder(Arrays.asList(menuKids), true)) {
            final JMenu m = new JMenu();
            m.setText("<html><body><font color=\"blue\"><u>" + menuKid.getName() + "</u></font></body></html>");
            if (m != null) {
                m.addMouseListener(new MouseListener() {
                    @Override
                    public void mouseClicked(MouseEvent e) {
                    }
                    @Override
                    public void mousePressed(MouseEvent e) {
                    }
                    @Override
                    public void mouseReleased(MouseEvent e) {
                    }
                    @Override
                    public void mouseEntered(MouseEvent evt) {
                        m.doClick(1);
                    }
                    @Override
                    public void mouseExited(MouseEvent e) {
                    }
                });
                add(m);
            }
            ...
            ...
            ...
    That's all, you're done. You can play a bit with the HTML, for example, try this:

    String name = menuKid.getName();
    m.setText("<html><body><font color=\"blue\">" + name + "</font></body></html>");
    if (m != null) {
        m.addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
            }
            @Override
            public void mousePressed(MouseEvent e) {
            }
            @Override
            public void mouseReleased(MouseEvent e) {
            }
            @Override
            public void mouseEntered(MouseEvent evt) {
                m.setText("<html><body><font color=\"red\"><u>" + name + "</u></font></body></html>");
                m.doClick(1);
            }
            @Override
            public void mouseExited(MouseEvent e) {
                m.setText("<html><body><font color=\"blue\">" + name + "</font></body></html>");
            }
        });

    So, the above means that when the user moves over and out of a menu, they will see the kind of effects they know from the web. By default, the display text of a menu is blue, when the mouse moves over the menu the menu is red and underlined and when the mouse moves out of the menu the default state is returned. Now, don't you think Swing is a lot cooler than you might already have thought?

    Finally, there are still a couple of imperfections in our code. The final result of what we're trying to achieve should be as follows:

    Note that the names of the menus are now correct (i.e., "GoTo" is now "Navigate") and that you can see the keyboard shortcuts that need to be entered as an alternative way to access the menus. (Lack of keyboard shortcut support is frequently a reason why the desktop is favored over the web, by the way.) Here's the complete & full code of my menu bar that achieves the above result:

    public class MyMenuBar extends JMenuBar {

        public MyMenuBar() {
            final FileObject menuFolder = FileUtil.getConfigFile("Menu");
            setLayout(new MigLayout("align right"));
            JPanel p = new LoginPanel();
            add(p, "span, align right");
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    buildPopup(menuFolder, nulltrue);
                }
            });
            setPreferredSize(new Dimension(50, 50));
        }

        private void buildPopup(FileObject fo, JComponent comp, boolean folder) {
            DataObject dob = null;
            try {
                dob = DataObject.find(fo);
            } catch (DataObjectNotFoundException ex) {
                Exceptions.printStackTrace(ex);
            }
            if (folder) {
                DataFolder df = DataFolder.findFolder(fo);
                DataObject[] childs = df.getChildren();
                for (int i = 0; i < childs.length; i++) {
                    dob = childs[i];
                    if (dob.getPrimaryFile().isFolder()) {
                        final JMenu menu = new JMenu();
                        final String name = dob.getNodeDelegate().getDisplayName();
                        Mnemonics.setLocalizedText(menu, "<html><body><font color=\"blue\">" + name + "</font><body>");
                        menu.addMouseListener(new MouseListener() {
                            @Override
                            public void mouseClicked(MouseEvent e) {}
                            @Override
                            public void mousePressed(MouseEvent e) {}
                            @Override
                            public void mouseReleased(MouseEvent e) {}
                            @Override
                            public void mouseEntered(MouseEvent evt) {
                                Mnemonics.setLocalizedText(menu, "<html><body><font color=\"red\"><u>" + name + "</u></font><body>");
                                menu.doClick(1);
                            }
                            @Override
                            public void mouseExited(MouseEvent e) {
                                Mnemonics.setLocalizedText(menu, "<html><body><font color=\"blue\">" + name + "</font><body>");
                            }
                        });
                        FileObject menuFolder = dob.getPrimaryFile();
                        for (FileObject menuItemFolder : FileUtil.getOrder(Arrays.asList(menuFolder.getChildren()), true)) {
                            if (menuItemFolder.isFolder()) {
                                buildPopup(menuItemFolder, menu, true);
                            } else {
                                buildPopup(menuItemFolder, menu, false);
                            }
                        }
                        add(menu);
                    }
                }
            } else {
                Object instanceObj;
                InstanceCookie ck = (InstanceCookie) dob.getCookie(InstanceCookie.class);
                try {
                    instanceObj = ck.instanceCreate();
                } catch (Exception ex) {
                    instanceObj = null;
                }
                if (instanceObj instanceof JSeparator) {
                    comp.add((JSeparator) instanceObj);
                } else if (instanceObj instanceof BooleanStateAction) {
                    JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem();
                    Actions.connect(menuItem, (BooleanStateAction) instanceObj, true);
                } else if (instanceObj instanceof Action) {
                    JMenuItem menuItem = new JMenuItem();
                    Actions.connect(menuItem, (Action) instanceObj, false);
                    comp.add(menuItem);
                }
            }
        }

        //Paint the banner image into the menu bar:
        private final Paint bannerPaint = makeBannerPaint();
        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            g2.setPaint(bannerPaint);
            g2.fillRect(0, 0, getWidth(), getHeight());
        }
        private Paint makeBannerPaint() {
            //Pointing to an image in org/menu/bar:
            BufferedImage img = (BufferedImage) ImageUtilities.loadImage("org/menu/bar/banner.jpg");
            return new TexturePaint(img, new Rectangle(0, 0, img.getWidth(), img.getHeight()));
        }

    }
  • 相关阅读:
    linux系统备份
    VNC轻松连接远程Linux桌面
    Cacti监控服务器配置教程(基于CentOS+Nginx+MySQL+PHP环境搭建)
    Linux tar命令高级用法——备份数据
    在linux下使用debugfs恢复rm删除的文件
    Linux系统MySQL开启远程连接
    查看LINUX进程内存占用情况
    JavaScript使用数组
    JavaScript计时器
    大话三层架构
  • 原文地址:https://www.cnblogs.com/cuizhf/p/2189944.html
Copyright © 2020-2023  润新知