簡體   English   中英

調用JTable.setModel()的先前模型行為

[英]Calling Previous Model Behavior of JTable.setModel()

我的秋千屏幕上有一個JTable 在加載屏幕時,我正在設置一個僅為此表創建的表模型。 在運行時,如果有任何數據更改,我正在重新創建相同的模型,並再次使用objJTable.setModel(objCustTableModel)

現在問題是在屏幕加載時加載的表模型,在運行時設置objJTable.setModel(objCustTableModel)時調用相同的模型對象,該方法從CustTableModel類調用getColumnClass(int col)方法。 在此對象調用之后,我的新模型對象被調用。 再次,如果我通過使用相同的代碼objJTable.setModel(objCustTableModel2)設置另一個新的表模型,則首先從objCustTableModel然后objCustTableModel2調用模型調用的函數。

簡而言之, setModel()函數首先調用前一個模型對象然后調用當前模型對象。 如何限制調用以前的模型對象?

例如

import java.awt.Cursor;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;


/**
 * Steps to reproduce issue.
 * 1. Run this program.
 * 2. There will be two rows in table. Delete all rows one by one.
 * 3. Now click on Add button and see the exception.
 * 
 * I come to know that this exception is because of table.setAutoCreateRowSorter(true); line, which is there in TestCustTableModel's constructor
 * If you comment this line, then issue got resolved.
 * But I want to apply sorting on columns so this line is required.
 */

public class TestCustTableModel extends JPanel{
    JTable table = new JTable();
    public TestCustTableModel() {

        Object[][] data = new Object[2][3];
        data[0][0] = "1";
        data[0][1] = "User1";
        data[0][2] = "Delete";

        data[1][0] = "2";
        data[1][1] = "User2";
        data[1][2] = "Delete";

        JButton addButton = new JButton("Add");
        addButton.addMouseListener(new AddListener());
        table.setModel(new CustModel(data));
        table.addMouseListener(new TableListener());

        /**#################################
         * Following line throws ArrayIndexOutOfBoundsException. Please comment or Uncomment following line and see the difference.
         */
        table.setAutoCreateRowSorter(true);


        table.getTableHeader().setCursor(new Cursor(Cursor.HAND_CURSOR));
        JScrollPane scrollPane = new JScrollPane(table);

        this.add(addButton);
        this.add(scrollPane);
    }


    class TableListener extends MouseAdapter {
        public void mouseClicked(MouseEvent evnt) {
            Point p = evnt.getPoint();
            if(table.columnAtPoint(p) == 2) {
                Object[][] data = null;
                if(table.getModel().getRowCount() == 2 && table.rowAtPoint(p) == 0) {
                    data = new Object[1][3];
                    data[0][0] = "2";
                    data[0][1] = "User2";
                    data[0][2] = "Delete";
                }else if(table.getModel().getRowCount() == 2 && table.rowAtPoint(p) == 1) {
                    data = new Object[1][3];
                    data[0][0] = "1";
                    data[0][1] = "User1";
                    data[0][2] = "Delete";
                }else {
                    data = new Object[0][];
                }
                table.setModel(new CustModel(data));
            }
        }
    }


    class AddListener extends MouseAdapter{

        @Override
        public void mouseClicked(MouseEvent evnt) {
            if(table.getModel().getRowCount() == 2) {
                return;
            }
            Object[][] data = new Object[table.getModel().getRowCount() + 1][3];
            for(int i = 0; i <= table.getModel().getRowCount(); i++) {
                data[i][0] = i;
                data[i][1] = "User" + i;
                data[i][2] = "Delete";
            }
            table.setModel(new CustModel(data));
        }

    }

    class CustModel extends AbstractTableModel {
        private String[] columnNames = {"ID", "NAME", "DELETE"};
        private Object[][] data = null;

        public CustModel(Object[][] data) {
            this.data = data;
        }
        public int getColumnCount() {
            return columnNames.length;
        }

        public int getRowCount() {
            return data.length;
        }

        public String getColumnName(int col) {
            return columnNames[col];
        }

        public Object getValueAt(int row, int col) {
            return data[row][col];
        }

