2009-04-03 86 views
11

OK, vấn đề này nằm ngoài giải đấu của tôi. Tôi đang cố gắng để thực hiện một widget GUI trong swing cho phép các tập tin được thả vào một JTable, và cho phép các hàng của JTable được kéo để sắp xếp lại. Hãy xem danh sách phát của VLC hoặc danh sách phát trong iTunes.JTable - kéo và thả

Tôi đã xóa tệp từ hệ điều hành (Trình khám phá, Trình tìm kiếm, v.v.) hoạt động tốt, nhưng tôi đang có một thời gian không thể sắp xếp lại các hàng của bảng, khi các tệp đang ở. khi tôi thêm một TransferHandler tùy chỉnh vào bảng, hãy kéo từ bảng sẽ bị giết ngay lập tức. Dưới đây là một số mã ví dụ:

import javax.swing.*; 

public class TableTest 
{ 
    public static void main (String [] argv) 
    { 
     // setup table data 
     String [] columns = new String [] {"Foo", "Bar", "Baz", "Quux"}; 
     String [][] data = new String [][] {{"A", "B", "C", "D"}, 
         {"1", "2", "3", "4"}, 
         {"i", "ii", "iii", "iv"}}; 
     // create table 
     JTable table = new JTable(data, columns); 

     // set up drag and drop 
     table.setDragEnabled(true); 
     table.setDropMode(DropMode.INSERT_ROWS); 
     table.setFillsViewportHeight(true); 
     TransferHandler dnd = new TransferHandler() { 
      // here be code to handle drops, and one would 
      // presume drag exporting, too 
     }; 
     table.setTransferHandler(dnd); 
     JScrollPane scroll = new JScrollPane(table); 

     // create and show window 
     JFrame window = new JFrame(); 
     window.getContentPane().add(scroll); 
     window.pack(); 
     window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     window.setVisible(true); 
    } 
} 

