2009-07-20 12 views
14

मेरे पास JTable है और मुझे कॉलम को पुन: व्यवस्थित करने में सक्षम होना चाहिए। हालांकि मैं चाहता हूं कि पहला कॉलम फिर से ऑर्डर नहीं किया जा सके।एक जेएमबल में एक कॉलम को फिर से व्यवस्थित करने से कैसे रखा जाए?

table.getTableHeader().setReorderingAllowed(true); 

कॉलम अब पहले कॉलम है जो मैं नहीं चाहता सहित पुनर्क्रमित किया जा सकता है: मैं सक्षम करने के लिए निम्न पुनर्व्यवस्था का इस्तेमाल किया। क्या पहले कॉलम को लॉक करने का कोई तरीका है?

मैंने कुछ समाधान देखा है जो पहले टेबल के साथ दो टेबल का उपयोग एक अलग तालिका में हैं, लेकिन शायद एक बेहतर/सरल तरीका है।

+0

मुझे आपके प्रश्न के माध्यम से 70% मिल गया और 2 टेबल का उपयोग करने के लिए आपको एक प्रतिक्रिया लिखना शुरू कर दिया ... फिर मैंने आपकी पोस्ट पढ़ना समाप्त कर दिया। – jjnguy

+0

तो आप कह रहे हैं कि पहला कॉलम दूसरों से स्वतंत्र होना चाहिए? –

+0

वह पूरे कॉलम, बाएं और दाएं स्थानांतरित करने के बारे में बात कर रहा है। – jjnguy

उत्तर

3

मुझे लगता है कि आपको TableColumnModelListener में columnMoved() विधि को ओवरराइड करने की आवश्यकता है। TableColumnModelEvent कक्षा में getFromIndex() विधि है जो आपको यह निर्धारित करने में सक्षम होना चाहिए कि यह आपका निश्चित कॉलम है या नहीं, और फिर आप ईवेंट को रद्द करने में सक्षम होना चाहिए।

उम्मीद है कि मदद करता है। एक

+0

के भीतर डेटा को ऑर्डर नहीं करना यह इसके बारे में जाने का सबसे अच्छा तरीका प्रतीत होता है। – jjnguy

+0

मैं इसके साथ झुका रहा हूं, मेरा सवाल है (क्योंकि मैं जावा नेफॉइट हूं) मैं इस कार्यक्रम को कैसे रद्द कर सकता हूं? – Bearddo

+1

आप चुनते हैं कि सुपरक्लास पर विधि कॉल को पास करना है या नहीं। यदि आप नहीं करते हैं, तो यह तालिका पर लागू नहीं होगा। – phatmanace

2

सबसे पहले आपको एक बेहतर और सरल तरीका परिभाषित करने की आवश्यकता है। आपको 2 टेबल दृष्टिकोण के बारे में क्या पसंद नहीं है?

आप टेबलकॉलम मॉडेल लिस्टनर का उपयोग नहीं कर सकते हैं, क्योंकि कॉलम को "बाद में" कॉल किया जा चुका है।

कॉलम खींचने के लिए कोड BasicTableHeaderUI में पाया गया है। तो आप वहां कोड को ओवरराइड करने का प्रयास कर सकते हैं, लेकिन फिर आपको सभी एलएएफ के लिए इसे करने की आवश्यकता होगी।

उपर्युक्त कोड एक माउस दबाए गए ईवेंट पर JTableHeader.getReorderingAllowed() को आमंत्रित करता है यह निर्धारित करने के लिए कि कॉलम रीडरिंग की अनुमति है या नहीं। मुझे लगता है कि आप JTableHeader में उस विधि को ओवरराइड कर सकते हैं और संभवतः माउसइन्फो क्लास का उपयोग वर्तमान माउस स्थान को यह निर्धारित करने के लिए कर सकते हैं कि यह पहले कॉलम पर था या फिर गलत लौटा। लेकिन फिर आपको कस्टम जेटीबल भी बनाना होगा जो कस्टम टेबल हेडर का उपयोग करता है।

