JTable:检测单元格数据变化

发布于 2024-11-27 05:08:43 字数 2774 浏览 1 评论 0原文

在 Netbeans 中,我使用 GUI 构建器将 JTable 插入到我的应用程序中。

到目前为止,我只有一个类 (CustomerDB),它是:

package CustomerDB;

import [...];

public class CustomerDB extends javax.swing.JFrame {

    CellEditorListener ChangeNotification = new CellEditorListener() {
        public void editingCanceled(ChangeEvent e) {
            System.out.println("The user canceled editing.");
        }

        public void editingStopped(ChangeEvent e) {
            System.out.println("The user stopped editing successfully.");
        }
    };

    public CustomerDB() {
        customerTable = new javax.swing.JTable();
        customerTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "ID", "Name", "Address", "Phone"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }
        });
        customerTable.getDefaultEditor(String.class).addCellEditorListener(ChangeNotification);
    } 

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new CustomerDB().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify
    [...]
    private javax.swing.JTable customerTable;
    [...]
    // End of variables declaration

}

每当用户更改表中的数据时,我想要获取该单元格的旧值(可选)和新值。

为了获取此数据,我尝试实现一个事件侦听器:

    CellEditorListener ChangeNotification = new CellEditorListener() {
        public void editingCanceled(ChangeEvent e) {
            System.out.println("The user canceled editing.");
        }

        public void editingStopped(ChangeEvent e) {
            System.out.println("The user stopped editing successfully.");
        }
    };

然后我将此 CellEditorListener 分配给表(其单元格编辑器) ):

    customerTable.getDefaultEditor(String.class).addCellEditorListener(ChangeNotification);

到目前为止,这有效。但它还无法让我检测到该单元格的旧值和新值。我还需要做什么?

提前非常感谢您!

In Netbeans, I used the GUI Builder to insert a JTable into my application.

I have just one class (CustomerDB) so far which is:

package CustomerDB;

import [...];

public class CustomerDB extends javax.swing.JFrame {

    CellEditorListener ChangeNotification = new CellEditorListener() {
        public void editingCanceled(ChangeEvent e) {
            System.out.println("The user canceled editing.");
        }

        public void editingStopped(ChangeEvent e) {
            System.out.println("The user stopped editing successfully.");
        }
    };

    public CustomerDB() {
        customerTable = new javax.swing.JTable();
        customerTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "ID", "Name", "Address", "Phone"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }
        });
        customerTable.getDefaultEditor(String.class).addCellEditorListener(ChangeNotification);
    } 

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new CustomerDB().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify
    [...]
    private javax.swing.JTable customerTable;
    [...]
    // End of variables declaration

}

Whenever a user changes data in the table, I want to get the old value (optional) and the new value of that cell.

In order to get this data, I tried to implement an event listener:

    CellEditorListener ChangeNotification = new CellEditorListener() {
        public void editingCanceled(ChangeEvent e) {
            System.out.println("The user canceled editing.");
        }

        public void editingStopped(ChangeEvent e) {
            System.out.println("The user stopped editing successfully.");
        }
    };

Then I assign this CellEditorListener to the table (its cell editor):

    customerTable.getDefaultEditor(String.class).addCellEditorListener(ChangeNotification);

This works so far. But it doesn't yet enable me to detect the old and the new value of this cell. What else do I have to do?

Thank you very much in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

壹場煙雨 2024-12-04 05:08:43

但它还无法让我检测到该单元格的旧值和新值。我还需要做什么?

使用 TableModelListener 来监听更改更容易,但仍然存在无法访问旧值的问题。

查看表格单元侦听器,获取可让您访问“旧版”的解决方案价值”和“新价值”。

But it doesn't yet enable me to detect the old and the new value of this cell. What else do I have to do?

It is easier to use a TableModelListener to listen for changes but it still has the problem of not being able to access the old value.

Check out the Table Cell Listener for a solution that gives you access to the "old value" as well as the "new value".

挽袖吟 2024-12-04 05:08:43

或带有 ListSelectionListener 的 TableModelLister,如果 TableCell 发生更改,则首先返回,第二个从选定的调用中返回,然后只需比较 Row 和 Row 即可。来自 TableModelLister 和 ListSelectionListener 的列索引

import java.awt.*;
import java.util.Random;
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;

