zoukankan      html  css  js  c++  java
  • 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()));
        }

    }
  • 相关阅读:
    [python学习篇][python工具使用篇][1] 编辑,设置等
    [python学习篇][廖雪峰][1]高级特性--创建生成器 方法2 yield
    [python学习篇][廖雪峰][1]高级特性--创建生成器 方法1 a = (x for x in range(1,3))
    [python学习篇][廖雪峰][1]高级特性--列表生成式
    [python学习篇][廖雪峰][1]高级特性 ---迭代
    自定义Sharepoint的登陆页面
    SharePoint 2010 使用自定义aspx页面替换列表默认的新建(NewForm.aspx),查看(DispForm.aspx)和编辑(EditForm.aspx)页面
    SharePoint2010新特性:InfoPath定义创建列表的界面
    SharePoint 2010 获取列表中所有数据(包括文件夹内)的方法
    SharePoint 2013中修改windows 活动目录(AD)域用户密码的WebPart(免费下载)
  • 原文地址:https://www.cnblogs.com/cuizhf/p/2189944.html
Copyright © 2011-2022 走看看