        public Class getColumnClass(int col) {
            return getValueAt(0, col).getClass();
        }
    }

    private void display() {
        JFrame f = new JFrame("SwapTableModel");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        TestCustTableModel obj = new TestCustTableModel();
        obj.display();
    }
}

此時swing首先在內部調用getColumnClass函數,在objCustTableModel的基礎上, objCustTableModel使用objCustTableModel2對象。 我想限制基於objCustTableModel

從這個例子開始,我沒有看到下面顯示的getColumnClass()實現的意外行為。

private Model() {
    final Object[] data = {this.toString()};
    this.model = new DefaultTableModel(data, 1){

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            System.out.println(data[0]);
            return super.getColumnClass(columnIndex);
        }
    };
    model.addRow(data);
}

請注意, JTable可以在確定單元格需要渲染時調用getColumnClass() 如有必要,您可以使用EventQueue.invokeLater()來安排“在處理完所有待處理事件后發生”的事情。

EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        // do something
    }
});

附加物:

  • 如果getAutoCreateRowSorter()true ,則setModel()嘗試恢復使用舊模型創建的RowSorter

  • 您可以指定setAutoCreateRowSorter(true)更改的模型,如下圖所示,或擴展您TableModel來更新替代模型,如圖所示這里

  • 使用ActionListener for JButton而不是MouseListener

  • 對表中的按鈕使用TableCellEditor ,如此此處所示。

碼:

addButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        if (table.getModel().getRowCount() == 2) {
            return;
        }
        Object[][] data = new Object[table.getModel().getRowCount() + 1][5];
        table.setRowSorter(null);
        for (int i = 0; i <= table.getModel().getRowCount(); i++) {
            data[i][0] = i;
            data[i][6] = "User" + i;
            data[i][7] = "Delete";
        }
        table.setModel(new CustModel(data));
        table.setAutoCreateRowSorter(true);
    }
});
 DefaultTableModel model ;
    /** Creates new form DynRowAdd */
    public DynRowAdd() {
        initComponents();
          model = new DefaultTableModel();
                    jTable1.setModel(model);
                    model.addColumn("Id");
                    model.addColumn("First Name");
                    model.addColumn("Last Name");
                    model.addColumn("Company Name");
    }
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         

        model.addRow(new Object[]{jTextField1.getText(), jTextField2.getText(),jTextField3.getText(),jTextField4.getText()});

    }                

之前我遇到過類似的問題,因為我在jtable的ListSelectionListener中調用了jTable.getValueAt(jTable.getSelectedRow(),col),並且在更改jtable的模型之后,在調用jTable.setModel之后拋出了無效的索引,超出了綁定的異常(模型)在行選擇之​​后,它通過確保調用值和所選行getter來解決 - jTable.getValueAt(jTable.getSelectedRow(),col) - 不是來自舊事件,它們仍在制作中,在jtable的ListSelectionListener中的!event.getValueIsAdjusting(),我通過這個問題理解這個符號,它是在jtable的set模型調用中調用舊模型時不試圖調用值和選擇的行getter - 如果你有一個更好的知識,如果我錯了或不准確,請你糾正我 - 這是我之前問題的一個例子,你可以嘗試評論!event.getValueIsAdjusting()if條件,看看符號:

package testingsetmodel;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;


public class TestingSetModel extends javax.swing.JFrame implements ItemListener  {


    TestingSetModel() {                                

        init();        

    }