Run mã này như-là và bạn sẽ thấy rằng bạn không thể bắt đầu một kéo trên table.If bạn nhận xét ra các cuộc gọi đến setTransferHandler() trên bàn, kéo công trình (tức là, khi tôi bắt đầu kéo một hàng bảng, tôi nhận được con trỏ vòng tròn X'd ra nói rằng tôi không thể thả ở đó). Nhưng ngay khi một TransferHandler được đặt cho bảng, tôi không thể kéo bất kỳ hàng nào. Vấn đề phải được trong TransferHandler, nhưng tôi đã triệt để gỡ rối và gỡ lỗi nó, và đã xác định rằng kéo là không bao giờ bắt đầu một khi có một TransferHandler trên bàn. Tôi đang làm gì sai?

+0

Làm thế nào lạ. Tôi có một vấn đề tương tự. Tôi đang cố gắng nhớ nếu tôi đã thực hiện bất kỳ công việc mà tôi đã có một bảng hỗ trợ cả hai kéo từ và đến. – willcodejavaforfood

Trả lời

3

Có vẻ như bạn đang sử dụng đúng TransferHandler. Hãy thử đọc qua hướng dẫn here.

Xem tài liệu TransferHandler here. Nhà xây dựng trống không giống như nó có nghĩa là để sử dụng bên ngoài một lớp con của TransferHandler.

Và bạn không thực hiện bất kỳ chức năng nào được cung cấp trong TransferHandler chuẩn được cung cấp trên các thành phần Swing. Xem exerpt từ hướng dẫn DnD here (chữ in đậm của tôi):

Lưu ý: Nếu bạn cài đặt TransferHandler tùy chỉnh lên thành phần Swing, hỗ trợ mặc định sẽ được thay thế. Ví dụ, nếu bạn thay thế TransferHandler của JTextField bằng cách chỉ xử lý màu, bạn sẽ vô hiệu hóa khả năng hỗ trợ nhập và xuất văn bản. Nếu bạn phải thay thế một TransferHandler mặc định - ví dụ, một trình xử lý văn bản - bạn sẽ cần phải triển khai lại khả năng nhập và xuất văn bản. Điều này không cần phải rộng rãi như những gì Swing cung cấp - nó có thể đơn giản như hỗ trợ hương vị dữ liệu StringFlavor, tùy thuộc vào nhu cầu của ứng dụng của bạn.

5

tôi đã cùng một vấn đề, nó có liên quan gì đến thực hiện tùy chỉnh của bạn trong những TransferHandler. Khi bạn thay thế TransferHandler, bạn cũng cần phải giữ một DragSource mặc định và yêu cầu nó nhận ra cử chỉ kéo. Bạn cũng có thể cần phải thực hiện Transferable của riêng bạn bởi vì bạn sẽ cần phải chuyển nó sang phương thức DragGestureEvent.startDrag().

table.setTransferHandler(new MyTransferHandler()); 
    table.setDragEnabled(true); 
    DragSource source = DragSource.getDefaultDragSource(); 
    source.createDefaultDragGestureRecognizer(table, DnDConstants.ACTION_COPY, new DragGestureListener() { 

     @Override 
     public void dragGestureRecognized(DragGestureEvent dge) { 
      //grab the selected files from the table model 
      ArrayList<File> files = new ArrayList<File>(); 
      for (int row : table.getSelectedRows()) { 
       files.add((File) dm.getValueAt(row, 1)); 
      } 

      //FileTransferable is a custom Transferable implementation 
      Transferable transferable = new FileTransferable(files); 

      //and this is the magic right here 
      dge.startDrag(null,transferable); 
     } 
    }); 
+1

làm việc cho tôi nếu tôi rời khỏi hai dòng đầu tiên - 'setTransferHandler' và' setDragEnabled'. Trong thực tế, thiết lập kéo kích hoạt sản xuất 'InvalidDnDOperationException: Kéo và thả trong tiến trình' cho tôi. Đồng thời, tôi giả định 'dm' là' table.getModel() '. –

+0

hoạt động hoàn hảo. nhận xét giống như tấm áp phích trước mặt tôi, bỏ qua hai dòng đầu tiên. – user1052080

1

Tôi không muốn nhận được các hạt và bu lông của những gì đang diễn ra vì vậy tôi chỉ ủy quyền các phương pháp mà tôi không quan tâm đến TransferHandler cũ.

tree.setDragEnabled(true); 
tree.setDropMode(DropMode.XXXX); 
tree.setTransferHandler(new MyTransferHandler(tree.getTransferHandler()); 

Bắt đầu với thiết lập tiêu chuẩn nhưng chuyển TransferHandler cũ vào TransferHandler tùy chỉnh của bạn.

private class MyTransferHandler extends TransferHandler { 
    private TransferHandler delegate; 

    public MyTransferHandler(TransferHandler delegate) { 
    this.delegate = delegate; 
    } 

    public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) { 
    return delegate.canImport(comp, transferFlavors); 
    } 

    public boolean canImport(TransferSupport support) { 
    return true; 
    } 

    protected Transferable createTransferable(JComponent c) { 
    try { 
     Method method = delegate.getClass().getDeclaredMethod("createTransferable", JComponent.class); 
     method.setAccessible(true); 
     return (Transferable) method.invoke(delegate, c); 
    } catch (Exception e) { 
     return super.createTransferable(c); 
    } 
    } 

    public void exportAsDrag(JComponent comp, InputEvent event, int action) { 
    delegate.exportAsDrag(comp, event, action); 
    } 

    protected void exportDone(JComponent source, Transferable data, int action) { 
    try { 
     Method method = delegate.getClass().getDeclaredMethod("exportDone", JComponent.class, Transferable.class, 
      int.class); 
     method.setAccessible(true); 
     method.invoke(delegate, source, data, action); 
    } catch (Exception e) { 
     super.exportDone(source, data, action); 
    } 
    } 

    public int getSourceActions(JComponent c) { 
    return delegate.getSourceActions(c); 
    } 

    public Icon getVisualRepresentation(Transferable t) { 
    return delegate.getVisualRepresentation(t); 
    } 

    public boolean importData(JComponent comp, Transferable t) { 
    return delegate.importData(comp, t); 
    } 

    public boolean importData(TransferHandler.TransferSupport support) { 
    return delegate.importData(support); 
    } 
} 

Một Gotcha là createTransferable (JComponent) và exportDone (JComponent, chuyển nhượng, int) phương pháp được bảo vệ, do đó bạn cần phải làm phản chiếu để uỷ thác cho các phương pháp đó. Khi tôi không thực hiện nhiệm vụ phản ánh này, chiến lược không hoạt động. Một khi tôi đã làm việc này kéo và thả đoàn làm việc như mong đợi mà không thay đổi DragSource hoặc phải viết một Transferable mới.

+0

mã ví dụ cẩu thả. kiểu trả về boolean canImport trả về không có gì và hủy bỏ kiểu trả về exportDone. –

+0

Tại sao điều này cẩu thả? Trong câu hỏi, ông đặc biệt nói rằng ông đang cố gắng thêm một TransferHandler vào bảng để hỗ trợ giọt. Toàn bộ vấn đề của anh ta là khi anh ta làm điều đó, sự hỗ trợ kéo cho bảng ngừng hoạt động. Điều gì xảy ra dưới sự bảo hiểm là khi anh ta cung cấp cho TransferHandler của mình, anh ta đã cài đặt một trình mặc định được cài đặt trên bảng. Đây là một ví dụ về cách ủy thác cho TransferHandler ban đầu từ bảng và bí mật đang sử dụng sự phản chiếu để thực hiện createTransferable() và exportDone(). Các phương pháp khác có thể được ghi đè hoặc ủy quyền theo ý muốn. – rancidfishbreath