Java 创建JTable行标题

Java 创建JTable行标题,java,swing,jtable,Java,Swing,Jtable,我是JTable的新手。我正在使用JTable和Toplink(JPA)进行秋千训练。我有两个按钮“添加行”,“删除行”,我有一些记录显示从数据库。当点击“添加行”一条新记录时,应将行标题添加到JTable中,并在JTable行标题中按顺序显示自动递增编号 在使用“删除行”按钮删除期间,必须删除记录&而不是其对应的标题,以便下一行更新为前一个标题&自动递增编号保持不变并始终保持顺序 请在这方面帮助我 提前感谢,, Chandu既然你是新来的,我就从你开始。正如这里所建议的,我将扩展、重写getV

我是JTable的新手。我正在使用JTable和Toplink(JPA)进行秋千训练。我有两个按钮“添加行”,“删除行”,我有一些记录显示从数据库。当点击“添加行”一条新记录时,应将行标题添加到JTable中,并在JTable行标题中按顺序显示自动递增编号

在使用“删除行”按钮删除期间,必须删除记录&而不是其对应的标题,以便下一行更新为前一个标题&自动递增编号保持不变并始终保持顺序

请在这方面帮助我

提前感谢,, Chandu

既然你是新来的,我就从你开始。正如这里所建议的,我将扩展、重写
getValueAt()
setValueAt()
getRowCount()
等,以使用相应的JPA实体和控制器类和方法。例如,NetBeans IDE可以自动生成此类类。还有一个将类绑定到Swing组件的特性,包括
JTable
JList
,但我还没有尝试过

如果行id是由数据库管理的自动递增数字,我不确定是否有可靠的方法在多用户环境中保持顺序顺序的外观。如果显示该字段,
isCellEditable()
可能会为该列返回
false
。这就是你所说的行标题吗

附录:另请参见

,因为您是新来的,我先从。正如这里所建议的,我将扩展、重写
getValueAt()
setValueAt()
getRowCount()
等,以使用相应的JPA实体和控制器类和方法。例如,NetBeans IDE可以自动生成此类类。还有一个将类绑定到Swing组件的特性,包括
JTable
JList
,但我还没有尝试过

如果行id是由数据库管理的自动递增数字,我不确定是否有可靠的方法在多用户环境中保持顺序顺序的外观。如果显示该字段,
isCellEditable()
可能会为该列返回
false
。这就是你所说的行标题吗

附录:另见

你的意思是这样吗

添加新记录时,其id设置为行标题(如记录1,2,3),删除记录时,行标题保留,但信息消失(如记录4,5,记录4,5中的数据,但删除后仅保留id)

如果这就是你的意思

您需要做的是创建两个表格模型,一个包裹另一个

  • 包装器的唯一功能是显示一个额外的列(id)并保留数据的内部“副本”

  • 当添加一行时,包装器将获得一条新记录,它将分配一个新id,然后它将获取所有字段并将值复制到自己的数据中,然后将其转发到包装表模型

  • 删除行时,包装器不会删除自己的记录,它只会清理(设置为“”)列值,并保留id列。然后,它将事件转发到包装的列,该列将实际删除该行

