簡體   English   中英

Swing - 刪除選定的邊框並更改 JComboBox 的箭頭顏色

[英]Swing - Remove selected border and change arrow color of JComboBox

我正在嘗試刪除 JComboBox 的選定邊框(頂部箭頭)並更改箭頭顏色(底部箭頭)

如果可能,如何刪除外邊框? (較深的灰色)

我該怎么做?

所以你可以通過實現一個ComboBoxUI來做到這一點,或者,實際上,例如,子類化BasicComboBoxUI 第二種選擇更好,因為您只需要在某些地方調整一些代碼就可以了(而不是從頭開始實現自己的ComboBoxUI )。 因此,請遵循執行您要求的代碼(希望如此):

import java.awt.Color;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.LookAndFeel;
import javax.swing.plaf.basic.BasicArrowButton;
import javax.swing.plaf.basic.BasicComboBoxUI;

public class MainComboBoxUI {
    public static class MyComboBoxUI extends BasicComboBoxUI {
        @Override
        protected void installDefaults() {
            super.installDefaults();
            LookAndFeel.uninstallBorder(comboBox); //Uninstalls the LAF border for both button and label of combo box.
        }

        @Override
        protected JButton createArrowButton() {
            //Feel free to play with the colors:
            final Color background = Color.CYAN.darker();     //Default is UIManager.getColor("ComboBox.buttonBackground").
            final Color pressedButtonBorderColor = Color.RED; //Default is UIManager.getColor("ComboBox.buttonShadow"). The color of the border of the button, while it is pressed.
            final Color triangle = Color.BLACK;               //Default is UIManager.getColor("ComboBox.buttonDarkShadow"). The color of the triangle.
            final Color highlight = background;               //Default is UIManager.getColor("ComboBox.buttonHighlight"). Another color to show the button as highlighted.
            final JButton button = new BasicArrowButton(BasicArrowButton.SOUTH, background, pressedButtonBorderColor, triangle, highlight);
            button.setName("ComboBox.arrowButton"); //Mandatory, as per BasicComboBoxUI#createArrowButton().
            return button;
        }
    }

