<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # Swing 中的拖放 > 原文: [http://zetcode.com/tutorials/javaswingtutorial/draganddrop/](http://zetcode.com/tutorials/javaswingtutorial/draganddrop/) 在計算機圖形用戶界面中,拖放是單擊虛擬對象并將其拖動到其他位置或另一個虛擬對象上的動作(或支持以下動作)。 通常,它可用于調用多種動作,或在兩個抽象對象之間創建各種類型的關聯。 [Tweet](https://twitter.com/share) ## 拖放 拖放操作使用戶可以直觀地完成復雜的事情。 通常,我們可以拖放兩件事:數據或某些圖形對象。 如果將圖像從一個應用拖到另一個應用,則會拖放二進制數據。 如果我們在 Firefox 中拖動選項卡并將其移動到另一個位置,則將拖放圖形組件。 ![Drag and drop](https://img.kancloud.cn/b2/6e/b26ee44af07566b919322459a020a78b_376x279.jpg) 圖:Swing 中的拖放 開始拖動操作的組件必須注冊一個`DragSource`對象。 `DropTarget`是負責在拖放操作中接受拖放的對象。 `Transferable`封裝正在傳輸的數據。 傳輸的數據可以是各種類型。 `DataFlavor`對象提供有關正在傳輸的數據的信息。 幾個 Swing 組件已經內置了對拖放操作的支持。 在這種情況下,我們使用`TransferHandler`來管理拖放功能。 在沒有內置支持的情況下,我們必須從頭開始創建所有內容。 ## Swing 文本拖放示例 我們將演示一個簡單的拖放示例。 我們將使用內置的拖放支持。 我們利用了`TransferHandler`類。 `SimpeDnD.java` ```java package com.zetcode; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JTextField; import javax.swing.TransferHandler; import java.awt.EventQueue; public class SimpleDnD extends JFrame { private JTextField field; private JButton button; public SimpleDnD() { initUI(); } private void initUI() { setTitle("Simple Drag & Drop"); button = new JButton("Button"); field = new JTextField(15); field.setDragEnabled(true); button.setTransferHandler(new TransferHandler("text")); createLayout(field, button); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addComponent(arg[1]) ); gl.setVerticalGroup(gl.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(arg[0]) .addComponent(arg[1]) ); pack(); } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new SimpleDnD(); ex.setVisible(true); }); } } ``` 在我們的示例中,我們有一個文本字段和一個按鈕。 我們可以將文本從字段中拖放到按鈕上。 ```java field.setDragEnabled(true); ``` 文本字段具有內置的拖動支持。 我們必須啟用它。 ```java button.setTransferHandler(new TransferHandler("text")); ``` `TransferHandler`是負責在組件之間傳輸數據的類。 構造器將屬性名稱作為參數。 ## Swing 圖標拖放 一些 Java Swing 組件沒有內置的拖動支持。 `JLabel`組件就是這樣的組件。 我們必須自己編寫拖動功能。 以下示例顯示了如何拖放圖標。 在前面的示例中,我們使用了`text`屬性。 這次我們使用`icon`屬性。 `IconDnD.java` ```java package com.zetcode; import javax.swing.GroupLayout; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.TransferHandler; import java.awt.EventQueue; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class IconDnD extends JFrame { public IconDnD() { initUI(); } private void initUI() { var icon1 = new ImageIcon("src/resources/sad.png"); var icon2 = new ImageIcon("src/resources/plain.png"); var icon3 = new ImageIcon("src/resources/smile.png"); var label1 = new JLabel(icon1, JLabel.CENTER); var label2 = new JLabel(icon2, JLabel.CENTER); var label3 = new JLabel(icon3, JLabel.CENTER); var listener = new DragMouseAdapter(); label1.addMouseListener(listener); label2.addMouseListener(listener); label3.addMouseListener(listener); var button = new JButton(icon2); button.setFocusable(false); label1.setTransferHandler(new TransferHandler("icon")); label2.setTransferHandler(new TransferHandler("icon")); label3.setTransferHandler(new TransferHandler("icon")); button.setTransferHandler(new TransferHandler("icon")); createLayout(label1, label2, label3, button); setTitle("Icon Drag & Drop"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); } private class DragMouseAdapter extends MouseAdapter { public void mousePressed(MouseEvent e) { var c = (JComponent) e.getSource(); var handler = c.getTransferHandler(); handler.exportAsDrag(c, e, TransferHandler.COPY); } } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createParallelGroup(GroupLayout.Alignment.CENTER) .addGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addGap(30) .addComponent(arg[1]) .addGap(30) .addComponent(arg[2]) ) .addComponent(arg[3], GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Integer.MAX_VALUE) ); gl.setVerticalGroup(gl.createSequentialGroup() .addGroup(gl.createParallelGroup() .addComponent(arg[0]) .addComponent(arg[1]) .addComponent(arg[2])) .addGap(30) .addComponent(arg[3]) ); pack(); } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new IconDnD(); ex.setVisible(true); }); } } ``` 在代碼示例中,我們有兩個標簽和一個按鈕。 每個組件都顯示一個圖標。 這兩個標簽啟用拖動手勢,按鈕接受放置手勢。 ```java label1.setTransferHandler(new TransferHandler("icon")); label2.setTransferHandler(new TransferHandler("icon")); label3.setTransferHandler(new TransferHandler("icon")); ``` 默認情況下,標簽的拖動支持未啟用。 我們為這兩個標簽注冊了一個自定義鼠標適配器。 ```java label1.setTransferHandler(new TransferHandler("icon")); label2.setTransferHandler(new TransferHandler("icon")); label3.setTransferHandler(new TransferHandler("icon")); button.setTransferHandler(new TransferHandler("icon")); ``` 每個組件都有一個用于圖標屬性的`TransferHandler`類。 拖動源和拖動目標也需要`TransferHandler`。 ```java var c = (JComponent) e.getSource(); var handler = c.getTransferHandler(); handler.exportAsDrag(c, e, TransferHandler.COPY); ``` 這些代碼行啟動拖動支持。 我們得到了拖動源。 在我們的例子中,它是一個標簽實例。 我們獲取其傳輸處理器對象,并最終通過`exportAsDrag()`方法調用來啟動拖動支持。 ![Icon drag & drop example](https://img.kancloud.cn/35/a8/35a8f931b3b6e75f6c12f248a626bef0_306x258.jpg) 圖:圖標 drag & drop example ## Swing `JList`放置示例 某些組件沒有默認的放置支持。 其中之一是`JList`。 這是有充分的理由的。 我們不知道是將數據插入一行,還是插入兩行或更多行。 因此,我們必須手動實現對列表組件的拖放支持。 下面的示例將逗號或空格分隔的文本插入`JList`組件的行中。 否則,文本將進入一行。 `ListDnD.java` ```java package com.zetcode; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.GroupLayout; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.ListSelectionModel; import javax.swing.TransferHandler; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.datatransfer.DataFlavor; public class ListDnD extends JFrame { private JTextField field; private DefaultListModel model; public ListDnD() { initUI(); } private void initUI() { var scrollPane = new JScrollPane(); scrollPane.setPreferredSize(new Dimension(180, 150)); model = new DefaultListModel(); var myList = new JList(model); myList.setDropMode(DropMode.INSERT); myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); myList.setTransferHandler(new ListHandler()); field = new JTextField(15); field.setDragEnabled(true); scrollPane.getViewport().add(myList); createLayout(field, scrollPane); setTitle("ListDrop"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); } private class ListHandler extends TransferHandler { public boolean canImport(TransferSupport support) { if (!support.isDrop()) { return false; } return support.isDataFlavorSupported(DataFlavor.stringFlavor); } public boolean importData(TransferSupport support) { if (!canImport(support)) { return false; } var transferable = support.getTransferable(); String line; try { line = (String) transferable.getTransferData(DataFlavor.stringFlavor); } catch (Exception e) { return false; } var dl = (JList.DropLocation) support.getDropLocation(); int index = dl.getIndex(); String[] data = line.split("[,\\s]"); for (String item : data) { if (!item.isEmpty()) model.add(index++, item.trim()); } return true; } } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addComponent(arg[1]) ); gl.setVerticalGroup(gl.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(arg[0]) .addComponent(arg[1]) ); pack(); } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new ListDnD(); ex.setVisible(true); }); } } ``` 在示例中,我們有一個文本字段和一個列表組件。 可以將文本字段中的文本拖放到列表中。 如果文本用逗號或空格字符逗號分隔,則單詞將分成幾行。 如果不是,則將文本插入一行。 ```java myList.setDropMode(DropMode.INSERT); ``` 在這里,我們指定放置模式。 `DropMode.INSERT`指定我們將要在列表組件中插入新項目。 如果選擇`DropMode.INSERT`,則將新項目拖放到現有項目上。 ```java myList.setTransferHandler(new ListHandler()); ``` 我們設置了一個自定義的傳輸處理器類。 ```java field.setDragEnabled(true); ``` 我們為文本字段組件啟用了拖動支持。 ```java public boolean canImport(TransferSupport support) { if (!support.isDrop()) { return false; } return support.isDataFlavorSupported(DataFlavor.stringFlavor); } ``` 此方法測試放置操作的適用性。 我們過濾掉剪貼板粘貼操作,僅允許字符串放置操作。 如果該方法返回 false,則取消放置操作。 ```java public boolean importData(TransferSupport support) { ... } ``` `importData()`方法將數據從剪貼板或拖放操作傳輸到放置位置。 ```java var transferable = support.getTransferable(); ``` `Transferable`是數據捆綁在一起的類。 ```java line = (String) transferable.getTransferData(DataFlavor.stringFlavor); ``` 我們檢索我們的數據。 ```java var dl = (JList.DropLocation) support.getDropLocation(); int index = dl.getIndex(); ``` 我們得到該列表的放置位置。 我們檢索將在其中插入數據的索引。 ```java String[] data = line.split("[,\\s]"); for (String item : data) { if (!item.isEmpty()) model.add(index++, item.trim()); } ``` 我們將文本分為幾部分,然后將其插入一行或多行中。 ![JList drop example](https://img.kancloud.cn/5c/ef/5ceff03fe4bc8256d5705e9796e9e03e_381x199.jpg) 圖:`JList`放置示例 前面的示例使用了具有內置拖放支持的組件。 接下來,我們將從頭開始創建拖放功能。 ## Swing 拖動手勢 在以下示例中,我們檢查了一個簡單的拖動手勢。 我們處理創建拖動手勢所需的幾個類。 `DragSource`,`DragGestureEvent`,`DragGestureListener`和`Transferable`。 `DragGesture.java` ```java package com.zetcode; import javax.swing.GroupLayout; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; public class DragGesture extends JFrame implements DragGestureListener, Transferable { public DragGesture() { initUI(); } private void initUI() { var redPanel = new JPanel(); redPanel.setBackground(Color.red); redPanel.setPreferredSize(new Dimension(120, 120)); var ds = new DragSource(); ds.createDefaultDragGestureRecognizer(redPanel, DnDConstants.ACTION_COPY, this); createLayout(redPanel); setTitle("Drag Gesture"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); } public void dragGestureRecognized(DragGestureEvent event) { var cursor = Cursor.getDefaultCursor(); if (event.getDragAction() == DnDConstants.ACTION_COPY) { cursor = DragSource.DefaultCopyDrop; } event.startDrag(cursor, this); } public Object getTransferData(DataFlavor flavor) { return null; } public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[0]; } public boolean isDataFlavorSupported(DataFlavor flavor) { return false; } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createSequentialGroup() .addGap(50) .addComponent(arg[0]) .addGap(50) ); gl.setVerticalGroup(gl.createSequentialGroup() .addGap(50) .addComponent(arg[0]) .addGap(50) ); pack(); } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new DragGesture(); ex.setVisible(true); }); } } ``` 這個簡單的示例演示了拖動手勢。 當我們單擊組件并在按下按鈕時移動鼠標指針時,將創建拖動手勢。 該示例說明了如何為組件創建`DragSource`。 ```java public class DragGesture extends JFrame implements DragGestureListener, Transferable { ``` `DragGesture`實現兩個接口。 `DragGestureListener`監聽拖動手勢。 `Transferable`處理用于傳輸操作的數據。 在該示例中,我們將不會傳輸任何數據; 我們僅演示拖動手勢。 `Transferable`接口的三種必要方法未實現。 ```java var ds = new DragSource(); ds.createDefaultDragGestureRecognizer(redPanel, DnDConstants.ACTION_COPY, this); ``` 在這里,我們創建一個`DragSource`對象并將其注冊到面板。 `DragSource`是負責啟動拖放操作的實體。 `createDefaultDragGestureRecognizer()`將拖動源和`DragGestureListener`與特定組件相關聯。 ```java public void dragGestureRecognized(DragGestureEvent event) { } ``` `dragGestureRecognized()`方法響應拖動手勢。 ```java var cursor = Cursor.getDefaultCursor(); if (event.getDragAction() == DnDConstants.ACTION_COPY) { cursor = DragSource.DefaultCopyDrop; } event.startDrag(cursor, this); ``` `DragGestureEvent`的`startDrag()`方法最終開始拖動操作。 我們指定兩個參數:游標類型和`Transferable`對象。 ```java public Object getTransferData(DataFlavor flavor) { return null; } public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[0]; } public boolean isDataFlavorSupported(DataFlavor flavor) { return false; } ``` 實現`Transferable`接口的對象必須實現這三種方法。 還沒有功能。 ## 一個復雜的拖放示例 在下面的示例中,我們創建一個復雜的拖放示例。 我們創建拖動源,放置目標和可移動對象。 `ComplexDnD.java` ```java package com.zetcode; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JColorChooser; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetAdapter; import java.awt.dnd.DropTargetDropEvent; public class ComplexDnD extends JFrame implements DragGestureListener { private JPanel leftPanel; public ComplexDnD() { initUI(); } private void initUI() { var colourBtn = new JButton("Choose Color"); colourBtn.setFocusable(false); leftPanel = new JPanel(); leftPanel.setBackground(Color.red); leftPanel.setPreferredSize(new Dimension(100, 100)); colourBtn.addActionListener(event -> { var color = JColorChooser.showDialog(this, "Choose Color", Color.white); leftPanel.setBackground(color); }); var rightPanel = new JPanel(); rightPanel.setBackground(Color.white); rightPanel.setPreferredSize(new Dimension(100, 100)); var mtl = new MyDropTargetListener(rightPanel); var ds = new DragSource(); ds.createDefaultDragGestureRecognizer(leftPanel, DnDConstants.ACTION_COPY, this); createLayout(colourBtn, leftPanel, rightPanel); setTitle("Complex drag and drop example"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); } public void dragGestureRecognized(DragGestureEvent event) { var cursor = Cursor.getDefaultCursor(); var panel = (JPanel) event.getComponent(); var color = panel.getBackground(); if (event.getDragAction() == DnDConstants.ACTION_COPY) { cursor = DragSource.DefaultCopyDrop; } event.startDrag(cursor, new TransferableColor(color)); } private class MyDropTargetListener extends DropTargetAdapter { private final DropTarget dropTarget; private final JPanel panel; public MyDropTargetListener(JPanel panel) { this.panel = panel; dropTarget = new DropTarget(panel, DnDConstants.ACTION_COPY, this, true, null); } public void drop(DropTargetDropEvent event) { try { var tr = event.getTransferable(); var col = (Color) tr.getTransferData(TransferableColor.colorFlavor); if (event.isDataFlavorSupported(TransferableColor.colorFlavor)) { event.acceptDrop(DnDConstants.ACTION_COPY); this.panel.setBackground(col); event.dropComplete(true); return; } event.rejectDrop(); } catch (Exception e) { e.printStackTrace(); event.rejectDrop(); } } } private void createLayout(JComponent... arg) { var pane = getContentPane(); var gl = new GroupLayout(pane); pane.setLayout(gl); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addGap(30) .addComponent(arg[1]) .addGap(30) .addComponent(arg[2]) ); gl.setVerticalGroup(gl.createParallelGroup() .addComponent(arg[0]) .addComponent(arg[1]) .addComponent(arg[2]) ); pack(); } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new ComplexDnD(); ex.setVisible(true); }); } } class TransferableColor implements Transferable { protected static final DataFlavor colorFlavor = new DataFlavor(Color.class, "A Color Object"); protected static final DataFlavor[] supportedFlavors = { colorFlavor, DataFlavor.stringFlavor, }; private final Color color; public TransferableColor(Color color) { this.color = color; } public DataFlavor[] getTransferDataFlavors() { return supportedFlavors; } public boolean isDataFlavorSupported(DataFlavor flavor) { return flavor.equals(colorFlavor) || flavor.equals(DataFlavor.stringFlavor); } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { if (flavor.equals(colorFlavor)) { return color; } else if (flavor.equals(DataFlavor.stringFlavor)) { return color.toString(); } else { throw new UnsupportedFlavorException(flavor); } } } ``` 該代碼示例顯示一個按鈕和兩個面板。 該按鈕顯示一個顏色選擇器對話框,并為第一個面板設置顏色。 可以將顏色拖到第二個面板中。 此示例增強了前一個示例。 我們將添加放置目標和自定義可轉移對象。 ```java var mtl = new MyDropTargetListener(rightPanel); ``` 我們在右側面板中注冊放置目標監聽器。 ```java event.startDrag(cursor, new TransferableColor(color)); ``` `startDrag()`方法具有兩個參數。 游標和`Transferable`對象。 ```java public MyDropTargetListener(JPanel panel) { this.panel = panel; dropTarget = new DropTarget(panel, DnDConstants.ACTION_COPY, this, true, null); } ``` 在`MyDropTargetListener`中,我們創建一個放置目標對象。 ```java var tr = event.getTransferable(); var col = (Color) tr.getTransferData(TransferableColor.colorFlavor); if (event.isDataFlavorSupported(TransferableColor.colorFlavor)) { event.acceptDrop(DnDConstants.ACTION_COPY); this.panel.setBackground(color); event.dropComplete(true); return; } ``` 我們得到正在傳輸的數據。 在我們的情況下,它是一個顏色對象。 在這里,我們設置右側面板的顏色。 ```java event.rejectDrop(); ``` 如果不滿足拖放操作的條件,我們將拒絕它。 ```java protected static DataFlavor colorFlavor = new DataFlavor(Color.class, "A Color Object"); ``` 在`TransferableColor`中,我們創建一個新的`DataFlavor`對象。 ```java protected static DataFlavor[] supportedFlavors = { colorFlavor, DataFlavor.stringFlavor, }; ``` 在這里,我們指定了我們支持的數據類型。 在我們的情況下,這是一個自定義的顏色味道和預定義的`DataFlavor.stringFlavor`。 ```java public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { if (flavor.equals(colorFlavor)) { return color; } else if (flavor.equals(DataFlavor.stringFlavor)) { return color.toString(); } else { throw new UnsupportedFlavorException(flavor); } } ``` `getTransferData()`返回一個具有特定數據風味的對象。 Java Swing 教程的這一部分專門用于 Swing 的拖放操作。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看