类似于下面的java

 // Wrapper table model   
 class IdTableModel implements TableModelListener {
      TableModel original;

      // Analog to: Object[][]
      List<List<Object> data = new ArrayList<List<Object>();

      // will take a copy of the data in original
      public IdTableModel( TableModel original ) {
          this.original = original;
          // fillData with values from original
         for( int row = 0 ; row < original.getRowCount(); row++ ) {
              List<Object> shadowRow = new ArrayList<Object>();
              shadowRow.add( row ); // the id
              // copy the values from original to this shadow
              for( int column = 0 ; column < original.getColumnCount(); column++ ) {
                  shadowRow.add( original.getValueAt(row,i));
              }
              // add the shadow to the data
              data.add( shadowRow );
          }
          original.addTableModelListener( this );
      }

      // for Object getValueAt( x, y ) get the data from your "data" not from the original

       ....
       //Here's the magic. this wapper will be a listener of the original
       // then this method will be invoked when the original gets more data 
       // or when it is removed.....
       public void tableChanged( TableEvent e )  {
           int row = e.getFirstRow();
           List<Object> shadowRow = data.get( row);
           switch( e.getType() ) {
               case TableEvent.INSERT:
                    if( ( shadowRow =) == null )  {
                        // there wasn't shadow data at that position
                        data.add( ( shadowRow = new ArrayList<Object>()));
                     }
                     // takevalues from original 
                     shadowRow.add( row ); // the id
                     for( int i = 0 ; i < original.getColumnCount();i++ ) {
                          shadowRow.add( original.getValueAt(row,i));
                     }
               break;
               case TableEvent.UPDATE:
                      // similar to insert, but you don't create a new row        
                     // takevalues from original 
                     for( int i = 0 ; i < original.getColumnCount();i++ ) {
                          shadowRow.set( i+1, original.getValueAt(row,i));
                     }
               break;
               case TableEvent.DELETE:
                      // You don't delete your shadow rows, but just clean it up
                     for( int i = 0 ; i < original.getColumnCount();i++ ) {
                          shadowRow.set( i+1, "");
                     }

               break;

       } 


       // forward calls to the original
      public int getColumnCount(){
           return original.getColumnCount()+1;
      }
      public String getColumnName( int columnIndex ) {
          if( columnIndex == 0 ) {
              return "id";
           } else {
               return original.getColumnName( columnIndex -1 );
           }
       }

       // and so on for, isEditable etc. etc

 }
如果我说的话对你没有任何意义,那就开始读这个:

你的意思是这样的吗

添加新记录时,其id设置为行标题(如记录1,2,3),删除记录时,行标题保留,但信息消失(如记录4,5,记录4,5中的数据,但删除后仅保留id)

如果这就是你的意思

您需要做的是创建两个表格模型,一个包裹另一个

  • 包装器的唯一功能是显示一个额外的列(id)并保留数据的内部“副本”

  • 当添加一行时,包装器将获得一条新记录,它将分配一个新id,然后它将获取所有字段并将值复制到自己的数据中,然后将其转发到包装表模型

  • 删除行时,包装器不会删除自己的记录,它只会清理(设置为“”)列值,并保留id列。然后,它将事件转发到包装的列,该列将实际删除该行

类似于下面的java

 // Wrapper table model   
 class IdTableModel implements TableModelListener {
      TableModel original;

      // Analog to: Object[][]
      List<List<Object> data = new ArrayList<List<Object>();

      // will take a copy of the data in original
      public IdTableModel( TableModel original ) {
          this.original = original;
          // fillData with values from original
         for( int row = 0 ; row < original.getRowCount(); row++ ) {
              List<Object> shadowRow = new ArrayList<Object>();
              shadowRow.add( row ); // the id
              // copy the values from original to this shadow
              for( int column = 0 ; column < original.getColumnCount(); column++ ) {
                  shadowRow.add( original.getValueAt(row,i));
              }
              // add the shadow to the data
              data.add( shadowRow );
          }
          original.addTableModelListener( this );
      }

      // for Object getValueAt( x, y ) get the data from your "data" not from the original

       ....
       //Here's the magic. this wapper will be a listener of the original
       // then this method will be invoked when the original gets more data 
       // or when it is removed.....
       public void tableChanged( TableEvent e )  {
           int row = e.getFirstRow();
           List<Object> shadowRow = data.get( row);
           switch( e.getType() ) {
               case TableEvent.INSERT:
                    if( ( shadowRow =) == null )  {
                        // there wasn't shadow data at that position
                        data.add( ( shadowRow = new ArrayList<Object>()));
                     }
                     // takevalues from original 
                     shadowRow.add( row ); // the id
                     for( int i = 0 ; i < original.getColumnCount();i++ ) {
                          shadowRow.add( original.getValueAt(row,i));
                     }
               break;
               case TableEvent.UPDATE:
                      // similar to insert, but you don't create a new row        
                     // takevalues from original 
                     for( int i = 0 ; i < original.getColumnCount();i++ ) {
                          shadowRow.set( i+1, original.getValueAt(row,i));
                     }
               break;
               case TableEvent.DELETE:
                      // You don't delete your shadow rows, but just clean it up
                     for( int i = 0 ; i < original.getColumnCount();i++ ) {
                          shadowRow.set( i+1, "");
                     }

               break;

       } 


       // forward calls to the original
      public int getColumnCount(){
           return original.getColumnCount()+1;
      }
      public String getColumnName( int columnIndex ) {
          if( columnIndex == 0 ) {
              return "id";
           } else {
               return original.getColumnName( columnIndex -1 );
           }
       }

       // and so on for, isEditable etc. etc

 }

如果我说的话对你没有任何意义,那就开始读吧:

这一页可能就是你要找的:

这一页可能就是你要找的:

我不明白你的意思。你能举一个简短的例子来说明你想要什么吗?可能会显示一个初始视图,单击“添加行”后是什么样子,单击“删除行”后是什么样子。到目前为止你有什么?我不明白你的意思。你能举一个简短的例子来说明你想要什么吗?也许可以显示一个初始视图,单击“添加行”后是什么样子,单击“删除行”后是什么样子。到目前为止你有什么?谢谢Oscar,我会尝试做同样的事。那些“行标题”会像标题一样正常工作吗?也就是说,它们不应该水平滚动。而且渲染效果也很差——我认为它们至少应该在远处看起来像列标题一样。你能提供这样做的方法吗?@Johannes,是的,这是可能的。您必须查看JScrollPane的rowheader属性。默认情况下,当使用JTable this row header为空的JScrollPane时,可以提供自定义组件。这里的更多信息:谢谢奥斯卡,我也会这么做。那些“行标题”会像标题一样正常工作吗?也就是说,它们不应该水平滚动。而且渲染效果还差得很远——我认为它们至少应该看起来有点像