public class Forum implements ListSelectionListener {

    private JFrame frame = new JFrame("Frame");
    private JPanel fatherCenter = new JPanel();
    private JScrollPane tableScroll = new JScrollPane();
    private myTableModel tableModel;
    private JTable dialogTable;
    private ListSelectionModel lsDialog;

    private void addComponentsToPane(Container pane) {
        tableModel = new myTableModel();
        dialogTable = new JTable(tableModel) {

            private static final long serialVersionUID = 1L;

            @Override
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                Component comp = super.prepareRenderer(renderer, row, column);
                JComponent jc = (JComponent) comp;//for Custom JComponent
                if (!isRowSelected(row)) {
                    int modelRow = convertRowIndexToModel(row);
                    boolean type = (Boolean) getModel().getValueAt(modelRow, 2);
                    boolean type1 = (Boolean) getModel().getValueAt(modelRow, 3);
                    boolean type2 = (Boolean) getModel().isCellEditable(row, column);
                    comp.setForeground(Color.black);
                    if ((type) && (!type1)) {
                        comp.setBackground(Color.yellow);
                    } else if ((!type) && (type1)) {
                        comp.setBackground(Color.orange);
                    } else if ((!type) || (!type1)) {
                        comp.setBackground(Color.red);
                        //} else if ((!type2)) {
                        //comp.setForeground(Color.red);
                        //comp.setBackground(Color.magenta);
                    } else {
                        comp.setBackground(row % 2 == 0 ? getBackground() : getBackground().darker());
                    }
                    dialogTable.convertRowIndexToView(0);
                } else {
                    comp.setForeground(Color.blue);
                    comp.setBackground(Color.lightGray);
                }
                if (!isCellEditable(row, column)) {
                    comp.setForeground(Color.red);
                    comp.setBackground(Color.magenta);
                }
                return comp;
            }
        };
        tableScroll = new JScrollPane(dialogTable, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        tableScroll.setBorder(null);
        dialogTable.getTableHeader().setReorderingAllowed(false);
        dialogTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        lsDialog = dialogTable.getSelectionModel();
        dialogTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
        dialogTable.setRowHeight(20);
        dialogTable.setRowMargin(2);
        ListSelectionModel rowSelMod = dialogTable.getSelectionModel();
        //ListSelectionModel colSelMod = dialogTable.getColumnModel().getSelectionModel();
        rowSelMod.addListSelectionListener(this);
        //colSelMod.addListSelectionListener(this);
        fatherCenter = new JPanel();
        fatherCenter.setLayout(new BorderLayout(10, 10));
        fatherCenter.add(tableScroll, BorderLayout.CENTER);
        pane.add(fatherCenter);
    }

    private void addData() {
        Runnable doRun1 = new Runnable() {

            @Override
            public void run() {
                tableModel.resetTable();
                Vector<String> tbl = new Vector<String>();
                Vector<Object> tbl1 = new Vector<Object>();
                Random rnd = new Random();
                tbl.add("Integer");
                tbl.add("Double");
                tbl.add("Boolean");
                tbl.add("Boolean");
                tbl.add("String");
                tableModel.setColumnNames(tbl);
                for (int row = 0; row < 30; row++) {
                    tbl1 = null;
                    tbl1 = new Vector<Object>();
                    tbl1.addElement(row + 1);
                    tbl1.addElement(rnd.nextInt(25) + 3.14);
                    tbl1.addElement((row % 3 == 0) ? false : true);
                    tbl1.addElement((row % 5 == 0) ? false : true);
                    if (row % 7 == 0) {
                        tbl1.add(("Canc"));
                    } else if (row % 6 == 0) {
                        tbl1.add(("Del"));
                    } else {
                        tbl1.add(("New"));
                    }
                    tableModel.addRow(tbl1);
                }
                addTableListener();
            }
        };
        SwingUtilities.invokeLater(doRun1);
    }

    private void addTableListener() {
        tableModel.addTableModelListener(new TableModelListener() {

            @Override
            public void tableChanged(TableModelEvent tme) {
                if (tme.getType() == TableModelEvent.UPDATE) {
                    System.out.println("");
                    System.out.println("Cell " + tme.getFirstRow() + ", "
                            + tme.getColumn() + " changed. The new value: "
                            + tableModel.getValueAt(tme.getFirstRow(),
                            tme.getColumn()));
                }
            }
        });
    }