    private void init()
    {

        northPanel = new JPanel( );     // for adding jtable6
        eastPanel = new JPanel( );      // for adding jtable7
        southPanel = new JPanel( );     // for adding 2 jradiobuttons

        first = new JRadioButton("1st");               
        second = new JRadioButton("2nd", true);  

        rg = new ButtonGroup( ); 
        rg.add( first ) ;  rg.add( second ) ;                              

        first.addItemListener(this);        second.addItemListener(this); 

        jScrollPane6 = new JScrollPane();
        jScrollPane7 = new JScrollPane();

        northPanel.add(jScrollPane6);    eastPanel.add(jScrollPane7);
        southPanel.add(first);      southPanel.add(second);        

        jTable6 = new javax.swing.JTable(){
            DefaultTableCellRenderer renderRight = new DefaultTableCellRenderer();

            { // initializer block
                renderRight.setHorizontalAlignment(SwingConstants.RIGHT);
            }

            @Override
            public TableCellRenderer getCellRenderer (int arg0, int arg1) {
                return renderRight;
            }

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

        };

        jTable6.setAutoCreateRowSorter(false);

        jTable6.setFont(new java.awt.Font("Traditional Arabic", 0, 19));

        jTable6.setEnabled(true);

        jTable6.setRowHeight(25);


        ((DefaultTableCellRenderer)jTable6.getTableHeader().getDefaultRenderer()).setHorizontalAlignment(JLabel.RIGHT);
        jTable6.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        jScrollPane6.setViewportView(jTable6);
        jTable6.setSelectionBackground(new Color(0,100,255,7)); // cutomize selection color
        jTable6.setSelectionForeground(Color.black);

        jTable6.setRowSelectionAllowed(true);

        setTheDefaultJTable6Model();

        if(jTable6.getRowCount()>0)
        {
            for(int i = 0; i<jTable6.getRowCount(); i++)
            {
                if(jTable6.getValueAt(i,0).toString().equalsIgnoreCase("4"))
                {
                    jTable6.setRowSelectionInterval(i, i);
                    jTable6.scrollRectToVisible(new Rectangle(jTable6.getCellRect(i, 0, true)));
                }
            }
        }

        jTable7 = new javax.swing.JTable(){
            DefaultTableCellRenderer renderRight = new DefaultTableCellRenderer();

            { // initializer block
                renderRight.setHorizontalAlignment(SwingConstants.RIGHT);
            }

            @Override
            public TableCellRenderer getCellRenderer (int arg0, int arg1) {
                return renderRight;
            }

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

        };

        jTable7.setAutoCreateRowSorter(false);

        jTable7.setFont(new java.awt.Font("Traditional Arabic", 0, 19));

        jTable7.setEnabled(true);

        jTable7.setRowHeight(25);

        jTable7.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);

        jScrollPane7.setViewportView(jTable7);
        jTable7.setSelectionBackground(new Color(0,100,255,7)); // cutomize selection color for lite one for writting under selection
        jTable7.setSelectionForeground(Color.black);

        jTable7.setRowSelectionAllowed(true);