    public static void main(final String[] args) {
        final JComboBox<String> combo = new JComboBox<>(new String[]{"A string", "B string 2", "C string 3"});
        combo.setUI(new MyComboBoxUI());

        final JPanel panel = new JPanel(new GridBagLayout());
        panel.add(combo);
        panel.setBackground(Color.RED.darker());

        final JFrame frame = new JFrame("MainComboBoxUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

首先,我們從installDefaults()方法內的組合框中刪除邊框。 這將從按鈕和標簽中刪除邊框。 然后我們模仿BasicComboBoxUIcreateArrowButton()方法來創建我們自己的自定義按鈕。 BasicComboBoxUI.createArrowButton()的默認實現創建了BasicArrowButton帶有一些構建時顏色的BasicArrowButton 例如,這些顏色會更改按鈕的三角形顏色和背景顏色。

那是為了創建一個BasicArrowButton 雖然,如果您想更好地控制按鈕(例如,您需要一個圖標和/或按鈕上的一些文本而不是三角形),那么您可以簡單地在createArrowButton()內創建一個普通的JButton而不是BasicArrowButton 然后你可以在相同的方法中初始化它,或者最好在configureArrowButton()修改它。 就像下面的代碼一樣:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.LookAndFeel;
import javax.swing.plaf.basic.BasicComboBoxUI;

public class MainComboBoxUI2 {
    public static class MyComboBoxUI extends BasicComboBoxUI {
        @Override
        protected void installDefaults() {
            super.installDefaults();
            LookAndFeel.uninstallBorder(comboBox);
        }

        @Override
        protected JButton createArrowButton() {
            final JButton button = new JButton("V");
            button.setName("ComboBox.arrowButton"); //Mandatory, as per BasicComboBoxUI#createArrowButton().
            return button;
        }

        @Override
        public void configureArrowButton() {
            super.configureArrowButton(); //Do not forget this!
            arrowButton.setBackground(Color.CYAN.darker());
            arrowButton.setForeground(Color.BLUE);
        }
    }

    public static void main(final String[] args) {
        final JComboBox<String> combo = new JComboBox<>(new String[]{"A string", "B string 2", "C string 3"});
        combo.setUI(new MyComboBoxUI());
        combo.setPreferredSize(new Dimension(150, 45)); //Needed to be able to show the button's text.

        final JPanel panel = new JPanel(new GridBagLayout());
        panel.add(combo);
        panel.setBackground(Color.RED.darker());

        final JFrame frame = new JFrame("MainComboBoxUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

自定義普通JButton方法(即第二種方法)的唯一問題是,如果 UI 內的受保護標志(名為squareButton )為true ,則JComboBoxLayoutManager將不會考慮箭頭按鈕的首選大小。 如果該標志為true ,則按鈕的寬度設置為等於按鈕的高度,而按鈕的高度又設置為等於組合框的高度。 這就是為什么在第二種方法中,我手動設置組合框的首選大小,使其高度為 45 像素,這足以能夠在按鈕內顯示文本(在這種特定情況下,文本等於“V”)。

例如,您可以通過覆蓋BasicComboBoxUI中的installDefaults()方法並將其設置為false來手動為單個 UI 實例設置此標志的值。 否則,您可以通過調用UIManager.put("ComboBox.squareButton", Boolean.FALSE);為所有組合框設置其值UIManager.put("ComboBox.squareButton", Boolean.FALSE); 在您的代碼中足夠早(即在每個組合框的實例化之前)。 但事實證明,因為我測試了它,當將此值設置為false時,按鈕的大小與顯示區域的大小重疊(顯示區域是組合框的選定值可見的地方)。

進一步挖掘后,我發現這個問題的原因是 UI 的getMinimumSize(...)方法沒有考慮按鈕的 insets ......這意味着文本/圖標周圍的JButton的默認邊框是不計入。 因此,在將squareButton標志設置為false ,您還需要覆蓋此方法。

將它們放在一起,您將獲得以下最終方法/代碼:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicComboBoxUI;

public class MainComboBoxUI3 {
    public static class MyComboBoxUI extends BasicComboBoxUI {
        @Override
        protected void installDefaults() {
            super.installDefaults();
            LookAndFeel.uninstallBorder(comboBox);
        }

        @Override
        protected JButton createArrowButton() {
            final JButton button = new JButton("Drop");
            button.setName("ComboBox.arrowButton"); //Mandatory, as per BasicComboBoxUI#createArrowButton().
            return button;
        }

        @Override
        public void configureArrowButton() {
            super.configureArrowButton(); //Do not forget this!
            arrowButton.setBackground(Color.CYAN.darker());
            arrowButton.setForeground(Color.BLUE);
            //arrowButton.setBorder(javax.swing.BorderFactory.createEmptyBorder());
        }

        //Overrided getMinimumSize to take into account the button's insets for both width and height:
        @Override
        public Dimension getMinimumSize(final JComponent c) {
            final Dimension mindim = super.getMinimumSize(c);
            final Insets buttonInsets = arrowButton.getInsets();
            return new Dimension(mindim.width + buttonInsets.left + buttonInsets.right, mindim.height + buttonInsets.top + buttonInsets.bottom);
        }
    }

    public static void main(final String[] args) {
        UIManager.put("ComboBox.squareButton", Boolean.FALSE); //Set all the combo boxes' button to non-square...
        final JComboBox<String> combo = new JComboBox<>(new String[]{"A string", "B string 2", "C string 3"});
        combo.setUI(new MyComboBoxUI());

        final JPanel panel = new JPanel(new GridBagLayout());
        panel.add(combo);
        panel.setBackground(Color.RED.darker());

        final JFrame frame = new JFrame("MainComboBoxUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

結果如下所示:

組合框最終進場結果

最后,如果希望下拉按鈕的邊框變小(即上圖中帶有文字“Drop”的那個),可以將arrowButton按鈕的邊框設置為(例如) javax.swing.BorderFactory.createEmptyBorder() inside configureArrowButton()方法...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM