我目前有一個JComboBox,我用它作爲音頻播放列表 - 我想要實現的是每個項目右側的一個小「刪除」按鈕,我可以使用它將其從底層模型中刪除,其中圓圈是:JComboBox項目中的顯示按鈕
實現此目的的最佳方法是什麼?
我希望按鈕對於JComboBox中的所有項目都是相同的。
我目前有一個JComboBox,我用它作爲音頻播放列表 - 我想要實現的是每個項目右側的一個小「刪除」按鈕,我可以使用它將其從底層模型中刪除,其中圓圈是:JComboBox項目中的顯示按鈕
實現此目的的最佳方法是什麼?
我希望按鈕對於JComboBox中的所有項目都是相同的。
讓我說,這是一個有趣的問題(+1前一段時間)開始。
我不得不快速嘗試親眼看看JComboBox
實現想要的結果有多困難。我得到的結論(正如@trashgod在上面的評論中所說)是這個對象從來沒有被設計成具有其他組件,或者至少它對我來說是這樣的感覺。
下面是一個你想做的事情的樣本。你可以用它作爲開始,但說實話,你應該忘記使用JComboBox
來解決這個問題。
沒有意思,下面的例子提出了正確的解決問題的方法。它只是顯示了我嘗試解決問題的結果。下面的代碼並不保留良好的慣例規則,例如它將表示與功能混合在一起(渲染器刪除元素)。這實際上只是一種黑客而非真正的解決方案。
import java.awt.*;
import java.awt.event.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class ButtonCombo {
private JPanel getContent() throws MalformedURLException {
String[] ids = {"north", "west", "south", "east"};
JComboBox combo = new JComboBox(ids);
Icon removeIcon = new ImageIcon(new URL("http://filesharefreak.org/images/red_x.png"));
combo.setRenderer(new ButtonComboRenderer(removeIcon, combo));
JPanel panel = new JPanel();
panel.add(combo);
return panel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.add(new ButtonCombo().getContent());
JButton button = new JButton("OKOKO");
panel.add(button);
f.setContentPane(panel);
f.setSize(300, 160);
f.setLocation(200, 200);
f.setVisible(true);
} catch (MalformedURLException ex) {
Logger.getLogger(ButtonCombo.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
}
class ButtonComboRenderer implements ListCellRenderer {
Icon icon;
JPanel panel;
JLabel label;
JButton button;
public ButtonComboRenderer(Icon removeIcon, final JComboBox combo) {
icon = removeIcon;
label = new JLabel();
button = new JButton(icon);
button.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
panel = new JPanel(new BorderLayout());
panel.add(label);
panel.add(button, BorderLayout.EAST);
panel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (button.getX() < e.getX()) {
System.out.println("button contains the click remove the item");
combo.removeItem(label.getText());
}
}
});
}
//so we will install the mouse listener once
boolean isFirst = true;
@Override
public Component getListCellRendererComponent(JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
if (isFirst) {
isFirst = false;
list.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
panel.dispatchEvent(e);
e.consume();
}
});
}
String text = (String) value;
label.setText(text);
if(text == null)
button.setIcon(null);
else if(button.getIcon() == null)
button.setIcon(icon);
panel.setBackground(isSelected ? Color.red : Color.white);
panel.setForeground(isSelected ? Color.white : Color.black);
return panel;
}
}
我的最後建議,我會做的方式是: 建立你自己的組件。通過將其與觸發器和演示文稿分離,使其具有可擴展性和可修改性,兩者均使用JComponent
,因爲它們反對使用渲染器。通過這種方式,您將能夠捕獲和處理組件上的事件,而不是像這樣所有事件都被用於渲染的JList
捕獲。
下面是一個應該幫助您開始的示例。這不是最終的解決方案,但它提出了製作此類組件所涉及的許多重要問題。您應該使用的呈現功能,並在單一組件相應包裹了一切:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class MockJComboBox {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
final JPanel popupContent = new JPanel(new GridLayout(0, 1));
popupContent.setBackground(Color.GREEN);
popupContent.add(new JLabel("Content of popupContent panel"));
popupContent.add(new JLabel("Content of popupContent panel"));
popupContent.add(new JLabel("Content of popupContent panel"));
popupContent.add(new JLabel("Content of popupContent panel"));
popupContent.add(new JLabel("Content of popupContent panel"));
popupContent.add(new JComboBox(new Object[]{"Content of popupContent panel"}));
final JButton popupCloseButton = new JButton("X");
popupContent.add(popupCloseButton);
final JScrollPane s = new JScrollPane(popupContent);
s.setPreferredSize(new Dimension(popupContent.getPreferredSize().width + s.getVerticalScrollBar().getPreferredSize().width
+ s.getBorder().getBorderInsets(s).left
+ s.getBorder().getBorderInsets(s).right, 100));
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(200, 200));
final JButton popupOpenButton = new JButton();
panel.add(popupOpenButton);
final JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(panel);
final PopupFactory popupFactory = PopupFactory.getSharedInstance();
popupOpenButton.setAction(new AbstractAction("Open") {
private Popup popup;
private boolean isShown = false;
@Override
public void actionPerformed(ActionEvent e) {
if (isShown) {
popup.hide();
} else {
popup = popupFactory.getPopup(popupOpenButton, s,
popupOpenButton.getLocationOnScreen().x, popupOpenButton.getLocationOnScreen().y + popupOpenButton.getHeight());
popupCloseButton.setAction(new AbstractAction(popupCloseButton.getText()) {
@Override
public void actionPerformed(ActionEvent e) {
isShown = false;
popup.hide();
}
});
popup.show();
}
isShown = !isShown;
}
});
f.pack();
f.setVisible(true);
}
});
}
}
+1,很好的答案,謝謝! – berry120
是要'1)'把JLabel的,並與一個JButton的一個項目,'2)'在JComboBox中的所有項目或不是 – mKorbel
@mKorbel不確定你的意思是你的第一點?但是對於第二點,是的。 – berry120
那裏,我看到一個重要的問題,JComboBox的DROP_DOWN任何Mouse_click到項目(Java1.4和更高版本)後自行消失,你同意並接受 – mKorbel