बेशक उपरोक्त सुझावों में से किसी एक के साथ आप पहले कॉलम को स्थानांतरित होने से रोकने में सक्षम हो सकते हैं। लेकिन यह न भूलें कि आपको पहले कॉलम से पहले दूसरे कॉलम को डालने से रोकने की भी आवश्यकता है। मुझे विश्वास नहीं है कि सवाल का एक छोटा सा सरल जवाब है।

Fixed Column Table मेरा संस्करण है कि यह दो तालिकाओं के साथ कैसे लागू किया जाएगा। क्या यह बेहतर है? मुझे नहीं पता, लेकिन यह उपयोग करने के लिए कोड की केवल एक पंक्ति के बाद से यह आसान है।

+0

"2tables दृष्टिकोण" शायद वह पसंद नहीं करता क्योंकि यह ब्रेक बनाता है डाटामॉडल से, मैं अनुमान लगा रहा हूं। अंत में डेटा को दो मॉडलों में अलग करने के लिए मजबूर होना होगा, यह जेडबल पर ग्राफिकल पक्ष पर निश्चित रूप से सरल है, लेकिन यह मॉडल पक्ष पर अधिक परेशान है। – Gnoupi

+0

यह आपको दो मॉडल का उपयोग करने के लिए मजबूर नहीं करता है। केवल ओपी जानता है कि उसकी आवश्यकताओं क्या हैं। हम उसके दिमाग को नहीं पढ़ सकते हैं। – camickr

+0

आपको दो मॉडल की आवश्यकता नहीं है, आप एक ही टेबल मॉडल से आसानी से दो टेबल दृष्टिकोण कर सकते हैं। एक वैचारिक दृष्टिकोण और रखरखाव दृष्टिकोण से दोनों, यह सबसे आसान दृष्टिकोण है। – codethulhu

1

मुझे एक ही समस्या थी, और मैं इसके बारे में खोज रहा था। अब तक मुझे ऐसा करने के दो तरीके मिले।

  • "अगर मैं इसे अपने आप को फिर से लिखने की गई थी" विधि: जावा से आधार वर्ग में संशोधन करना।

TableColumn एक नया संपत्ति, की आवश्यकता होगी "resizingAllowed" की तरह, यह "reorderingAllowed" की आवश्यकता होगी। इस से, संशोधनों BasicTableHeaderUI में जगह ले:

वहां पहले से ही है:

private static boolean canResize(TableColumn column, 
           JTableHeader header) { 
    return (column != null) && header.getResizingAllowed() 
          && column.getResizable(); 
} 

यह बहुत की आवश्यकता होगी:

private static boolean canMove(TableColumn column, 
           JTableHeader header) { 
    return (column != null) && header.getReorderingAllowed() 
           && column.getReorderable(); 
} 

(ध्यान दें कि यदि आप पहले कॉलम नहीं करना चाहते केवल स्थानांतरित करने के लिए, आप टेबल कॉलम को बदलने के बिना कर सकते हैं:

private static boolean canMove(TableColumn column, 
           JTableHeader header) { 
    return (column != null) && header.getReorderingAllowed() 
          && header.getColumnModel().getColumnIndex(column.getIdentifier()) != 0; 
} 
mousePressed में

  • , header.getReorderingAllowed() के बजाय canMove() बुला:

    )

    के बाद, दो स्थानों पर MouseInputListener में संशोधित करने के लिए। यह सुनिश्चित करता है कि एक स्तंभ जो स्थानांतरित नहीं किया जाना चाहिए, नहीं होगा।

  • लेकिन यह पर्याप्त नहीं है, हमें किसी अन्य को खींचने के दौरान स्थिर कॉलम को स्थानांतरित करने से रोकने की आवश्यकता है। तुम्हें पता है, mouseDragged भी बदलने की जरूरत है जब यह "newColumnIndex" हो रही है:

    अगर (0 < newColumnIndex & & newColumnIndex < cm.getColumnCount())

आप शर्त जोड़ने की जरूरत यदि यह नई अनुक्रमणिका स्थानांतरित की जा सकती है, उदाहरण के लिए "canMove()" विधि का उपयोग कर। इस तरह, जब आप इस अबाध को कॉलम खींचेंगे, तो भी आप इसे खींचेंगे, लेकिन यह उन्हें स्वैप नहीं करेगा।