        jTable6.getSelectionModel().addListSelectionListener(new ListSelectionListener(){


            @Override
            public void valueChanged(ListSelectionEvent event) {

                // try to comment the following if condition, and setting the model through changing the jradiobuttons
                if(!event.getValueIsAdjusting() && jTable6.getSelectedRow() != -1 && jTable6.getSelectedRowCount() == 1)
                {

                    DefaultTableModel clinicsSpecsJtableModel = new DefaultTableModel(); // the model
                    Object[] clinicsSpecsJtableColumnsNames = new Object[2]; // the four showable columns from the jtable model
                    clinicsSpecsJtableColumnsNames[0] = "name" ;
                    clinicsSpecsJtableColumnsNames[1] = "address" ;
                    clinicsSpecsJtableModel.setColumnIdentifiers(clinicsSpecsJtableColumnsNames);
                    Object[] clinicsSpecsJtableRowData = new Object[2];
                    ArrayList<String> clinicsNames = new ArrayList<>();
                    ArrayList<String> clinicsAddresses = new ArrayList<>();
                    clinicsNames.add("J34hp "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
                    clinicsNames.add("J34df "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
                    clinicsNames.add("J34as "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
                    clinicsNames.add("J34gh "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
                    clinicsNames.add("J45hj "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
                    clinicsNames.add("J56gr "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
                    clinicsNames.add("J34mn "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
                    clinicsNames.add("J56vr "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
                    clinicsNames.add("J45pi "+jTable6.getValueAt(jTable6.getSelectedRow(), 0).toString());
                    clinicsAddresses.add("21 Tmk st");
                    clinicsAddresses.add("13 bcv st");
                    clinicsAddresses.add("67 rfb st");
                    clinicsAddresses.add("81 Tmk st");
                    clinicsAddresses.add("31 Tmk st");
                    clinicsAddresses.add("23 Jkl st");
                    clinicsAddresses.add("54 IUR st");
                    clinicsAddresses.add("51 Jkl st");
                    clinicsAddresses.add("71 rfb st");
                    for( int i=0 ; i<clinicsNames.size() ; i++ )
                    {

                        clinicsSpecsJtableRowData[0] = clinicsNames.get(i);
                        clinicsSpecsJtableRowData[1] = clinicsAddresses.get(i);

                        clinicsSpecsJtableModel.addRow(clinicsSpecsJtableRowData); // adding the row to the model

                    }
                    jTable7.setModel(clinicsSpecsJtableModel); // setting the model to the jtable
                    for (int column = 0; column < jTable7.getColumnCount(); column++)
                    {
                        TableColumn tableColumn = jTable7.getColumnModel().getColumn(column);
                        int preferredWidth = tableColumn.getMinWidth();
                        int maxWidth = tableColumn.getMaxWidth();

                        for (int row = 0; row < jTable7.getRowCount(); row++)
                        {
                            TableCellRenderer cellRenderer = jTable7.getCellRenderer(row, column);
                            Component c = jTable7.prepareRenderer(cellRenderer, row, column);
                            int width = c.getPreferredSize().width + jTable7.getIntercellSpacing().width;
                            preferredWidth = Math.max(preferredWidth, width);

                            //  We've exceeded the maximum width, no need to check other rows

                            if (preferredWidth >= maxWidth)
                            {
                                preferredWidth = maxWidth;
                                break;
                            }
                        }

                        tableColumn.setPreferredWidth( preferredWidth );
                    }
                    jTable7.getTableHeader().setFont(new Font("Traditional Arabic", 0, 17)); // assure the column headers font and text size
                    ((DefaultTableCellRenderer)jTable7.getTableHeader().getDefaultRenderer()).setHorizontalAlignment(JLabel.RIGHT); // align right
                    jTable7.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // set single selection only enabled
                    jScrollPane7.setViewportView(jTable7); // draw jtable             

                }                       

            }

        });                                   

        Container cont = getContentPane();
        cont.add(northPanel, BorderLayout.NORTH);
        cont.add(eastPanel, BorderLayout.EAST);
        cont.add(southPanel, BorderLayout.SOUTH);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // to close the JFrame        

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        EventQueue.invokeLater(() -> {

            JFrame f = new TestingSetModel();
            f.setSize(800, 600);    
            f.setVisible(true);        

        });
    }

    private javax.swing.JPanel northPanel, southPanel, eastPanel;                                   
    private javax.swing.JRadioButton first, second;
    private javax.swing.ButtonGroup rg;                
    private javax.swing.JTable jTable6;
    private javax.swing.JScrollPane jScrollPane6;
    private javax.swing.JTable jTable7;
    private javax.swing.JScrollPane jScrollPane7;

    @Override
    public void itemStateChanged(ItemEvent e) {

        if(first.isSelected())
        {

            setTheDefaultJTable6Model();
            removeJTable7Rows();


        }else if(second.isSelected())
        {

            setTheCustomizedJTable6Model();
            removeJTable7Rows();

        }


    }


    private void removeJTable7Rows()
    {

        DefaultTableModel defaultModel = (DefaultTableModel) jTable7.getModel();
        defaultModel.setRowCount(0);        

    }    

    private void setTheDefaultJTable6Model()
    {

        DefaultTableModel numbersJtableModel = new DefaultTableModel(); // the model
        Object[] numbersJtableColumnsNames = new Object[1]; // the four showable columns from the jtable model
        numbersJtableColumnsNames[0] = "number" ;

        numbersJtableModel.setColumnIdentifiers(numbersJtableColumnsNames);
        Object[] numbersJtableRowData = new Object[1]; 
        ArrayList<String> numbers = new ArrayList<>();

        numbers.add("1");
        numbers.add("2");
        numbers.add("3");
        numbers.add("4");
        numbers.add("5");
        numbers.add("6");


        for( int i=0 ; i<numbers.size() ; i++ ) // feeding array of object with numbers data
        {
            numbersJtableRowData[0] = numbers.get(i);

            numbersJtableModel.addRow(numbersJtableRowData); // adding the row to the model

        }

        jTable6.setModel(numbersJtableModel); // setting the model to the jtable


        for (int column = 0; column < jTable6.getColumnCount(); column++)
        {
            TableColumn tableColumn = jTable6.getColumnModel().getColumn(column);
            int preferredWidth = tableColumn.getMinWidth();
            int maxWidth = tableColumn.getMaxWidth(); 

            for (int row = 0; row < jTable6.getRowCount(); row++)
            {
                TableCellRenderer cellRenderer = jTable6.getCellRenderer(row, column);
                Component c = jTable6.prepareRenderer(cellRenderer, row, column);
                int width = c.getPreferredSize().width + jTable6.getIntercellSpacing().width;
                preferredWidth = Math.max(preferredWidth, width);

                //  We've exceeded the maximum width, no need to check other rows

                if (preferredWidth >= maxWidth)
                {
                    preferredWidth = maxWidth;
                    break;
                }
            }                    

            tableColumn.setPreferredWidth( preferredWidth );
        }

        jTable6.getTableHeader().setFont(new Font("Traditional Arabic", 0, 17)); // assure the column headers font and text size
        ((DefaultTableCellRenderer)jTable6.getTableHeader().getDefaultRenderer()).setHorizontalAlignment(JLabel.RIGHT); // align right
        jTable6.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // set single selection only enabled
        jScrollPane6.setViewportView(jTable6); // draw jtable


    }


    private void setTheCustomizedJTable6Model()
    {

        DefaultTableModel numbersJtableModel = new DefaultTableModel(); // the model
        Object[] numbersJtableColumnsNames = new Object[1]; // the four showable columns from the jtable model
        numbersJtableColumnsNames[0] = "number" ;

        numbersJtableModel.setColumnIdentifiers(numbersJtableColumnsNames);
        Object[] numbersJtableRowData = new Object[1]; 
        ArrayList<String> numbers = new ArrayList<>();

        numbers.add("10");
        numbers.add("20");
        numbers.add("30");
        numbers.add("40");
        numbers.add("50");
        numbers.add("60");


        for( int i=0 ; i<numbers.size() ; i++ ) // feeding array of object with numbers data
        {
            numbersJtableRowData[0] = numbers.get(i);

            numbersJtableModel.addRow(numbersJtableRowData); // adding the row to the model

        }

        jTable6.setModel(numbersJtableModel); // setting the model to the jtable


        for (int column = 0; column < jTable6.getColumnCount(); column++)
        {
            TableColumn tableColumn = jTable6.getColumnModel().getColumn(column);
            int preferredWidth = tableColumn.getMinWidth();
            int maxWidth = tableColumn.getMaxWidth(); 

            for (int row = 0; row < jTable6.getRowCount(); row++)
            {
                TableCellRenderer cellRenderer = jTable6.getCellRenderer(row, column);
                Component c = jTable6.prepareRenderer(cellRenderer, row, column);
                int width = c.getPreferredSize().width + jTable6.getIntercellSpacing().width;
                preferredWidth = Math.max(preferredWidth, width);

                //  We've exceeded the maximum width, no need to check other rows

                if (preferredWidth >= maxWidth)
                {
                    preferredWidth = maxWidth;
                    break;
                }
            }                    

            tableColumn.setPreferredWidth( preferredWidth );
        }

        jTable6.getTableHeader().setFont(new Font("Traditional Arabic", 0, 17)); // assure the column headers font and text size
        ((DefaultTableCellRenderer)jTable6.getTableHeader().getDefaultRenderer()).setHorizontalAlignment(JLabel.RIGHT); // align right
        jTable6.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // set single selection only enabled
        jScrollPane6.setViewportView(jTable6); // draw jtable


    }    

}

此示例應通過setTheDefaultJTable6Model()方法中的setModel()方法選擇單選按鈕組中的其他單選按鈕來更改jTable6的模型。 所以在這樣的情況下,我們與jtable模型有一定的聯系,而沒有確保它不是來自之前仍在進行更改的任何事件,我們會在將jtable的模型設置為新模型后得到異常

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM