I want to add/remove buttons in JList. How can I do so?
Alternatively, consider a button-friendly JToolBar, as shown in How to Use Tool Bars.
#rohit I wonder here, what would you need them in a JList? If you want to lay them out vertically you should use some layout manager, e.g. BoxLayout or (better) GridLayout.
There is really no reason why you should have buttons in a JList, where having them in a panel will have the same result.
Seriously try to reconsider your design and go with a more flexible and easier one which uses a layout manager.
All the best, Boro.
Take a look at the Oracle Swing tutorial about how to use lists:
http://download.oracle.com/javase/tutorial/uiswing/components/list.html
JList.addElement() and JList.removeElement can be used to add en remove elements to and from JLists.
I Used this code. try it
class PanelRenderer implements ListCellRenderer {
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JButton renderer = (JButton) value;
renderer.setBackground(isSelected ? Color.red : list.getBackground());
return renderer;
}
}
public void ShowItemList(List<JButton> buttonList, JPanel container) {
DefaultListModel model = new DefaultListModel();
for (JButton b:buttonList) {
model.addElement(b);
}
final JList list = new JList(model);
list.setFixedCellHeight(40);
list.setSelectedIndex(-1);
list.setCellRenderer(new JPanelToJList.PanelRenderer());
JScrollPane scroll1 = new JScrollPane(list);
final JScrollBar scrollBar = scroll1.getVerticalScrollBar();
scrollBar.addAdjustmentListener(new AdjustmentListener() {
#Override
public void adjustmentValueChanged(AdjustmentEvent e) {
System.out.println("JScrollBar's current value = " + scrollBar.getValue());
}
});
container.removeAll();
container.add(scroll1);
}
If you want to add a JButton add it to the list. If want to remove, remove it from the list and run the method again.
Related
alright.,ive already tried every trick off my sleeves..but couldnt figure out how to update the comboBox w/glazedList..if the input is coming from other class..ive tried passing the value to the methods,declaring it first to a string..and such..but none has work..tho it does work if the new item will just gonna come from same class..via click of a button..
so far ive got this code..
values = GlazedLists.eventListOf(auto);//auto is an array..
AutoCompleteSupport.install(comboSearch,values);//comboSearch is the comboBox
//"x" is the value coming from another class.
public void updateCombo(String x){
List<String> item = new ArrayList<>();
item.add(x)
value.addAll(item);
}
i hope this codes are enough to interpret what im trying to ask..
It's not possible to see how you've created your combobox and your eventlist. Therefore I'll just create a simple example application from scratch that shows you the essentials.
Just in case you're not familiar the general concepts the main take home points are:
Try and avoid using standard Java collections (eg ArrayList, Vector) and use the EventList class as soon as possible. All the goodness that comes with sorting/filtering/auto-complete relies on the EventList foundation so set one up asap and then simply manipulate (add/remove/etc) and then the GlazedLists plumbing will take care of the rest.
Once you've got your collection of objects in an EventList and you want to leverage a swing component then look in the ca.odell.glazedlists.swing module which contains everything you need. In this instance you can use an EventListComboBoxModel - pass in your eventlist, and then set your JComboBox model to use the newly created EventListComboBoxModel and from that point GlazedLists will take care of ensuring your list data structure and combobox stay in sync.
So in my example I create an empty combobox and an button. Clicking the button will add an item per click into the combobox. The magic is simply the creation of the EventList and the use of EventListComboBoxModel to link the list to the combobox.
Please note that the code below was only tested against GlazedLists 1.8. But I'm pretty sure it'll work fine with 1.9 or 1.7 too.
public class UpdateComboBox {
private JFrame mainFrame;
private JComboBox cboItems;
private EventList<String> itemsList = new BasicEventList<String>();
public UpdateComboBox() {
createGUI();
}
private void createGUI() {
mainFrame = new JFrame("GlazedLists Update Combobox Example");
mainFrame.setSize(600, 400);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton addButton = new JButton("Add Item");
addButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
itemsList.add("Item " + (itemsList.size()+1));
}
});
// Use a GlazedLists EventComboBoxModel to connect the JComboBox with an EventList.
EventComboBoxModel<String> model = new EventComboBoxModel<String>(itemsList);
cboItems = new JComboBox(model);
JPanel panel = new JPanel(new BorderLayout());
panel.add(cboItems, BorderLayout.NORTH);
panel.add(addButton, BorderLayout.SOUTH);
mainFrame.getContentPane().add(panel);
mainFrame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new UpdateComboBox();
}
});
}
}
I have created a JDialog which contains a JComboBox and a panel underneath which should display a different content based on the value selected in the JComboBox. I have created a JPanel (panel_1) which is added to the content pane of the dialog and an additional JPanel for each of the possible items in the JComboBox (for example panel_item_1 and panel_item_2 if it does have only 2 items). I have attached the following listener class in the JComboBox:
public class SelectedListener implements ActionListener {
private SettingsDialog dialog;
public SelectedListener(SettingsDialog dialog){
this.dialog = dialog;
}
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox)e.getSource();
String selected_settings = (String)cb.getSelectedItem();
if(selected_settings.compareTo("Option 1") == 0){
dialog.panel_1 = dialog.panel_item_1;
dialog.panel_1.updateUI();
}else if(selected_settings.compareTo("Option 2") == 0 ){
dialog.panel_1 = dialog.panel_item_2;
dialog.panel_1.updateUI();
}
}
}
However this doesn't make the panel update with the new content. Any suggestion? Thanks in advance
which should display a different content based on the value selected in the JComboBox.
Read the section from the Swing tutorial on How to Use Card Layout which has a working example that does exactly what you want.
Edit:
dialog.panel_1 = dialog.panel_item_1;
The real problem is that you can't just change the reference to a variable and expect the component to show up on the panel. You still need to add the component to the panel before you do a revalidate() on the panel. So your code is like:
panel.remove(...);
panel.add(...);
panel.revalidate();
panel.repaint();
However, the better solution is to use a CardLayout which does all this work for you.
The background color of the selected item in an uneditable JComboBox is a sort of blue:
I know that you can change it to a different color, such as white, for example with the following code:
jComboBox1.setRenderer(new DefaultListCellRenderer() {
#Override
public void paint(Graphics g) {
setBackground(Color.WHITE);
setForeground(Color.BLACK);
super.paint(g);
}
});
That gives you something like this:
However, if you double-click on that combo-box, some of it turns gray (the part with the triangle and the border):
Is there a way to stop these parts from turning gray when you double-click on it?
Note that, if you call super.paint() first, the whole thing turns dark (including the part behind "Select..."), so that doesn't help.
Not sure what exactly OP is trying to achieve, but here is my JComboBox coloring recipe:
static public void main(String[] args) {
JFrame window = new JFrame("Coloring ComboBox");
window.setSize(170, 150);
window.setLocationRelativeTo(null);
window.setLayout(null);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//---textArea is just for focus switching
JTextArea textArea = new JTextArea();
textArea.setBounds(5, 5, 140, 25);
window.add(textArea);
UIManager.put("ComboBox.selectionBackground", Color.magenta); //---focused background color
//---see comboBox's UIDefaults for more tweaks
JComboBox<String> coloredCombo = new JComboBox<String>(new String[]{"Dog", "Cat", "Bird"});
coloredCombo.setEditable(false);
coloredCombo.setUI(new BasicComboBoxUI() {
#SuppressWarnings({"serial"})
#Override
protected ComboPopup createPopup() {
return new BasicComboPopup(coloredCombo) {
{
//---style popup anyway you like
this.setBorder(BorderFactory.createLineBorder(Color.green, 2));//---popup's border color
}
};
}
#Override
protected JButton createArrowButton() {
//---style arrow button anyway you like
JButton result = new JButton();
result.setBackground(Color.orange);//---button's color
return result;
}
});
coloredCombo.setBorder(BorderFactory.createLineBorder(Color.red, 2));//---border color
coloredCombo.setBackground(Color.yellow); //---not focused background color
coloredCombo.setRenderer(new ListCellRenderer<String>() {
#Override
public Component getListCellRendererComponent(JList<? extends String> list, String value, int index,
boolean isSelected, boolean cellHasFocus) {
JLabel result = new JLabel(value);
result.setOpaque(true);
result.setBackground(isSelected ? Color.cyan : Color.blue); //---item background color
return result;
}
});
coloredCombo.setBounds(5, 35, 140, 25);
window.add(coloredCombo);
window.setVisible(true);
}
Of course, this is just an axample, I recommend you to create a fancy custom class to reuse.
A couple things:
The appearance of the combobox (the display area, the arrow, the drop down) are LAF dependent. Your screen shots suggest WinXP. If you must support any other LAFs, be sure to test that as well, because what works for one LAF may not work for another. I have found this to be particularly true for JComboBoxes.
Like Twister suggests, changing the color by overriding the paint() method likely isn't the best way to do this. Just set the background/foreground color of the combobox itself. If you want to change the color of the dropdown itself (I'm not clear if you want to do this or not), then add a custom renderer that overrides getListCellRendererComponent to set the background/foreground.
public static class CustomRenderer extends DefaultListCellRenderer {
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected,
cellHasFocus);
setBackground(Color.WHITE);
setForeground(Color.BLACK);
return this;
}
}
The appearance of the grey triangle and border is because the combo box now has focus. You can just make it not focusable, and the coloring will go away. This may not be the behavior you want, however.
JComboBox combo = new JComboBox(new Object[]{"Dog", "Cat", "Bird"});
combo.setBackground(Color.WHITE);
combo.setForeground(Color.BLACK);
combo.setFocusable(false);
First, you should not set the foreground and background in the paint method. You should override the getListCellRendererComponent of your renderer in order to customize it. The default renderer change its aspect if you it has the focus or if it is selected. If you do not want those features reimplements the method.
Then if you add a line border to your renderer (setBorder(BorderFactory.createLineBorder(Color.black)) you will see that what is drawn is not part of your renderer but the combobox itself. So you might have to customize the UI
The swing code that calls getListCellRendererComponent, then calls setForeground and setBackground on the returned component (depending on the whether the component is selected and/or focused). I assume this is for some legacy behavior. Unfortunately, it defeats the purpose of my setting it in the renderer.
I've had some good results with this approach:
The code below circumvents changing the foreground and background by overriding the fg/bg setters to do nothing, then I just call the super implementations to set the colors I want.
public static class CustomRenderer extends DefaultListCellRenderer {
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected,
cellHasFocus);
super.setBackground(Color.WHITE);
super.setForeground(Color.BLACK);
return this;
}
public void setForeground(Color c) {}
public void setBackground(Color c) {}
}
Addendum:
The grey border is probably just that, a border. Try the same approach, but also override setBorder.
I have, the same issue with two components JTextField and JComboBox, I assume the solution I'm looking for would solve it for all components.
I have set the size of the components to default thus their size fits the initial content I supplied to it. when I change the content of a component to exceeds the region of the component, I cannot see the whole text, and I would like my component to resize to fit the text.
How can I accomplish that?
Update:
The pack() on the frame only enlarged the text field, how can I do the same and enlarge the combo box?
Update:
private class ComboBoxRenderer extends JLabel implements ListCellRenderer {
private static final long serialVersionUID = 752379460716217273L;
Dimension maxSize=new Dimension();
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
setText(value.toString());
Dimension size = getPreferredSize();
if(maxSize.width<size.width)
maxSize.width=size.width;
if(maxSize.height<size.height)
maxSize.height=size.height;
resolutionDescriptor_ComboBox.setPreferredSize(maxSize);
return this;
}
}
this works, not very efficient, but it is a first step, thing is, it does not take the button image into size considerations, so some of the text is still not shown, but the component resizes, do you have any suggestions?
Adam.
Answer:
This did the trick together with a pack(), no revalidation needed.
private class ComboBoxRenderer extends JLabel implements ListCellRenderer {
private static final long serialVersionUID = 752379460716217273L;
Dimension maxSize=new Dimension();
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
setText(value.toString());
Dimension size = getPreferredSize();
if(maxSize.width<size.width) {
maxSize.width=size.width;
resolutionDescriptor_ComboBox.setPrototypeDisplayValue(value.toString());
}
if(maxSize.height<size.height)
maxSize.height=size.height;
return this;
}
}
make sure you design something more efficient then this...
Update:
and there is no need for the pack()!
Adam.
JComboBox has setPrototypeDisplayValue(Object) method that is used to calculate component's preferred width based on the length of the parameter. Try that.
And instead of pack() use doLayout() together with some revalidate() or repaint()
Do a pack() on the frame
To resize the combo box you can try:
comboBox.setModel( comboBox.getModel() );
I believe this should cause the preferred size of the combo box to be recalculated. Of course you would then need to do the pack() again.
Edit:
Added a simple SSCCE that shows this works:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ComboBoxTest3 extends JFrame implements ActionListener
{
JComboBox comboBox;
JTextField textField;
public ComboBoxTest3()
{
String[] tabs = {"one", "two", "three", "four", "five", "six", "seven" };
DefaultComboBoxModel model = new DefaultComboBoxModel(tabs);
comboBox = new JComboBox( model );
textField = new JTextField("hello");
add(comboBox, BorderLayout.WEST );
add(textField, BorderLayout.EAST );
JButton button = new JButton("Pack");
button.addActionListener( this );
add(button, BorderLayout.SOUTH);
}
public void actionPerformed(ActionEvent e)
{
textField.setText("hello there!");
comboBox.addItem("some longer text");
comboBox.setModel( comboBox.getModel() );
pack();
}
public static void main(String[] args)
{
JFrame frame = new ComboBoxTest3();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
}
As a JCombobox ListCellRenderer, I have a class like this one:
class ZComboBoxRenderer extends JPanel implements ListCellRenderer{
private ZGrid grid;
public ZComboBoxRenderer(ZGrid grid) {
setLayout(new BorderLayout());
this.grid = grid;
add(new JScrollPane(grid), BorderLayout.CENTER);
}
public ZGrid getGrid(){
return grid;
}
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
grid.fetchSQL();
return this;
}
}
ZGrid here, extends JTable.
As a ListCellRendererComponent, I provide a JPanel which has a ZGrid inside, to the JCombobox. The problem is, in its list, this ZGrid is painting properly. But it is also being painted inside the Editor of JCombobox. I have uploaded an image to show this better.
Is there a way to separate Editor from List?
alt text http://img444.imageshack.us/img444/564/soex.jpg
From what I understand, you are implementing a custom Renderer for your JComboBox, and though it correctly renders the contents of your dropdown, it completely messes up the current value of the combo box.
I see two options at your disposal:
you can extend the UI component for your JComboBox and override the paint method to get a custom representation of your grid for your current value view. This would be a pretty quick proof of concept, but it poses issues as you would need to extend every UI (metal, windows, mac, etc) that you expect your app to be running with.
you can roll your own dropdown, and make it look like a JComboBox. This would not be that difficult to do as a POC as well, but the complexity here is to handle the different keyboard inputs that influence the selection and navigation around the combo box.