    public void valueChanged(ListSelectionEvent le) {
        int row = dialogTable.getSelectedRow();
        int col = dialogTable.getSelectedColumn();
        String str = "Selected Row(s): ";
        int[] rows = dialogTable.getSelectedRows();
        for (int i = 0; i < rows.length; i++) {
            str += rows[i] + " ";
        }
        str += "Selected Column(s): ";
        int[] cols = dialogTable.getSelectedColumns();
        for (int i = 0; i < cols.length; i++) {
            str += cols[i] + " ";
        }
        str += "Selected Cell: " + dialogTable.getSelectedRow() + ", " + dialogTable.getSelectedColumn();
        System.out.println(str);
        Object value = dialogTable.getValueAt(row, col);
        System.out.println(String.valueOf(value));
    }

    private void createAndShowGUI() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout(10, 10));
        addComponentsToPane(frame.getContentPane());
        addData();
        frame.setLocation(150, 150);
        frame.setPreferredSize(new Dimension(400, 647));
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        Forum osFrame = new Forum();
    }

    public Forum() {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private class myTableModel extends AbstractTableModel {

        private static final long serialVersionUID = 1L;
        private Vector<Vector<Object>> data;
        private Vector<String> colNames;
        private boolean[] _columnsVisible = {true, true, true, true, true};

        myTableModel() {
            this.colNames = new Vector<String>();
            this.data = new Vector<Vector<Object>>();
        }

        myTableModel(Vector<String> colnames) {
            this.colNames = colnames;
            this.data = new Vector<Vector<Object>>();
        }

        public void resetTable() {
            this.colNames.removeAllElements();
            this.data.removeAllElements();
        }

        public void setColumnNames(Vector<String> colNames) {
            this.colNames = colNames;
            this.fireTableStructureChanged();
        }

        public void addRow(Vector<Object> data) {
            this.data.add(data);
            this.fireTableDataChanged();
            this.fireTableStructureChanged();
        }

        public void removeRowAt(int row) {
            this.data.removeElementAt(row);
            this.fireTableDataChanged();
        }

        @Override
        public int getColumnCount() {
            return this.colNames.size();
        }

        @Override
        public Class<?> getColumnClass(int colNum) {
            switch (colNum) {
                case 0:
                    return Integer.class;
                case 1:
                    return Double.class;
                case 2:
                    return Boolean.class;
                case 3:
                    return Boolean.class;
                default:
                    return String.class;
            }
        }

        @Override
        public boolean isCellEditable(int row, int colNum) {
            switch (colNum) {
                case 2:
                    return false;
                default:
                    return true;
            }
        }

        @Override
        public String getColumnName(int colNum) {
            return this.colNames.get(colNum);
        }

        @Override
        public int getRowCount() {
            return this.data.size();
        }

        @Override
        public Object getValueAt(int row, int col) {
            Vector<Object> value = this.data.get(row);
            return value.get(col);
        }

        @Override
        public void setValueAt(Object newVal, int row, int col) {
            Vector<Object> aRow = data.elementAt(row);
            aRow.remove(col);
            aRow.insertElementAt(newVal, col);
            fireTableCellUpdated(row, col);
        }

        public void setColumnVisible(int index, boolean visible) {
            this._columnsVisible[index] = visible;
            this.fireTableStructureChanged();
        }
    }
}

or TableModelLister with ListSelectionListener, fist returns if TableCell changed, second from selected call, then just compare Row & Column Index from TableModelLister with ListSelectionListener

import java.awt.*;
import java.util.Random;
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;

public class Forum implements ListSelectionListener {

    private JFrame frame = new JFrame("Frame");
    private JPanel fatherCenter = new JPanel();
    private JScrollPane tableScroll = new JScrollPane();
    private myTableModel tableModel;
    private JTable dialogTable;
    private ListSelectionModel lsDialog;

