我需要找到在另一个操作中显示多个操作的方法,就像 Netbeans 使用Run Main Project图标那样。
您可以看到有一个默认操作Run Main Project,如果单击绿色播放图标旁边的小箭头,您可以选择特定操作,例如Run。
我正在检查代码Netbeans,但找不到在我的应用程序中执行此操作的代码。
啊,UI 组件的(之一)圣杯,分割按钮。多年来,我一直试图找到一种能够在多种外观和感觉下表现良好的产品,但惨遭失败。
\n\n许多人使用多个按钮或只是使用一个JComboBox
像许多事情一样,我偶然发现了一个做得很好的东西,但我必须对其进行修改以满足我的需要,不幸的是,我不记得原始版本或作者,抱歉。(如果您认为此代码是基于您的代码,请留下评论并提供原始链接,我将评估并提供适当的信用)
\n\n\n\n基本上,如果您单击按钮,它将运行“默认”操作(香蕉),否则您可以选择子元素之一,它将执行它
\n\npublic 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}\nRun Code Online (Sandbox Code Playgroud)\n\n它将被配置为类似...
\n\nSplitButton 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)));\nRun Code Online (Sandbox Code Playgroud)\n\n而且,作为参考,水果动作看起来像......
\n\npublic 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}\nRun Code Online (Sandbox Code Playgroud)\n\n这是使用基于自定义矢量的图标库,所以显然,我不会包含
| 归档时间: |
|
| 查看次数: |
552 次 |
| 最近记录: |