2017-06-03 5 views
0

J'ai créé un JTreeTable où le TreeCellRenderer est un JTable. Cela me permet d'avoir différents TableColumnModel pour chaque rangée. Les frères et sœurs des JTree partagent un TableColumnModel. Cela fonctionne très bien. Je peux sélectionner une rangée et montrer un ensemble différent de colonnes sans réellement changer les données dans les autres rangées même à des niveaux différents.JTable redimensionne mes largeurs de colonnes

J'ai cependant un problème lorsque, lorsque vous sélectionnez une ligne différente, la JTable change ma largeur de TableColumn et la règle sur la taille préférée. L'effet est donc que le fait de faire glisser la largeur d'une colonne puis de sélectionner une ligne différente la redéfinit à la taille préférée.

J'ai essayé un certain nombre de choses pour résoudre ce problème, y compris l'ajout d'un TableColumnModelListener et quand je change la largeur, je définis la taille préférée de la colonne. Cela ne fonctionne pas car JTable définit la taille préférée à 15 après que je l'ai modifiée.

J'ai remonté le code à cause de cela. C'est la méthode JTable.doLayout() qui cause mon chagrin. Cette méthode appelle la méthode privée setWidthsFromPreferredWidths(...). Cette méthode est ce qui définit mes largeurs TableColumn.

J'ai essayé de surcharger la méthode doLayout() car elle est publique mais je n'ai pas pu appeler super.doLayout() alors que je suis déjà en train de surcharger la méthode. Ne pas appeler cela provoque des problèmes d'interface utilisateur très étranges, comme vous pouvez l'imaginer. J'ai également essayé de couler this à la superclasse de JTable qui est JComponent mais je me retrouve avec une erreur de dépassement de pile. Cela ne semble pas être la bonne solution ici de toute façon. Ce que je pense qui se passe est que parce que mon JTable est à l'intérieur d'un panneau comme rendu d'une cellule d'arbre au lieu d'à l'intérieur d'un scrollpane, quelque chose ne va pas avec la disposition. Je ne sais pas avec certitude cependant . Ci-dessous le code à l'intérieur de la méthode privée I mentionné ci-dessus:

private void setWidthsFromPreferredWidths(final boolean inverse) { 
    int totalWidth  = getWidth(); 
    int totalPreferred = getPreferredSize().width; 
    int target = !inverse ? totalWidth : totalPreferred; 

    final TableColumnModel cm = columnModel; 
    Resizable3 r = new Resizable3() { 
     public int getElementCount()  { return cm.getColumnCount(); } 
     public int getLowerBoundAt(int i) { return cm.getColumn(i).getMinWidth(); } 
     public int getUpperBoundAt(int i) { return cm.getColumn(i).getMaxWidth(); } 
     public int getMidPointAt(int i) { 
      if (!inverse) { 
       return cm.getColumn(i).getPreferredWidth(); 
      } 
      else { 
       return cm.getColumn(i).getWidth(); 
      } 
     } 
     public void setSizeAt(int s, int i) { 
      if (!inverse) { 
       cm.getColumn(i).setWidth(s); 
      } 
      else { 
       cm.getColumn(i).setPreferredWidth(s); 
      } 
     } 
    }; 

    adjustSizes(target, r, inverse); 
} 

En regardant le code, je pense que ce qui se passe est que la méthode getWidth() est à l'origine du JTable vouloir redimensionner les colonnes à preferredSize parce qu'il pense il n'a pas assez de place. J'ai essayé de simplement copier cette méthode localement mais comme il y a des méthodes privées impliquées et ça continue de plus en plus profond, j'ai arrêté ça. L'intention était d'essayer de déboguer pourquoi il est choisi d'ajuster la largeur. Si je peux m'attaquer à la cause première, c'est peut-être la meilleure solution pour cela.

Le JTree se trouve à l'intérieur de JScrollPane. Le JTableHeader est défini sur ViewPortColumnHeaderView. Voici deux images où je sélectionne différentes lignes. Ignorer l'alignement d'en-tête, j'ai déjà une solution pour cela ne l'a pas encore entièrement mis en œuvre.

JTreeTable-Level1 JTreeTable-Level2

Toute réflexion sur le problème serait grandement apprécié. Aussi heureux d'afficher tout code que vous pensez pourrait être utile si vous pensez que cela va aider.

Répondre

0

Donc, après beaucoup de modifications et d'enquêtes, il était dû ne pas avoir un scrollpane pour les tables. Je ne l'ai pas fait à l'origine parce qu'il y avait une bordure funky autour et que la mise à zéro ne fonctionnait pas. Ce que je devais faire était de définir une bordure vide.