    private void addComponentsToPane(Container pane) {
        tableModel = new myTableModel();
        dialogTable = new JTable(tableModel) {

            private static final long serialVersionUID = 1L;

            @Override
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                Component comp = super.prepareRenderer(renderer, row, column);
                JComponent jc = (JComponent) comp;//for Custom JComponent
                if (!isRowSelected(row)) {
                    int modelRow = convertRowIndexToModel(row);
                    boolean type = (Boolean) getModel().getValueAt(modelRow, 2);
                    boolean type1 = (Boolean) getModel().getValueAt(modelRow, 3);
                    boolean type2 = (Boolean) getModel().isCellEditable(row, column);
                    comp.setForeground(Color.black);
                    if ((type) && (!type1)) {
                        comp.setBackground(Color.yellow);
                    } else if ((!type) && (type1)) {
                        comp.setBackground(Color.orange);
                    } else if ((!type) || (!type1)) {
                        comp.setBackground(Color.red);
                        //} else if ((!type2)) {
                        //comp.setForeground(Color.red);
                        //comp.setBackground(Color.magenta);
                    } else {
                        comp.setBackground(row % 2 == 0 ? getBackground() : getBackground().darker());
                    }
                    dialogTable.convertRowIndexToView(0);
                } else {
                    comp.setForeground(Color.blue);
                    comp.setBackground(Color.lightGray);
                }
                if (!isCellEditable(row, column)) {
                    comp.setForeground(Color.red);
                    comp.setBackground(Color.magenta);
                }
                return comp;
            }
        };
        tableScroll = new JScrollPane(dialogTable, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        tableScroll.setBorder(null);
        dialogTable.getTableHeader().setReorderingAllowed(false);
        dialogTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        lsDialog = dialogTable.getSelectionModel();
        dialogTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
        dialogTable.setRowHeight(20);
        dialogTable.setRowMargin(2);
        ListSelectionModel rowSelMod = dialogTable.getSelectionModel();
        //ListSelectionModel colSelMod = dialogTable.getColumnModel().getSelectionModel();
        rowSelMod.addListSelectionListener(this);
        //colSelMod.addListSelectionListener(this);
        fatherCenter = new JPanel();
        fatherCenter.setLayout(new BorderLayout(10, 10));
        fatherCenter.add(tableScroll, BorderLayout.CENTER);
        pane.add(fatherCenter);
    }

    private void addData() {
        Runnable doRun1 = new Runnable() {

            @Override
            public void run() {
                tableModel.resetTable();
                Vector<String> tbl = new Vector<String>();
                Vector<Object> tbl1 = new Vector<Object>();
                Random rnd = new Random();
                tbl.add("Integer");
                tbl.add("Double");
                tbl.add("Boolean");
                tbl.add("Boolean");
                tbl.add("String");
                tableModel.setColumnNames(tbl);
                for (int row = 0; row < 30; row++) {
                    tbl1 = null;
                    tbl1 = new Vector<Object>();
                    tbl1.addElement(row + 1);
                    tbl1.addElement(rnd.nextInt(25) + 3.14);
                    tbl1.addElement((row % 3 == 0) ? false : true);
                    tbl1.addElement((row % 5 == 0) ? false : true);
                    if (row % 7 == 0) {
                        tbl1.add(("Canc"));
                    } else if (row % 6 == 0) {
                        tbl1.add(("Del"));
                    } else {
                        tbl1.add(("New"));
                    }
                    tableModel.addRow(tbl1);
                }
                addTableListener();
            }
        };
        SwingUtilities.invokeLater(doRun1);
    }

    private void addTableListener() {
        tableModel.addTableModelListener(new TableModelListener() {

            @Override
            public void tableChanged(TableModelEvent tme) {
                if (tme.getType() == TableModelEvent.UPDATE) {
                    System.out.println("");
                    System.out.println("Cell " + tme.getFirstRow() + ", "
                            + tme.getColumn() + " changed. The new value: "
                            + tableModel.getValueAt(tme.getFirstRow(),
                            tme.getColumn()));
                }
            }
        });
    }

    public void valueChanged(ListSelectionEvent le) {
        int row = dialogTable.getSelectedRow();
        int col = dialogTable.getSelectedColumn();
        String str = "Selected Row(s): ";
        int[] rows = dialogTable.getSelectedRows();
        for (int i = 0; i < rows.length; i++) {
            str += rows[i] + " ";
        }
        str += "Selected Column(s): ";
        int[] cols = dialogTable.getSelectedColumns();
        for (int i = 0; i < cols.length; i++) {
            str += cols[i] + " ";
        }
        str += "Selected Cell: " + dialogTable.getSelectedRow() + ", " + dialogTable.getSelectedColumn();
        System.out.println(str);
        Object value = dialogTable.getValueAt(row, col);
        System.out.println(String.valueOf(value));
    }

