2012-06-21 58 views
10

「有沒有什麼辦法可以防止JList在列表下面點擊時選擇最後一個元素?」如何防止JList在單元格邊界外進行選擇?

這是一個問題,有人問here和我有同樣的問題。那個人發現了一個通常的解決方案(通過重寫processMouseEvent()),但我想知道是否有更好/更優雅的方法來做到這一點。

[編輯]

好的,更多的細節。 如果您有一個JList,並且有一些空間未被任何單元/元素佔用,並且您單擊該空間,那麼JList中的最後一個元素被選中。

對於一個實例,試試這個JList Swing Tutorial example,單擊空白區域並看到Rollo被選中。

+0

就違反」 T代碼生成器,爲更好地幫助更快張貼[SSCCE(http://sscce.org/),否則,我的回答是寬,你的問題簡單'consume' – mKorbel

+0

@GuillaumePolet日Thnx,完全忽略這方面 – Alex

+0

@mKorbel簡單例如添加 – Alex

回答

16

https://forums.oracle.com/forums/thread.jspa?threadID=2206996

import java.awt.EventQueue; 
import java.awt.Point; 
import java.awt.Toolkit; 
import java.awt.event.InputEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 

import javax.swing.JFrame; 
import javax.swing.JList; 
import javax.swing.JScrollPane; 

public class TestJList { 
    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       JList list = new JList(new Object[] { "One", "Two", "Three" }) { 
        @Override 
        public int locationToIndex(Point location) { 
         int index = super.locationToIndex(location); 
         if (index != -1 && !getCellBounds(index, index).contains(location)) { 
          return -1; 
         } 
         else { 
          return index; 
         } 
        } 
       }; 

       list.addMouseListener(new MouseAdapter() { 

        @Override 
        public void mouseClicked(MouseEvent e) { 
         JList list = (JList) e.getSource(); 
         if (list.locationToIndex(e.getPoint()) == -1 && !e.isShiftDown() 
           && !isMenuShortcutKeyDown(e)) { 
          list.clearSelection(); 
         } 
        } 

        private boolean isMenuShortcutKeyDown(InputEvent event) { 
         return (event.getModifiers() & Toolkit.getDefaultToolkit() 
           .getMenuShortcutKeyMask()) != 0; 
        } 
       }); 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
       frame.getContentPane().add(new JScrollPane(list)); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 
+0

+1外觀極好的代碼,通過對OTN兩個海報,請哪裏的所有內置'putClientProperty(...)'在Swing的API – mKorbel

+1

考慮名單也讀下Kleopatra在答案下的評論。清除選擇可能有點不方便。我的期望是沒有任何反應。如果我以前做過有效的選擇(不一定是最後一個單元格),然後單擊JList之外,我希望選擇保持不變,不要清除 –

2

望着調用堆棧,你真的不能做你想做的,而不與AWT事件搞亂:

Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 384 in DefaultListSelectionModel)) 
    DefaultListSelectionModel.changeSelection(int, int, int, int, boolean) line: 384  
    DefaultListSelectionModel.changeSelection(int, int, int, int) line: 415 
    DefaultListSelectionModel.setSelectionInterval(int, int) line: 459 
    TestJList$1(JList<E>).setSelectionInterval(int, int) line: 2067 
    BasicListUI$Handler.adjustSelection(MouseEvent) line: 2739 
    BasicListUI$Handler.mousePressed(MouseEvent) line: 2695 
    AWTEventMulticaster.mousePressed(MouseEvent) line: 280 
    TestJList$1(Component).processMouseEvent(MouseEvent) line: 6502 
    TestJList$1(JComponent).processMouseEvent(MouseEvent) line: 3321  
    TestJList$1.processMouseEvent(MouseEvent) line: 24 
    TestJList$1(Component).processEvent(AWTEvent) line: 6270  
    TestJList$1(Container).processEvent(AWTEvent) line: 2229  
    TestJList$1(Component).dispatchEventImpl(AWTEvent) line: 4861 
    TestJList$1(Container).dispatchEventImpl(AWTEvent) line: 2287 
    TestJList$1(Component).dispatchEvent(AWTEvent) line: 4687 
    LightweightDispatcher.retargetMouseEvent(Component, int, MouseEvent) line: 4832 
    LightweightDispatcher.processMouseEvent(MouseEvent) line: 4489 
    LightweightDispatcher.dispatchEvent(AWTEvent) line: 4422  
    JFrame(Container).dispatchEventImpl(AWTEvent) line: 2273  
    JFrame(Window).dispatchEventImpl(AWTEvent) line: 2713 
    JFrame(Component).dispatchEvent(AWTEvent) line: 4687  
    EventQueue.dispatchEventImpl(AWTEvent, Object) line: 707  
    EventQueue.access$000(EventQueue, AWTEvent, Object) line: 101 
    EventQueue$3.run() line: 666  
    EventQueue$3.run() line: 664  
    AccessController.doPrivileged(PrivilegedAction<T>, AccessControlContext) line: not available [native method]  
    ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext, AccessControlContext) line: 76  
    ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext) line: 87 
    EventQueue$4.run() line: 680  
    EventQueue$4.run() line: 678  

你可以實現自己的ListUI然後做任何你想做的事情(包括防止這種不需要的行爲),但我不會推薦走這條路。

對於它的價值(這是通過覆蓋processXXXEvent方法來完成),這裏是一個小片段,其實我覺得不難看,並且阻止了選擇對象點擊它們的邊界以外時:

import java.awt.event.MouseEvent; 

import javax.swing.JFrame; 
import javax.swing.JList; 
import javax.swing.JScrollPane; 
import javax.swing.SwingUtilities; 

public class TestJList { 

    private JList list; 

    protected void initUI() { 
     JFrame frame = new JFrame("test"); 
     list = new JList(new Object[] { "Hello", "World", "!" }) { 

      private boolean processEvent(MouseEvent e) { 
       int index = list.locationToIndex(e.getPoint()); 
       return index > -1 && list.getCellBounds(index, index).contains(e.getPoint()); 
      } 

      @Override 
      protected void processMouseEvent(MouseEvent e) { 
       if (processEvent(e)) { 
        super.processMouseEvent(e); 
       } 
      } 

      @Override 
      protected void processMouseMotionEvent(MouseEvent e) { 
       if (processEvent(e)) { 
        super.processMouseMotionEvent(e); 
       } 
      } 
     }; 
     list.setVisibleRowCount(10); 

     frame.add(new JScrollPane(list)); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new TestJList().initUI(); 
      } 
     }); 
    } 
} 
相關問題