Battling JComboBox behavior of removing items

we are working on a document browser GUI and encountered some weird behavioral issue with JComboBox/DefaultComboBoxModel. The current workaround is ugly and we are wondering if there is somehow different way to get it to work.
Our application uses an in-house class to keep a list of documents, and this class has APIs for navigation and deletion so forth. On the GUI, we display a JComboBox to show the name of the current document being viewed. This JComboBox is backed by a DefaultComboBoxModel which has a separate list containing only the names of the document. When a user selects a document from the JComboBox, the application jumps to the selected document, and when a user deletes a document, the corresponding document name is removed from the JComboBox.
The problem is that our in-house class behaves differently than DefaultComboBoxModel. When an item is removed from the in-house class, it points to the next item on the list (i.e. the index value renames the same), unless the last item of the list is removed, and then the index simply points to the new last item of the list. This behavior is intuitive and is in conformation to user requirements.
However, the DefaultComboBoxModel does the opposite with some oddity. When an item is removed from the ComboModel, the selectedIndex points to the previous item the list (i.e. the index value decrements by 1), unless it is the first item of the list, in which case it behaves even more oddly... it points to the next item in the list, but for some reason, the selectedIndex becomes 1 (instead of 0) as if the item to be deleted is still in the list!
So we have been having trouble keeping the in-house class and the JComboBox in sync. For one thing, when a user deletes a document, it renders twice for the next document to be viewed (one triggered by JComboBox automatically points to the previous doc, which is incorrect, and the second one is our code that forces JComboBox to select the next doc by setting selected index), and problems occur especially for the boundary cases. We ended up doing a hack - add an ActionListener to the JComboBox only when it receives a mouse-down event and remove the actionListener inside of the actionPerformed() code, so that we can force the JComboBox to display the correct document name without triggering document rendition.
But this is ugly. We are wondering if there is a better way. One possibility is of course to ditch the defaultComboBoxModel, and implement a mutableComboBoxModel in our in-house class. But is there another way (easier way so we dont have to deal with triggering events etc)? Thanks.

