[英]Swing - Remove selected border and change arrow color of 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()
方法內的組合框中刪除邊框。 這將從按鈕和標簽中刪除邊框。 然后我們模仿BasicComboBoxUI
的createArrowButton()
方法來創建我們自己的自定義按鈕。 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
,則JComboBox
的LayoutManager
將不會考慮箭頭按鈕的首選大小。 如果該標志為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.