ध्यान दें कि इस विधि के लिए आपको अपने JTable के लिए उपयोग किए जाने वाले JTableHeader के लिए यूआई को स्पष्ट रूप से सेट करने की आवश्यकता होगी, जो वास्तव में आदर्श नहीं है। लेकिन यह सबसे अनुकूल है हालांकि, यह उस स्थान पर समस्या से संबंधित है जहां इसे माना जाता है।


  • विधि "क्या हम वास्तव में है के साथ सामान्य व्यवहार को ब्लॉक करने की कोशिश करते हैं": यूआई, JTableHeader पर इस विधि फोकस यूआई द्वारा किए गए आदेशों को ब्लॉक करने को संशोधित नहीं।

पहले, पहले कॉलम खींच ब्लॉक करने के लिए, हम इस ओवरराइड विधि के साथ JTableHeader से एक उपवर्ग की जरूरत है,:

@Override 
public void setDraggedColumn(TableColumn pAColumn) 
{ 
    int lIndex = -1; 
    if (pAColumn != null) 
     lIndex = getColumnModel().getColumnIndex(pAColumn.getIdentifier()); 
    if (lIndex != 0) 
     super.setDraggedColumn(pAColumn); 
} 

यह पहला स्तंभ खींच से रोकेगा। लेकिन पहले वर्णित की तरह, यह समस्या का केवल एक हिस्सा है, हमें इस पहले के साथ स्वैपिंग से दूसरे ड्रैग किए गए कॉलम को रोकने की आवश्यकता है।

अभी तक, मेरे पास इसके लिए कोई सही विधि नहीं है। मैं TableColumnModel उपवर्गीकरण, और moveColumn() विधि अधिभावी द्वारा की कोशिश की:

@Override 
public void moveColumn(int pColumnIndex, int pNewIndex) 
{ 
    //Move only if the first column is not concerned 
    if (pColumnIndex =! 0 && pNewIndex != 0) 
     super.moveColumn(pColumnIndex, pNewIndex); 
} 

लेकिन यह काम नहीं करेगा, के रूप में यूआई mouseDragged विधि में वैसे भी माउस स्थिति अपडेट करेगा, आप अपने घसीटा स्तंभ से एक कूद करना होगा एक और जगह पर।

तो मैं अभी भी खोज रहा हूं, और आश्चर्य है कि किसी के पास इस हिस्से से संबंधित प्रस्ताव हैं या नहीं।

+0

अच्छी नौकरी। कृपया मुझे अपने सुझाव के बारे में अपनी राय दें और अपने विस्तृत स्पष्टीकरण के लिए धन्यवाद। – gouessej

0

मैंने "द 'आइए सामान्य व्यवहार को अवरुद्ध करने का प्रयास किया है जो हमारे पास वास्तव में' विधि 'दृष्टिकोण है। ग्नोपी ने कहा कि उन्होंने समस्या के दूसरे भाग को हल नहीं किया है। यहां केवल विंडोज एक्सपी एल & एफ:

  1. XPStyle क्लास को कॉपी करने का समाधान यहां दिया गया है।
  2. WindowsTableHeaderUI का विस्तार करें। source code पर एक नज़र डालें। प्रयासों के लिए को getTableHeader().setUI(new TreeTableWindowsTableHeaderUI());