    private void createAndShowGUI() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout(10, 10));
        addComponentsToPane(frame.getContentPane());
        addData();
        frame.setLocation(150, 150);
        frame.setPreferredSize(new Dimension(400, 647));
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        Forum osFrame = new Forum();
    }

    public Forum() {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private class myTableModel extends AbstractTableModel {

        private static final long serialVersionUID = 1L;
        private Vector<Vector<Object>> data;
        private Vector<String> colNames;
        private boolean[] _columnsVisible = {true, true, true, true, true};

        myTableModel() {
            this.colNames = new Vector<String>();
            this.data = new Vector<Vector<Object>>();
        }

        myTableModel(Vector<String> colnames) {
            this.colNames = colnames;
            this.data = new Vector<Vector<Object>>();
        }

        public void resetTable() {
            this.colNames.removeAllElements();
            this.data.removeAllElements();
        }

        public void setColumnNames(Vector<String> colNames) {
            this.colNames = colNames;
            this.fireTableStructureChanged();
        }

        public void addRow(Vector<Object> data) {
            this.data.add(data);
            this.fireTableDataChanged();
            this.fireTableStructureChanged();
        }

        public void removeRowAt(int row) {
            this.data.removeElementAt(row);
            this.fireTableDataChanged();
        }

        @Override
        public int getColumnCount() {
            return this.colNames.size();
        }

        @Override
        public Class<?> getColumnClass(int colNum) {
            switch (colNum) {
                case 0:
                    return Integer.class;
                case 1:
                    return Double.class;
                case 2:
                    return Boolean.class;
                case 3:
                    return Boolean.class;
                default:
                    return String.class;
            }
        }

        @Override
        public boolean isCellEditable(int row, int colNum) {
            switch (colNum) {
                case 2:
                    return false;
                default:
                    return true;
            }
        }

        @Override
        public String getColumnName(int colNum) {
            return this.colNames.get(colNum);
        }

        @Override
        public int getRowCount() {
            return this.data.size();
        }

        @Override
        public Object getValueAt(int row, int col) {
            Vector<Object> value = this.data.get(row);
            return value.get(col);
        }

        @Override
        public void setValueAt(Object newVal, int row, int col) {
            Vector<Object> aRow = data.elementAt(row);
            aRow.remove(col);
            aRow.insertElementAt(newVal, col);
            fireTableCellUpdated(row, col);
        }

        public void setColumnVisible(int index, boolean visible) {
            this._columnsVisible[index] = visible;
            this.fireTableStructureChanged();
        }
    }
}
野侃 2024-12-04 05:08:43

姆科贝尔正在做一些事情。如果您创建自己的单元格编辑器来扩展 DefaultCellEditor 会怎样:

  customerTable.setDefaultEditor(String.class, new DefaultCellEditor(new JTextField()){
     @Override
     public Component getTableCellEditorComponent(JTable table,
              Object value, boolean isSelected, int row, int column) {
        // code on line below is redundant but would be needed if need to see
        // other property of the value object than toString()
        String valueStr = (value == null) ? "null" : value.toString();
        System.out.printf("[%d, %d]: %s%n", row, column, valueStr);
        return super.getTableCellEditorComponent(table, value, isSelected, row, column);
     }

     @Override
     public Object getCellEditorValue() {
        System.out.printf("cell editor value: %s%n", super.getCellEditorValue());
        return super.getCellEditorValue();
     }
  });

mKorbel is on to something. What if you create your own cell editor that extends DefaultCellEditor:

  customerTable.setDefaultEditor(String.class, new DefaultCellEditor(new JTextField()){
     @Override
     public Component getTableCellEditorComponent(JTable table,
              Object value, boolean isSelected, int row, int column) {
        // code on line below is redundant but would be needed if need to see
        // other property of the value object than toString()
        String valueStr = (value == null) ? "null" : value.toString();
        System.out.printf("[%d, %d]: %s%n", row, column, valueStr);
        return super.getTableCellEditorComponent(table, value, isSelected, row, column);
     }

     @Override
     public Object getCellEditorValue() {
        System.out.printf("cell editor value: %s%n", super.getCellEditorValue());
        return super.getCellEditorValue();
     }
  });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文