And the way to solve it with a custom MutableComboBoxModel (also does not auto select an item that is added):
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class ListComboBoxModel extends AbstractListModel implements MutableComboBoxModel {
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                ListComboBoxModel model = new ListComboBoxModel("one", "two", "three");
                model.setSelectionChangeOnRemove(SelectionChange.SELECT_NEXT);
                final JComboBox comboBox = new JComboBox(model);
                comboBox.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        System.out.println("Selected: "
                                + comboBox.getSelectedIndex()
                                + "=" + comboBox.getSelectedItem());
                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.getContentPane().add(comboBox, BorderLayout.PAGE_START);
                frame.getContentPane().add(
                        new JButton(new AbstractAction("Delete") {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                int index = comboBox.getSelectedIndex();
                                System.out.println("Before: " + index
                                        + "=" + comboBox.getSelectedItem());
                                comboBox.removeItemAt(index);
                                System.out.println("After: "
                                        + comboBox.getSelectedIndex()
                                        + "=" + comboBox.getSelectedItem());
                                setEnabled(comboBox.getItemCount() > 0);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
    public enum SelectionChange { SELECT_PREVIOUS, SELECT_NEXT, CLEAR_SELECTION }
    private final List<Object> items;
    private SelectionChange changeOnRemove = SELECT_PREVIOUS;
    private Object selected;
    public ListComboBoxModel(Object...items) {
        this.items = new ArrayList<Object>();
        if(items != null) {
            this.items.addAll(Arrays.asList(items));
    public void setSelectionChangeOnRemove(SelectionChange changeOnRemove) {
        if(changeOnRemove == null) {
            throw new NullPointerException("SelectionChange should not be null");
        this.changeOnRemove = changeOnRemove;
    @Override
    public int getSize() {
        return items.size();
    @Override
    public Object getElementAt(int index) {
        return items.get(index);
    @Override
    public void setSelectedItem(Object anItem) {
        if((selected != null && !selected.equals(anItem))
                || (selected == null && anItem != null)) {
            selected = anItem;
            fireContentsChanged(this, -1, -1);
    @Override
    public Object getSelectedItem() {
        return selected;
    @Override
    public void addElement(Object obj) {
        insertElementAt(obj, items.size());
    @Override
    public void removeElement(Object element) {
        removeElementAt(items.indexOf(element));
    @Override
    public void insertElementAt(Object element, int index) {
        items.add(index, element);
        fireIntervalAdded(this, index, index);
    @Override
    public void removeElementAt(int index) {
        Object removed = items.get(index);
        if(selected != null && selected.equals(removed)) {
            Object newSelection;
            int size = items.size();
            if(size == 1) {
                newSelection = null;
            else {
                switch(changeOnRemove) {
                case CLEAR_SELECTION:
                    newSelection = null;
                    break;
                case SELECT_NEXT:
                    if(index == size - 1) {
                        newSelection = items.get(index - 1);
                    else {
                        newSelection = items.get(index + 1);
                    break;
                case SELECT_PREVIOUS:
                    if(index == 0) {
                        newSelection = items.get(index + 1);
                    else {
                        newSelection = items.get(index - 1);
                    break;
                default:
                    assert false : "Unknown SelectionChange: " + changeOnRemove;
                    newSelection = null;
                    break;
            setSelectedItem(newSelection);
        items.remove(index);
        fireIntervalRemoved(removed, index, index);
}

Similar Messages

  • Removing items from sheet doesn't change SQL

    Discoverer desktop 10.1.2.1
    When I create a sheet, run it, then remove items from the sheet, and then refresh it, the SQL doesn't change (items/columns that were removed remain in the select statement). They (columns) are removed from the resulting report, but it's throwing off my results (number of rows due to summary items). In other words, I had detail numbers, replace them with summary numbers, now it should be grouping by the detail items, but it's isn't. Basically, the tool isn't removing those items from the SQL.
    Has anyone seen this?
    Thanks in advance.

    I'll chime in on this one - we're seeing this same behavior as well. I can reproduce the problem at will like so:
    1) Create a new sheet.
    2) Pick a table, any table, that has a data point.
    3) To this new sheet, add the DETAIL of the data point, and one other attribute.
    4) View the results - they are good.
    5) Realize you made a misteak, go to Edit Sheet, remove the DETAIL and replace it with the SUM of that same data point.
    6) View the results, and become dismayed that they are not grouping at all.
    7) Click on View->SQL Inspector, and observe the detail item is still in the SQL (along with the SUM) despite having removed it in the sheet editor.
    8) Edit sheet - remove all items leaving absolutely everything blank (no selected items, no columns, no calculations, no sorts, nothing)
    9) Click on View->SQL Inspector, and observe the detail item is still in the SQL. That's wrong!
    If that's not a bug, I'm czar of all the Russias.
    // Discoverer Desktop 10.1.2.1
    // Discoverer Desktop Client 10.1.2.48.18
    // EUL Library 10.1.2.48.18
    // EUL 5.1.1.0.0.0

  • JComboBox behavior

    I'm trying to verify my understanding of the JComboBox behavior. Specifically the events which are generated and when. I have a JComboBox that I reload based on the contents of an "upstream" field. I reload the JComboBox using the focusLost() method of this upstream field. The behavior I see exhibited is that when I add the first item I get an actionPerformed event and an itemStateChanged event (or two) both of which show that the first item in the JComboBox is the selected item. Now, at this time the user has not chosen an item and, actually, I don't even want an item in the combo box portion of the control. After I have loaded the data into the JComboBox I invoke setSelectedIndex(-1) to clear out the JComboBox which again generates an actionPerformed evemt and an itemStateChanged event. Frankly, I'm not interested in reacting to any of the above events during this process. I'm looking for the standard way that people use to avoid reacting to these events. The approach I have taken is to call setEnabled(false) before I manipulate the JComboBox data and call setEnabled(true) when I'm done. Then, in the methods which handle these two events I call isEnabled() and simple return if the JComboBox isn't enabled (obviously, to me at least, if the JComboBox was disabled when this event was generated, it [the event]must have been generated under program control and should be ignored).
    Any comments as to the appropriateness of this approach would be appreciated or if I'm missing an elegant solution.
    Thank you for your attention to this matter!
    Peter

    There's not really an elegant solution to your problem.
    However, your solution is reasonable but does have some minor flaws.
    It assumes that the portion of code responsible for reloading the data can disable the combo box (or combo boxes if the data is shared). Ideally it would simply be the model that gets manipulated; access to the view should be ring-fenced.
    The combo box might be disabled for a real reason (like the user can't alter it directly) but its selected item may be changed in another way (eg, the user selects something in another combo box that alters the disabled combo box).
    You can simply set a flag somewhere else in your application that indicates whether listeners should take action:
    public void itemStateChanged(...)
      if(DataManager.isLoading())
        return;
      /* ... your code here ... */
    }This then doesn't hijack the view code to shoehorn in something that's not view-related.
    It's certainly not elegant but does provide a clear contract for indicating to your listeners that there's something going on that might influence the action they take.
    Another option is to use a ComboBoxModel subclass that is told that it's about to reload and suspends event dispatch until it's told that loading's finished. This is arguably better but does require that you write your own models:
    public class MyComboBoxModel implements ComboBoxModel
      private boolean eventsActive;
      public boolean setEventsActive(boolean eventsActive)
        this.eventsActive = eventsActive;
        // If events are reactivated then just pretend that the entire model's changed (for example)!!
        if(eventsActive)
          fireContentsChanged();
          fireSelectedItemChanged();
      protected void fireSelectedItemChanged()
        if(!eventsActive)
          return;
        // loop over listeners, fire item change event
    }You get the idea...
    Hope this helps.

  • How can we remove items from the VF04 list?

    We have a long list of items in VF04 that, for various reasons (some process related, some due to errors), are not to be billed. We have looked at applying filters to the list but there is nothing really suitable to hide these individual documents e.g. we could filter out some dates where none of the items on that date are to be billed but other dates have a mix of items we want to bill and others we don't.
    I have done a search of this forum but didn't find a previous topic with a quick and simple method to remove items from the list .
    Is there a method, other than billing them or sorting each issue individually, to permanently remove individual documents from the VF04 list?
    Thanks in advance for any help.
    David

    Hi,
    David,
    Download a list of Pending delivers doc form VF04.
    Paste the list in T.Code : VL09 (Delivery reversal) and reverse the delivery.
    Then go to T.Code: VL06G Select the list of deliveries that has been reversed, select/delete all un- wanted deliveries.
    This way you can remove all unwanted pending deliveries forn Billing due list (VF04).
    Thanks & Regards,
    R.Janakiraman

  • How can i update/Remove Items from AR Invoice using SDK?

    Hi All,
    I have 1 problem with update or remove item from sales order. here is the source code of mine.
    If inv.GetByKey(DocumentNumber) = True Then
                        inv.CardCode = cardcode
                        Dim ercode As Integer
                        Dim ind As Integer = 1
                        For Each drow As DataGridViewRow In gv.Rows
                            If gv.Rows.Count = ind Then Exit For
                            ercode = drow.Cells("No").Value
                            inv.Lines.SetCurrentLine(ercode)
                            'inv.Lines.ItemCode = drow.Cells("itemcode").Value
                            'inv.Lines.ItemDescription = drow.Cells("itemname").Value
                            inv.Lines.Quantity = drow.Cells("qty").Value
                            inv.Lines.Price = drow.Cells("price").Value
                            ind = ind + 1
                        Next
                        errorcode = inv.Update
                        If errorcode <> 0 Then
                            PublicVariable.oCompany.GetLastError(errorcode, errorsms)
                        Else
                            errorcode = 0
                        End If
                    Else
                        errorsms = "Not found Invoice Document Number"
    End If
    After update, it error "[INV1.Quantity][line:1],'Field cannot be updated (ODBC -1029)'"
    Does anybody know about this?
    Thanks
    TONY

    Hi $riniva$ Rachumallu,
    This is my mistake that not test manually in application.
    Thanks
    TONY

  • Remove Item from Item list through DTW

    Hi Experts,
    Please do the needful for the below issues.
    1.System is not allow partial delivery but  I already activate allow partial delivery at sales order logistic tab.
    2.System is allow to  print the document at client place automatically at the time of the creation of the sales quotation but not at server.
    3.How to remove Item code from the DB with the help of the DTW.

    hi,
    If there is no transactions associated with item,
    Open item in item master data,From menu bar,Select Data ---> Remove.
    for other cases refer Note 1163367 - How can obsolete items be managed in SAP Business One?
    [https://websmp230.sap-ag.de/sap(bD1lbiZjPTAwMQ==)/bc/bsp/spn/sapnotes/index2.htm?numm=1163367]
    Jeyakanthan

  • How can I remove items from my start up disc and create more space on it?, How can I remove items from my start up disc and create more space on it?

    My Mac Book Air tells me that the start up disc is nearly full land that I do not have the capacity to load Maverick.  How can I remove items that I may not need from this disc?

    Move them to an external hard drive, formatted as HFS Extended (Journaled).

  • How do I remove items from the cloud without losing them permanently?

    My icloud storage is almost full. How do I remove items from the cloud and not lose them?

    What items?
    Purchased music, movies, TV shows, apps, and books do not use up your iCloud storage.
    See the link below for how to reduce the amount of storage you're using:
    http://support.apple.com/kb/HT4847

  • How do you remove items from the assets panel that are duplicated?

    How do you remove items from the assets panel that are duplicated?

    If you add an item to a slideshow, you'll usually see 2 entries for that image in the assets panel - one represents the thumbnail, and the other represents the larger 'hero' image.
    It sounds like you may have added the same image to your slideshow twice. You can select one of the hero images or thumbnail images in your slideshow and use the delete key to remove it. Then the extra 2 entries in the assets panel should disappear.

  • How do you remove items from the start up disc

    How do you remove items from the start up disc?

    Freeing Up Space on The Hard Drive
    You can remove data from your Home folder except for the /Home/Library/ folder.
    Visit The XLab FAQs and read the FAQ on freeing up space on your hard drive.
    Also see Freeing space on your Mac OS X startup disk.

  • How do I remove items from the dock?

    How do I remove items from the dock ?

    Single click and then drag it to the desktop. It will dissapear in a puff of smoke. You also may benefit by bookmarking and using:
    Find Out How Video tutorials

  • Can't remove items from the selectMenu

    I am using selectMenu as:
    <a4j:region selfRendered="true"  id="text">
                <h:selectOneListbox id="symbol" value="#{user.name}">
                  <f:selectItems value="#{user.temp_list}" />
              </h:selectOneListbox>
    <a4j:commandButton action="#{user.getData}" reRender="symbol" value="Get"/>
    </a4j:region>temp_list has following three values when page loads:
    temp_list.add(new SelectItem("Sunday"));
    temp_list.add(new SelectItem("Monday"));
    temp_list.add(new SelectItem("Tuesday"));Now in user.getData i want to remove items one by one based on the selection made by the user. The code is:
    temp_list.remove(0);
    this.setTemp_list(temp_list);But the problem is that if user selects Sunday for example, it remove it from the list but next time when user select Monday it removes monday but BRING BACK SUNDAY AGAIN IN THE LIST. Why is it so?

    BalusC wrote:
    I don´t understand you.Actually i was asking about the code which i mentioned in my last post.
    Okay then what could be the solution? What my thinking is that calling list.remove actually removes the item from the list permenantly, isn't it? If so then why does it showing me again in the selectMenu?

  • Can I remove items from the Services menu?

    I think the subject line says it all: can I remove items from the Services menu? I have a number of items in the Services menu that I never use and I would like to make the menu shorter to make it easier to access the items that I do use.

    There are a couple of things you could try. There's an application called Service Scrubber that is supposed to do this. But the web page says it's for 10.4, though it says it might work on 10.3
    Alternatively, you can edit the Info.plist or Info-macos.plist file in each application bundle to remove its service from the Services menu. This post at Mac OS X Hints has a pretty detailed description of how to do it. I tried this on my iMac running 10.3.9 and it worked just fine.
    Don't know about the Service Scrubber app, but if you edit the plist files, you'll need to log out and log back in before the changes take effect.
    Also, if you decide to edit the files by hand, I'd suggest just renaming NSServices by adding an "x" to the front or something, rather than deleting the item completely. That makes the changes easier to reverse.
    charlie

  • How can i remove items from list that have been deleted when i click on them it keeps showing empty

    how can i remove items from the list that have been deleted when i click on them it keeps showing folder empty

    Actually, Reader SHOULD keep showing documents that no longer exist, I disagree. It's no big deal, and people will quickly realise why they can't open the file. They open more files, the old ones move off.
    The REASON why it should not check is that checking whether a file exists can take a long time when things aren't good. For instance if a file server goes down, or a memory card is unplugged. That in turn would mean delays opening the File menu, and I've seen some software that can sit there for several minutes. That would really give people something of which to complain...

  • How can I remove items from the open a recent file menue.

    How can I remove items from the "Open a Recent File" menue. Many other applications allow the clearing of that file . Is this possible in Adobe Reader 10.1.2 ? If so how?

    See this previous topic: http://forums.adobe.com/message/3759596
    It is for Acrobat, but the registry entries are similar for Reader.

Maybe you are looking for

  • Flash movies made in keynote are not working in firefox

    I have just finished a 65 page iwebsite at www.acendedmasterscards.com it is a card reading with a flash movie - made in keynote for each card. It looks beautiful in Safari but in firefox I get a blank white bit instead of the movie. Help! I would al

  • Creating additional DIT's in Internet directory

    Hi I have Internet directory 10.1.4 as part of an Oracle 10g database environment. I have a DIT defined as part of the environment which matches the AD environment on site. The problem I have found is that I probably need multiple Oracle Context and

  • DTW Some fields don't update

    I am updating lines of a Purchase Order throught DTW. I have multiple fields that I want to update. When I do the import it says that that record updated successfully, yet most of the fields are not updating. Here is my POR1 template: DocNum     Line

  • Is it possible to implement a 4bit image?

    Hi! I have some exotic image files with one, 16bit channel. Currently I am able to display them in flex by translating this to 4 8it channels in a bitmapData and using a shader. But, the problem with this is it takes twice the memory it should (16bit

  • Posting opening balances to control accounts

    Hi everyone, I am entering the opening balances in SAP B1 2007 PL: 42 and I am unable to post the A/R and A/P balances because they are control accounts and there are transactions already posted to these accounts. I can't do a Journal Entry either.