धन्यवाद Gnoupi:

  • में उपयोग करें।

  • 7

    यह समाधान है कि मैं जा रहा से 1 स्तंभ को रोकने के लिए प्रयोग किया जाता है लगभग 4 साल बाद फिर से आदेश दिया

    private int columnValue = -1; 
    private int columnNewValue = -1; 
    
    
    tblResults.getColumnModel().addColumnModelListener(new TableColumnModelListener() 
    { 
        public void columnAdded(TableColumnModelEvent e) {} 
    
        public void columnMarginChanged(ChangeEvent e) {} 
    
        public void columnMoved(TableColumnModelEvent e) 
        { 
         if (columnValue == -1) 
          columnValue = e.getFromIndex(); 
    
         columnNewValue = e.getToIndex(); 
        } 
    
        public void columnRemoved(TableColumnModelEvent e) {} 
    
        public void columnSelectionChanged(ListSelectionEvent e) {} 
    }); 
    
    tblResults.getTableHeader().addMouseListener(new MouseAdapter() 
    { 
        @Override 
        public void mouseReleased(MouseEvent e) 
        { 
         if (columnValue != -1 && (columnValue == 0 || columnNewValue == 0)) 
         tblResults.moveColumn(columnNewValue, columnValue); 
    
         columnValue = -1; 
         columnNewValue = -1; 
        } 
    }); 
    

    चीयर्स,

    5

    , वहां अभी भी कहीं भी दृष्टि में कोई इष्टतम समाधान है। पहले कॉलम (और पहले ओवर अन्य स्तंभों) की खींच को रोकने के लिए

    फिर भी एक और करने से इनकी दृष्टिकोण mouseEvents से पहले mouseInputListener uidelegate द्वारा स्थापित उन्हें (similar to a recent QA) संभाल कर सकते हैं रोकना है।

    सहयोगियों

    • एक कस्टम MouseMotionListener जो प्रतिनिधियों मूल रूप से स्थापित करने के लिए सभी घटनाओं को छोड़कर घसीटा अगर यह पहले
    • ऊपर एक और स्तंभ के लिए नेतृत्व करेंगे कस्टम
    • अद्यतन के साथ मूल की जगह प्रतिस्थापन जब भी एलएएफ बदल जाता है (क्योंकि मूल ui द्वारा नियंत्रित किया जाता है)। यह JTableHeader की उपवर्गीकरण की आवश्यकता है और कस्टम MouseInputListener updateUI

    में तारों कार्य करें:

    /** 
    * A delegating MouseInputListener to be installed instead of 
    * the one registered by the ui-delegate. 
    * 
    * It's implemented to prevent dragging the first column or any other 
    * column over the first. 
    */ 
    public static class DragHook implements MouseInputListener { 
    
        private JTableHeader header; 
        private MouseListener mouseDelegate; 
        private MouseMotionListener mouseMotionDelegate; 
        private int maxX; 
    
        public DragHook(JTableHeader header) { 
         this.header = header; 
         installHook(); 
        } 
    
        /** 
        * Implemented to do some tweaks/bookkeeping before/after 
        * passing the event to the original 
        * 
        * - temporarily disallow reordering if hit on first column 
        * - calculate the max mouseX that's allowable in dragging to the left 
        * 
        */ 
        @Override 
        public void mousePressed(MouseEvent e) { 
         int index = header.columnAtPoint(e.getPoint()); 
         boolean reorderingAllowed = header.getReorderingAllowed(); 
         if (index == 0) { 
          // temporarily disable re-ordering 
          header.setReorderingAllowed(false); 
         } 
         mouseDelegate.mousePressed(e); 
         header.setReorderingAllowed(reorderingAllowed); 
         if (header.getDraggedColumn() != null) { 
          Rectangle r = header.getHeaderRect(index); 
          maxX = header.getColumnModel().getColumn(0).getWidth() 
            + e.getX() - r.x -1; 
         } 
        } 
    
        /** 
        * Implemented to pass the event to the original only if the 
        * mouseX doesn't lead to dragging the column over the first. 
        */ 
        @Override 
        public void mouseDragged(MouseEvent e) { 
         TableColumn dragged = header.getDraggedColumn(); 
         int index = getViewIndexForColumn(header.getColumnModel(), dragged); 
         // dragged column is at second position, allow only drags to the right 
         if (index == 1) { 
          if (e.getX() < maxX) return; 
         } 
         mouseMotionDelegate.mouseDragged(e); 
        } 
    
        //-------- delegating-only methods 
    
        @Override 
        public void mouseReleased(MouseEvent e) { 
         mouseDelegate.mouseReleased(e); 
        } 
    
        @Override 
        public void mouseClicked(MouseEvent e) { 
         mouseDelegate.mouseClicked(e); 
        } 
    
        @Override 
        public void mouseEntered(MouseEvent e) { 
         mouseDelegate.mouseEntered(e); 
        } 
    
        @Override 
        public void mouseExited(MouseEvent e) { 
         mouseDelegate.mouseExited(e); 
        } 
    
        @Override 
        public void mouseMoved(MouseEvent e) { 
         mouseMotionDelegate.mouseMoved(e); 
        } 
    
        //------------ un-/install listeners 
    
        protected void installHook() { 
         installMouseHook(); 
         installMouseMotionHook(); 
        } 
    
        protected void installMouseMotionHook() { 
         MouseMotionListener[] listeners = header.getMouseMotionListeners(); 
         for (int i = 0; i < listeners.length; i++) { 
          MouseMotionListener l = listeners[i]; 
          if (l.getClass().getName().contains("TableHeaderUI")) { 
           this.mouseMotionDelegate = l; 
           listeners[i] = this; 
          } 
          header.removeMouseMotionListener(l); 
         } 
         for (MouseMotionListener l : listeners) { 
          header.addMouseMotionListener(l); 
         } 
        } 
    
        protected void installMouseHook() { 
         MouseListener[] listeners = header.getMouseListeners(); 
         for (int i = 0; i < listeners.length; i++) { 
          MouseListener l = listeners[i]; 
          if (l.getClass().getName().contains("TableHeaderUI")) { 
           this.mouseDelegate = l; 
           listeners[i] = this; 
          } 
          header.removeMouseListener(l); 
         } 
         for (MouseListener l : listeners) { 
          header.addMouseListener(l); 
         } 
        } 
    
        public void uninstallHook() { 
         uninstallMouseHook(); 
         uninstallMouseMotionHook(); 
        } 
    
        protected void uninstallMouseMotionHook() { 
         MouseMotionListener[] listeners = header.getMouseMotionListeners(); 
         for (int i = 0; i < listeners.length; i++) { 
          MouseMotionListener l = listeners[i]; 
          if (l == this) { 
           listeners[i] = mouseMotionDelegate; 
          } 
          header.removeMouseMotionListener(l); 
         } 
         for (MouseMotionListener l : listeners) { 
          header.addMouseMotionListener(l); 
         } 
        } 
    
        protected void uninstallMouseHook() { 
         MouseListener[] listeners = header.getMouseListeners(); 
         for (int i = 0; i < listeners.length; i++) { 
          MouseListener l = listeners[i]; 
          if (l == this) { 
           listeners[i] = mouseDelegate; 
          } 
          header.removeMouseListener(l); 
         } 
         for (MouseListener l : listeners) { 
          header.addMouseListener(l); 
         } 
        } 
    
    } 
    

    प्रयोग जो एलएएफ की स्विचिंग बच जाता है, फाई:

    JTable table = new JTable(new AncientSwingTeam()) { 
    
        @Override 
        protected JTableHeader createDefaultTableHeader() { 
         JTableHeader header = new JTableHeader(getColumnModel()) { 
          DragHook hook; 
    
          @Override 
          public void updateUI() { 
           if (hook != null) { 
            hook.uninstallHook(); 
            hook = null; 
           } 
           super.updateUI(); 
           hook = new DragHook(this); 
          } 
    
         }; 
         return header; 
        } 
    
    }; 
    
    +0

    +1 .................................... – mKorbel

    0

    सबसे पहले, मैं प्रयोग किया जाता है बहुत आखिरी ग्नोपी का सुझाव टेबल कॉलम मॉडेल को उपclassing और moverolumn overrassing में शामिल है, लेकिन अभी भी कुछ परेशान कूद रहे थे।

    यह "मेरा" पूरी तरह से काम करने वाला और परीक्षण समाधान है, जिसमें कोई बुरा कूद नहीं है, यह मुख्य रूप से स्टैनिस्लावको और क्लोपेट्रा के सुझावों पर निर्भर करता है।

    table.getTableHeader().setUI(new WindowsTableHeaderUI() { 
         @Override 
         protected MouseInputListener createMouseInputListener() { 
          return new BasicTableHeaderUI.MouseInputHandler() { 
    
           @Override 
           public void mouseDragged(MouseEvent e) { 
            if (header.isEnabled() && header.getReorderingAllowed() && header.getDraggedColumn() != null && header.getDraggedColumn().getModelIndex() == frozenColumnModelIndex) { 
             header.setDraggedDistance(0); 
             header.setDraggedColumn(null); 
             return; 
            } 
            super.mouseDragged(e); 
           } 
    
           @Override 
           public void mouseReleased(MouseEvent e) { 
            if (header.isEnabled() && header.getReorderingAllowed() && header.getDraggedColumn() != null && 
             0 <= illegalTableColumnMoveFromIndex && illegalTableColumnMoveFromIndex < header.getTable().getColumnModel().getColumnCount()) { 
             header.setDraggedDistance(0); 
             header.setDraggedColumn(null); 
             header.getTable().getColumnModel().moveColumn(illegalTableColumnMoveToIndex, illegalTableColumnMoveFromIndex); 
             illegalTableColumnMoveFromIndex = -1; 
             illegalTableColumnMoveToIndex = -1; 
             return; 
            } 
            super.mouseReleased(e); 
           } 
          }; 
         } 
        }); 
        table.getColumnModel().addColumnModelListener(new TableColumnModelListener() { 
         @Override 
         public void columnAdded(TableColumnModelEvent e) { 
         } 
    
         @Override 
         public void columnRemoved(TableColumnModelEvent e) { 
         } 
    
         @Override 
         public void columnMoved(TableColumnModelEvent e) { 
          if (e.getFromIndex() != e.getToIndex() && table.getColumnModel().getColumn(e.getFromIndex()).getModelIndex() == frozenColumnModelIndex) { 
           illegalTableColumnMoveFromIndex = e.getFromIndex(); 
           illegalTableColumnMoveToIndex = e.getToIndex(); 
          } else { 
           illegalTableColumnMoveFromIndex = -1; 
           illegalTableColumnMoveToIndex = -1; 
          } 
         } 
    
         @Override 
         public void columnMarginChanged(ChangeEvent e) { 
         } 
    
         @Override 
         public void columnSelectionChanged(ListSelectionEvent e) { 
         } 
        }); 
    

    ध्यान दें कि नवीनतम वैध कदम पूरी तरह से कॉलम खींचें को पूर्ववत करने के बजाय स्वीकार किया जाता है: मैं अवांछित कदम जब माउस बटन छोड़ने वापस लौटने के लिए एक और अधिक जटिल तंत्र गयी।

    frozenColumnModelIndex तालिका मॉडल में "जमे हुए" कॉलम का सूचकांक है।

    अवैधTableColumnMoveFromIndex कॉलम का सूचकांक है जहां से इसे स्थानांतरित किया गया था जब नवीनतम अवैध कदम का पता चला था।

    अवैधTableColumnMoveToIndex कॉलम का सूचकांक है जहां यह नवीनतम अवैध कदम का पता चला था, जहां इसे स्थानांतरित किया गया था।

    माउस ड्रैग के अंदर कोड जमे हुए कॉलम को खींचने से रोकने के लिए पर्याप्त है, शेष अन्य कॉलम को जमे हुए कॉलम पर खींचने से रोकने की अनुमति देता है।

    यह रूप में काम करता माइक्रोसॉफ्ट विंडोज के अंतर्गत है के रूप में मैं WindowsTableHeaderUI विस्तार बल्कि, टेबल हैडर यूआई के माउस इनपुट श्रोता सेट uninstallerListeners() कॉल करने के लिए प्रतिबिंब एपीआई का उपयोग और अंत में header.addMouseListener (mouseInputListener) और header.addMouseMotionListener फोन (mouseInputListener) प्रत्येक तालिका शीर्षलेख UI के लिए कक्षा के नाम पर कोई धारणा किए बिना मेरे समाधान क्रॉस-प्लेटफ़ॉर्म को ड्राइव करने के लिए।

    मैं स्वीकार करता हूं कि यह क्लोपेट्रा के समाधान से थोड़ा कम मजबूत हो सकता है। मैं आपकी मदद के लिए सभी का धन्यवाद करता हूं, मैं वास्तव में आभारी हूं और मुझे यह देखकर खुशी हो रही है कि सहयोगी काम सिर्फ काम करता है :)

    0

    चाल पूरी होने के बाद मैं कॉलम को वापस रखूंगा। तो कुछ पसंद है।

    @Override 
    public void moveColumn(int from, int to) { 
         super.moveColumn(from, to); 
         if (from == 0 || to == 0) { 
          super.moveColumn(to, from); 
         } 
    } 
    
    संबंधित मुद्दे