另一个操作(例如 Netbeans)内的操作

Adr*_*llo 4 java netbeans

我需要找到在另一个操作中显示多个操作的方法,就像 Netbeans 使用Run Main Project图标那样。

您可以看到有一个默认操作Run Main Project,如果单击绿色播放图标旁边的小箭头,您可以选择特定操作,例如Run

我正在检查代码Netbeans,但找不到在我的应用程序中执行此操作的代码。

Mad*_*mer 5

啊,UI 组件的(之一)圣杯,分割按钮。多年来,我一直试图找到一种能够在多种外观和感觉下表现良好的产品,但惨遭失败。

\n\n

许多人使用多个按钮或只是使用一个JComboBox

\n\n

像许多事情一样,我偶然发现了一个做得很好的东西,但我必须对其进行修改以满足我的需要,不幸的是,我不记得原始版本或作者,抱歉。(如果您认为此代码是基于您的代码,请留下评论并提供原始链接,我将评估并提供适当的信用)

\n\n

分割按钮

\n\n

基本上,如果您单击按钮,它将运行“默认”操作(香蕉),否则您可以选择子元素之一,它将执行它

\n\n
public class SplitButton extends JButton {\n\n    private int separatorSpacing = 4;\n    private int splitWidth = 22;\n    private int arrowSize = 8;\n    private boolean onSplit;\n    private Rectangle splitRectangle;\n    private JFrame popupMenu;\n    private boolean alwaysDropDown;\n    private Color arrowColor = Color.BLACK;\n    private Color disabledArrowColor = Color.GRAY;\n    private Image image;\n    private MouseHandler mouseHandler;\n    private boolean toolBarButton;\n\n    private PopupWindowEventHandler popupWindowEventHandler;\n\n    /**\n     * Creates a button with initial text and an icon.\n     *\n     * @param text the text of the button\n     * @param icon the Icon image to display on the button\n     */\n    public SplitButton() {\n        super();\n        addMouseMotionListener(getMouseHandler());\n        addMouseListener(getMouseHandler());\n        // Default for no "default" action...\n        setAlwaysDropDown(true);\n\n        InputMap im = getInputMap(WHEN_FOCUSED);\n        ActionMap am = getActionMap();\n\n        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "PopupMenu.close");\n        am.put("PopupMenu.close", new ClosePopupAction());\n\n    }\n\n    public SplitButton(Action defaultAction, Action... actions) {\n        this();\n        setAction(defaultAction);\n        for (Action action : actions) {\n            addAction(action);\n        }\n    }\n\n    public SplitButton(String text, Icon icon, Action... actions) {\n        this((Action) null, actions);\n        setText(text);\n        setIcon(icon);\n    }\n\n    public SplitButton(String text, Action... actions) {\n        this((Action) null, actions);\n        setText(text);\n    }\n\n    public JSplitButton(Icon icon, Action... actions) {\n        this((Action) null, actions);\n        setIcon(icon);\n    }\n\n    @Override\n    public void setAction(Action a) {\n        super.setAction(a);\n        if (a != null) {\n            setAlwaysDropDown(false);\n        }\n    }\n\n    /**\n     * Creates a pre-configured button suitable for being used on a JToolBar\n     *\n     * @param defaultAction\n     * @param actions\n     * @return\n     */\n    public static SplitButton createToolBarButton(Action defaultAction, Action... actions) {\n        JSplitButton btn = new JSplitButton(defaultAction, actions);\n        btn.configureForToolBar();\n        return btn;\n    }\n\n    /**\n     * Creates a pre-configured "options only" button suitable for being used on\n     * a JToolBar\n     *\n     * @param text\n     * @param icon\n     * @param actions\n     * @return\n     */\n    public static SplitButton createToolBarButton(String text, Icon icon, Action... actions) {\n        JSplitButton btn = new JSplitButton(icon, actions);\n        btn.setToolTipText(text);\n        btn.configureForToolBar();\n        return btn;\n    }\n\n    /**\n     * Used to determine if the button is begin configured for use on a tool bar\n     *\n     * @return\n     */\n    public boolean isToolBarButton() {\n        return toolBarButton;\n    }\n\n    /**\n     * Configures this button for use on a tool bar...\n     */\n    public void configureForToolBar() {\n        toolBarButton = true;\n        if (getIcon() != null) {\n            setHideActionText(true);\n        }\n        setHorizontalTextPosition(JButton.CENTER);\n        setVerticalTextPosition(JButton.BOTTOM);\n        setFocusable(false);\n    }\n\n    protected MouseHandler getMouseHandler() {\n        if (mouseHandler == null) {\n            mouseHandler = new MouseHandler();\n        }\n        return mouseHandler;\n    }\n\n    protected AbstractButton getButtonFor(Action action) {\n        Container parent = ((JFrame) getPopupWindow()).getContentPane();\n        AbstractButton btn = null;\n        for (Component comp : parent.getComponents()) {\n            if (comp instanceof AbstractButton) {\n                Action childAction = ((AbstractButton) comp).getAction();\n                if (action.equals(childAction)) {\n                    btn = (AbstractButton) comp;\n                    break;\n                }\n            }\n        }\n\n        return btn;\n    }\n\n    /**\n     * Returns the index of the specified action within the popup window or -1\n     * of it does not exist\n     *\n     * @param action\n     * @return\n     */\n    public int indexOfAction(Action action) {\n        Container parent = ((JFrame) getPopupWindow()).getContentPane();\n        AbstractButton btn = getButtonFor(action);\n\n        return btn == null ? -1 : parent.getComponentZOrder(btn);\n    }\n\n    /**\n     * Adds the specified action to the popup menu...\n     *\n     * This simply calls getPopupWindow().add(action)\n     *\n     * @param action Add\n     */\n    public void addAction(Action action) {\n        addActionAt(action, -1);\n    }\n\n    protected int getOptionsCount() {\n        return ((JFrame) getPopupWindow()).getContentPane().getComponentCount();\n    }\n\n    protected void addActionAt(Action action, int index) {\n        if (index < 0 || index >= getOptionsCount()) {\n            getPopupWindow().add(createMenuItem(action));\n        } else {\n            getPopupWindow().add(createMenuItem(action), index);\n        }\n    }\n\n    protected void removeAction(Action action) {\n        AbstractButton btn = getButtonFor(action);\n        if (btn != null) {\n            getPopupWindow().remove(btn);\n        }\n    }\n\n    /**\n     * Creates a new JMenuItem from the supplied Action. This is used to\n     * provided the ability for subclasses to either change the type of menu\n     * item used by the button or add additional functionality (like listeners)\n     * should they be required\n     *\n     * @param action\n     * @return\n     */\n    protected JMenuItem createMenuItem(Action action) {\n        return new JMenuItem(action);\n    }\n\n    @Override\n    public Insets getInsets() {\n        Insets insets = (Insets) super.getInsets().clone();\n        insets.right += splitWidth;\n        return insets;\n    }\n\n    @Override\n    public Insets getInsets(Insets insets) {\n        Insets insets1 = getInsets();\n        insets.left = insets1.left;\n        insets.right = insets1.right;\n        insets.bottom = insets1.bottom;\n        insets.top = insets1.top;\n        return insets1;\n    }\n\n    /**\n     * Returns the window that acts as the buttons popup window\n     *\n     * @return\n     */\n    public Window getPopupWindow() {\n        if (popupMenu == null) {\n            popupMenu = new JFrame();\n            popupMenu.setFocusableWindowState(false);\n            popupMenu.setUndecorated(true);\n            popupMenu.setContentPane(createPopupWindowContentPane());\n            popupMenu.setAlwaysOnTop(true);\n            DefaultKeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener(new PropertyChangeListener() {\n                @Override\n                public void propertyChange(PropertyChangeEvent evt) {\n                    String name = evt.getPropertyName();\n                    if ("focusOwner".equalsIgnoreCase(name)\n                            || "permanentFocusOwner".equalsIgnoreCase(name)\n                            || "focusedWindow".equalsIgnoreCase(name)\n                            || "activeWindow".equalsIgnoreCase(name)) {\n                        Window focusedWindow = DefaultKeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow();\n                        if (!popupMenu.equals(focusedWindow)) {\n                            closePopupWinodw();\n                        }\n                    }\n                }\n            });\n        }\n        return popupMenu;\n    }\n\n    protected Container createPopupWindowContentPane() {\n        return new DefaultMenuPane();\n    }\n\n    protected void closePopupWinodw() {\n        getPopupWindow().setVisible(false);\n        if (popupWindowEventHandler != null) {\n            Toolkit.getDefaultToolkit().removeAWTEventListener(popupWindowEventHandler);\n        }\n    }\n\n    protected void showPopupWindow() {\n        Window popup = getPopupWindow();\n        popup.pack();\n        Point pos = getLocationOnScreen();\n        popup.setLocation(pos.x + (getWidth() - popup.getWidth()), pos.y + getHeight());\n        popup.setVisible(true);\n\n        if (popupWindowEventHandler == null) {\n            popupWindowEventHandler = new PopupWindowEventHandler();\n        }\n        Toolkit.getDefaultToolkit().addAWTEventListener(popupWindowEventHandler, AWTEvent.MOUSE_EVENT_MASK);\n    }\n\n    /**\n     * Returns the separatorSpacing. Separator spacing is the space above and\n     * below the separator( the line drawn when you hover your mouse over the\n     * split part of the button).\n     *\n     * @return separatorSpacingimage = null; //to repaint the image with the new\n     * size\n     */\n    public int getSeparatorSpacing() {\n        return separatorSpacing;\n    }\n\n    /**\n     * Sets the separatorSpacing.Separator spacing is the space above and below\n     * the separator( the line drawn when you hover your mouse over the split\n     * part of the button).\n     *\n     * @param spacing\n     */\n    public void setSeparatorSpacing(int spacing) {\n        if (spacing != separatorSpacing && spacing >= 0) {\n            int old = separatorSpacing;\n            this.separatorSpacing = spacing;\n            image = null;\n            firePropertyChange("separatorSpacing", old, separatorSpacing);\n            revalidate();\n            repaint();\n        }\n    }\n\n    /**\n     * Show the dropdown menu, if attached, even if the button part is clicked.\n     *\n     * @return true if alwaysDropdown, false otherwise.\n     */\n    public boolean isAlwaysDropDown() {\n        return alwaysDropDown;\n    }\n\n    /**\n     * Show the dropdown menu, if attached, even if the button part is clicked.\n     *\n     * If true, this will prevent the button from raising any actionPerformed\n     * events for itself\n     *\n     * @param value true to show the attached dropdown even if the button part\n     * is clicked, false otherwise\n     */\n    public void setAlwaysDropDown(boolean value) {\n        if (alwaysDropDown != value) {\n            this.alwaysDropDown = value;\n            firePropertyChange("alwaysDropDown", !alwaysDropDown, alwaysDropDown);\n        }\n    }\n\n    /**\n     * Gets the color of the arrow.\n     *\n     * @return arrowColor\n     */\n    public Color getArrowColor() {\n        return arrowColor;\n    }\n\n    /**\n     * Set the arrow color.\n     *\n     * @param color\n     */\n    public void setArrowColor(Color color) {\n        if (arrowColor != color) {\n            Color old = arrowColor;\n            this.arrowColor = color;\n            image = null;\n            firePropertyChange("arrowColor", old, arrowColor);\n            repaint();\n        }\n    }\n\n    /**\n     * gets the disabled arrow color\n     *\n     * @return disabledArrowColor color of the arrow if no popup attached.\n     */\n    public Color getDisabledArrowColor() {\n        return disabledArrowColor;\n    }\n\n    /**\n     * sets the disabled arrow color\n     *\n     * @param color color of the arrow if no popup attached.\n     */\n    public void setDisabledArrowColor(Color color) {\n        if (disabledArrowColor != color) {\n            Color old = disabledArrowColor;\n            this.disabledArrowColor = color;\n            image = null; //to repaint the image with the new color\n            firePropertyChange("disabledArrowColor", old, disabledArrowColor);\n        }\n    }\n\n    /**\n     * Splitwidth is the width of the split part of the button.\n     *\n     * @return splitWidth\n     */\n    public int getSplitWidth() {\n        return splitWidth;\n    }\n\n    /**\n     * Splitwidth is the width of the split part of the button.\n     *\n     * @param width\n     */\n    public void setSplitWidth(int width) {\n        if (splitWidth != width) {\n            int old = splitWidth;\n            this.splitWidth = width;\n            firePropertyChange("splitWidth", old, splitWidth);\n            revalidate();\n            repaint();\n        }\n    }\n\n    /**\n     * gets the size of the arrow.\n     *\n     * @return size of the arrow\n     */\n    public int getArrowSize() {\n        return arrowSize;\n    }\n\n    /**\n     * sets the size of the arrow\n     *\n     * @param size\n     */\n    public void setArrowSize(int size) {\n        if (arrowSize != size) {\n            int old = arrowSize;\n            this.arrowSize = size;\n            image = null; //to repaint the image with the new size\n            firePropertyChange("setArrowSize", old, arrowSize);\n            revalidate();\n            repaint();\n        }\n    }\n\n    /**\n     * Gets the image to be drawn in the split part. If no is set, a new image\n     * is created with the triangle.\n     *\n     * @return image\n     */\n    public Image getImage() {\n        if (image == null) {\n            Graphics2D g = null;\n            BufferedImage img = new BufferedImage(arrowSize, arrowSize, BufferedImage.TYPE_INT_RGB);\n            g = (Graphics2D) img.createGraphics();\n            g.setColor(Color.WHITE);\n            g.fillRect(0, 0, img.getWidth(), img.getHeight());\n            g.setColor(popupMenu != null ? arrowColor : disabledArrowColor);\n            //this creates a triangle facing right >\n            g.fillPolygon(new int[]{0, 0, arrowSize / 2}, new int[]{0, arrowSize, arrowSize / 2}, 3);\n            g.dispose();\n            //rotate it to face downwards\n            img = rotate(img, 90);\n            BufferedImage dimg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);\n            g = (Graphics2D) dimg.createGraphics();\n            g.setComposite(AlphaComposite.Src);\n            g.drawImage(img, null, 0, 0);\n            g.dispose();\n            for (int i = 0; i < dimg.getHeight(); i++) {\n                for (int j = 0; j < dimg.getWidth(); j++) {\n                    if (dimg.getRGB(j, i) == Color.WHITE.getRGB()) {\n                        dimg.setRGB(j, i, 0x8F1C1C);\n                    }\n                }\n            }\n\n            image = Toolkit.getDefaultToolkit().createImage(dimg.getSource());\n        }\n        return image;\n    }\n\n    /**\n     *\n     * @param g\n     */\n    @Override\n    protected void paintComponent(Graphics g) {\n        super.paintComponent(g);\n        //Graphics gClone = g.create();//EDIT: Herv\xc3\xa9 Guillaume\n        Color oldColor = g.getColor();\n        splitRectangle = new Rectangle(getWidth() - splitWidth, 0, splitWidth, getHeight());\n        g.translate(splitRectangle.x, splitRectangle.y);\n        int mh = getHeight() / 2;\n        int mw = splitWidth / 2;\n        g.drawImage(getImage(), mw - arrowSize / 2, mh + 2 - arrowSize / 2, null);\n        if (!alwaysDropDown) {\n            if (getModel().isRollover() || isFocusable()) {\n                g.setColor(UIManager.getLookAndFeelDefaults().getColor("Button.background"));\n                g.drawLine(1, separatorSpacing + 2, 1, getHeight() - separatorSpacing - 2);\n                g.setColor(UIManager.getLookAndFeelDefaults().getColor("Button.shadow"));\n                g.drawLine(2, separatorSpacing + 2, 2, getHeight() - separatorSpacing - 2);\n            }\n        }\n        g.setColor(oldColor);\n        g.translate(-splitRectangle.x, -splitRectangle.y);\n    }\n\n    /**\n     * Rotates the given image with the specified angle.\n     *\n     * @param img image to rotate\n     * @param angle angle of rotation\n     * @return rotated image\n     */\n    private BufferedImage rotate(BufferedImage img, int angle) {\n        int w = img.getWidth();\n        int h = img.getHeight();\n        BufferedImage dimg = dimg = new BufferedImage(w, h, img.getType());\n        Graphics2D g = dimg.createGraphics();\n        g.rotate(Math.toRadians(angle), w / 2, h / 2);\n        g.drawImage(img, null, 0, 0);\n        return dimg;\n    }\n\n    @Override\n    protected void fireActionPerformed(ActionEvent event) {\n        // This is a little bit of a nasty trick.  Basically this is where\n        // we try and decide if the buttons "default" action should\n        // be fired or not.  We don\'t want it firing if the button\n        // is in "options only" mode or the user clicked on\n        // on the "drop down arrow"....\n        if (onSplit || isAlwaysDropDown()) {\n            showPopupWindow();\n        } else {\n            super.fireActionPerformed(event);\n\n        }\n    }\n\n    protected class MouseHandler extends MouseAdapter {\n\n        @Override\n        public void mouseExited(MouseEvent e) {\n            onSplit = false;\n            repaint(splitRectangle);\n        }\n\n        @Override\n        public void mouseMoved(MouseEvent e) {\n            if (splitRectangle.contains(e.getPoint())) {\n                onSplit = true;\n            } else {\n                onSplit = false;\n            }\n            repaint(splitRectangle);\n        }\n    }\n\n    protected class PopupWindowEventHandler implements AWTEventListener {\n\n        @Override\n        public void eventDispatched(AWTEvent event) {\n            if (popupMenu.isVisible()) {\n                switch (event.getID()) {\n                    case MouseEvent.MOUSE_RELEASED:\n                        Object source = event.getSource();\n                        if (source instanceof Component) {\n                            Window win = SwingUtilities.getWindowAncestor((Component) source);\n                            if (!popupMenu.equals(win)) {\n                                closePopupWinodw();\n                            }\n                        }\n                        break;\n                }\n            }\n        }\n\n    }\n\n    protected class ClosePopupAction extends AbstractAction {\n\n        @Override\n        public void actionPerformed(ActionEvent e) {\n            closePopupWinodw();\n        }\n\n    }\n\n    protected class DefaultMenuPane extends JPanel {\n\n        public DefaultMenuPane() {\n            setBorder(UIManager.getBorder("PopupMenu.border"));\n            setBackground(UIManager.getColor("PopupMenu.background"));\n            setLayout(new GridLayout(0, 1));\n        }\n\n    }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

它将被配置为类似...

\n\n
SplitButton btn = new SplitButton();\nbtn.setAction(new FruitAction("Banana", new BananaIcon(32, 32)));\nbtn.addAction(new FruitAction("Apple", new AppleIcon(32, 32)));\nbtn.addAction(new FruitAction("Black Berry", new BlackBerriesIcon(32, 32)));\nbtn.addAction(new FruitAction("Grapes", new GrapesIcon(32, 32)));\nbtn.addAction(new FruitAction("Peach", new PeachIcon(32, 32)));\nbtn.addAction(new FruitAction("Strewberry", new StrewberriesIcon(32, 32)));\n
Run Code Online (Sandbox Code Playgroud)\n\n

而且,作为参考,水果动作看起来像......

\n\n
public class FruitAction extends AbstractAction {\n\n    public FruitAction(String text, Icon icon) {\n\n        putValue(NAME, text);\n        putValue(SMALL_ICON, icon);\n        putValue(SHORT_DESCRIPTION, text);\n\n    }\n\n    @Override\n    public void actionPerformed(ActionEvent e) {\n\n        JOptionPane.showMessageDialog(null, "I am " + getValue(NAME), "Fruit", JOptionPane.INFORMATION_MESSAGE);\n\n    }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是使用基于自定义矢量的图标库,所以显然,我不会包含