IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AWT/Swing Java Discussion :

[linux][JTable] Le "renderer" n'est appelé qu'une fois sur les vingt fois prévues


Sujet :

AWT/Swing Java

  1. #1
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut [linux][JTable] Le "renderer" n'est appelé qu'une fois sur les vingt fois prévues
    Bonjour,

    Je suis en dehors de mon labo donc du coup pour les codes sources il faudra que je télécharge d'abord les sources elles ne sont pas disponibles là maintenant, j'ajouterais les extraits de code
    (je dis tout de suite que je ne respecte pas forcément les conventions d'écriture Java, je fais cela un peu "à la volée", ...) dans quelques minutes/heures.

    Description/observation de ce qui me fait dire que ce que j'ai produit comme programme ne me rassure pas sur l'état d'avancement de mon projet:

    J'ai une application qui effectue une connexion avec une base de données, j'ai aucun soucis pour extraire les données et les afficher dans une de mes deux JTable.
    La première affiche des données on va dire brutes, la seconde affiche des données en provenance d'une autre Table de la base de données avec des données un peu plus précises.

    La première JTable se trouve dans une JFrame, la seconde dans une JPanel.
    on accède à ce JPanel via l'appui d'un onglet (ou via "la sélection forcée" en fonction de certains événements...).

    La première JTable fonctionne à merveilles, aucun soucis, bon c'est lent mais c'est peut-être ma manière d'approcher la chose qui n'est pas optimisée (le refraichissement du contenu suite à des ajouts n'est pas instantané en tous cas).
    Par contre la seconde JTable, elle, me pose soucis: j'ai 20 enregistrements à afficher dans cette table, et elle n'affichera jamais qu'une seule "row" (ligne).
    Pourtant j'ai comparé et parcouru les instructions carrément en step by step et, comparant à la fois le Modèle (AbstractTableModel) et le "renderer" (TableCellRenderer0) il y a de très fortes similitudes jusqu'aux noms des objets.

    Le "renderer" lui n'est appelé que pour une seule "row"... alors que la boucle faisant appel à la méthode pour ajouter une ligne dans la table (comme avec la première JTable) est, elle, appelée 20 fois.
    J'ai "watché" avec le débugger les différentes listes disponibles dans le Modèle et dans le "renderer", elles contiennent bien les données, il y en a bien 20 dans le tableau Donnees[][] du Modèle, ma liste représentant les enregistrements en provenance de la base de données contient bien 20 éléments.

    Mes questions:

    1. Est-ce une bonne idée d'avoir deux JTable sur la même fenêtre ?
    2. Comment expliquer que JTable fasse appel à son "renderer" qu'une seule fois sur 20 ?

  2. #2
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Voilà le code incriminé

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    public void computeVictories(java.sql.Connection LaConnection) throws SQLException
    	{
    		System.err.println("computeVictoires");
    		if(LaConnection.isValid(1))
    		{
    			uneConnexion=LaConnection;
    			ListeDesMatches.clear();
    			java.sql.Statement Request=LaConnection.createStatement();
    			bStatusRequest=Request.execute("SELECT * FROM Matches WHERE Result='V'");
    			if(bStatusRequest)
    			{
    				Resultats = Request.getResultSet();
    				//Resultats.first();
    				ModeleTableMatch.ClearDatas();
    				while(Resultats.next())
    				{
    					java.sql.ResultSetMetaData MetaDonnees=Resultats.getMetaData();
    					int NbChamps=MetaDonnees.getColumnCount();
     
    					for(int cptchamps=0;cptchamps<NbChamps;cptchamps++)
    					{
    						String unecolonne=ParseSQL(MetaDonnees.getColumnTypeName(cptchamps+1),Resultats,cptchamps+1);
    						lesdonnees.add(unecolonne);
    					}
    					PackDatasFromDB(lesdonnees);
    					lesdonnees.clear();
    				}
    				System.err.println("Nombre de matches gagnés: "+ListeDesMatches.size());
    				for(int cptMatches=0;cptMatches<ListeDesMatches.size();cptMatches++) ModeleTableMatch.addRow(ListeDesMatches.get(cptMatches));
     
    			}
    			Request.close();
    		}
    	}
    En gros j'utilise une liste contenant les "objets" relatifs à chacun des matches.
    Cette liste est construite via des appels successifs à la méthode PackDatasFromDB qui permet à partir des informations reçues de la base de données de construire des objets de type classEnemy.
    Une fois ces objets construits ils sont ajoutés dans la liste.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    public boolean PackDatasFromDB(LinkedList<Object> source) throws SQLException
    	{
    		classMatch tmp=new classMatch();
    		BitSet tmpbs=new BitSet(5);
    		String PlayerName=new String();
    		int repint;
     
    		tmp.setDBMatchID(Integer.valueOf((String)source.get(classMatch.IDMATCH)));
    		tmp.setDBPlayerID(Integer.valueOf((String)source.get(classMatch.IDPLAYER)));
     
    		if(uneConnexion.isValid(1))
    		{
    			PlayerName=getPlayerNameDB(uneConnexion,tmp.getDBPlayerID());
    		}
     
    		tmp.setName(PlayerName);
     
    		repint=Integer.valueOf((String)source.get(classMatch.MCOL));
     
    		if((repint&ma_Couleurs.VALNOIR)==ma_Couleurs.VALNOIR) tmpbs.set(ma_Couleurs.NOIR);
    		if((repint&ma_Couleurs.VALROUGE)==ma_Couleurs.VALROUGE) tmpbs.set(ma_Couleurs.ROUGE);
    		if((repint&ma_Couleurs.VALVERT)==ma_Couleurs.VALVERT) tmpbs.set(ma_Couleurs.VERT);
    		if((repint&ma_Couleurs.VALBLEU)==ma_Couleurs.VALBLEU) tmpbs.set(ma_Couleurs.BLEU);
    		if((repint&ma_Couleurs.VALBLANC)==ma_Couleurs.VALBLANC) tmpbs.set(ma_Couleurs.BLANC);
     
    		tmp.setColors(tmpbs);
     
     
    		tmp.setTurns(Integer.valueOf((String)source.get(classMatch.TRNS)));
    		tmp.setScore(false,Integer.valueOf((String)source.get(classMatch.HIS)));
    		tmp.setScore(true,Integer.valueOf((String)source.get(classMatch.MYS)));
    		tmp.setResult((String)source.get(classMatch.RES));
    		tmp.importBegin((String)source.get(classMatch.STT)); 
    		tmp.importEnd((String)source.get(classMatch.NDT));
     
    		String value;
    		value = source.get(classMatch.ELVL).toString();
     
    		tmp.importLevel(false,value);
     
    		value=source.get(classMatch.PLVL).toString();
     
    		tmp.importLevel(true,value);
     
    		return ListeDesMatches.add(tmp);
    	}
    Le modèle contient les informations suivantes, exactement les mêmes que pour la JTable de la JFrame...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    	public void addRow(classMatch unmatch)
    	{
    		int CurrentRow=Donnees.length-1;
    		Object saved[][]=new Object[Donnees.length][titres.length];
    		saved=Donnees;
    		Donnees=new Object[Donnees.length+1][titres.length];
    		for(int cpt=CurrentRow-1;cpt>=0;cpt--) Donnees[cpt]=saved[cpt];
     
    		Donnees[CurrentRow][NAME]=unmatch.getName();
    		Donnees[CurrentRow][COL]=new ma_Couleurs(unmatch.getColors());
    		Donnees[CurrentRow][MYLVL]=String.valueOf(unmatch.getLevel(true));
    		Donnees[CurrentRow][SCP]=Integer.toString(unmatch.getScore(true));
    		Donnees[CurrentRow][SCC]=Integer.toString(unmatch.getScore(false));
    		Donnees[CurrentRow][ENLVL]=String.valueOf(unmatch.getLevel(false));
    		//Donnees[CurrentRow][RES]=String.valueOf(unmatch.getResults());
     
     
    		fireTableDataChanged();                                        // On indique au contrôle que quelque chose a changé et qu'il faut redessiner le contenu
    	}
    Quand je "débugge" cette partie je "vois" que les données sont présentes dans le "Modèle" mais le "renderer" n'est appelé qu'une seule fois au lieu de 20...

    Le renderer est renseigné comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    jTableInfos.setDefaultRenderer(ma_Couleurs.class, AfficheurMatch);
    		jTableInfos.setDefaultRenderer(String.class, AfficheurMatch);
    ...et contient...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    public Component getTableCellRendererComponent(JTable LaTable, Object source, boolean isSelected, boolean hasFocus, int ligne, int colonne) 
    	{
    		removeAll();
    		if(colonne==ma_tablemodel.COL) LaTable.getColumnModel().getColumn(colonne).setMinWidth(160);
     
    		setLayout(new FlowLayout(JLabel.CENTER));
    		setBackground(new Color(31, 112, 121,255));
     
     
    		switch(colonne)
    		{
    			case ma_tablemodelmatch.NAME:	add(new JTextField((String)source));
    																		this.getComponent(this.getComponentCount()-1).setFont(new Font("Liberation Mono", Font.BOLD, 12));	
    																		break;
    			case ma_tablemodelmatch.COL:	BitSet valeur=(BitSet)((ma_Couleurs)source).DeckColors.clone();
    																		add(new ma_Couleurs(valeur));
    																		break;
    			case ma_tablemodelmatch.MYLVL:	int keyLevelP=Integer.valueOf((String)source);
    																			add(new JTextField((String)classMatch.Levels.get(keyLevelP)));
    																			this.getComponent(this.getComponentCount()-1).setFont(new Font("Liberation Mono", Font.BOLD, 12));	
    																			break;
    			case ma_tablemodelmatch.SCP:	add(new JTextField((String)source));
    																		this.getComponent(this.getComponentCount()-1).setFont(new Font("Liberation Mono", Font.BOLD, 12));	
    																		break;
    			case ma_tablemodelmatch.SCC:	add(new JTextField((String)source));
    																		this.getComponent(this.getComponentCount()-1).setFont(new Font("Liberation Mono", Font.BOLD, 12));	
    																		break;
    			case ma_tablemodelmatch.ENLVL:	int keyLevelE=Integer.valueOf((String)source);
    																			add(new JTextField((String)classMatch.Levels.get(keyLevelE)));
    																			this.getComponent(this.getComponentCount()-1).setFont(new Font("Liberation Mono", Font.BOLD, 12));	
    																			break;
     
     
    		}
     
    		return this;
    	}

  3. #3
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Voici ce que j'obtiens dans les "logs", cela indique qu'il y a quelque chose que je ne sais expliquer:

    Fonctionnement normal, ici les coordonnées en (x,y) indiquent que les rows sont effectivement "passées correctement au renderer":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Appel au renderer -- classEnemy (0,0)
    Appel au renderer -- classEnemy (1,0)
    ...
    Appel au renderer -- classEnemy (7,0)
    Appel au renderer -- classEnemy (0,1)
    Appel au renderer -- classEnemy (1,1)
    ...
    Appel au renderer -- classEnemy (3,1)
    Appel au renderer -- classEnemy (4,1)
    Appel au renderer -- classEnemy (5,1)
    Appel au renderer -- classEnemy (6,1)
    Appel au renderer -- classEnemy (7,1)
    Ici quand je sélectionne l'onglet victoire... dans le JTabbedPane contenant la JTable
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Selected: Victories
    computeVictoires
    Nombre de matches gagnés: 21
    Appel au modèle -- classMatch (CurrentRow 0)
    Appel au modèle -- classMatch (CurrentRow 1)
    ...
    Appel au modèle -- classMatch (CurrentRow 19)
    Appel au modèle -- classMatch (CurrentRow 20)
    
    Appel au renderer -- classMatch (0,0)
    Appel au renderer -- classMatch (1,0)
    Appel au renderer -- classMatch (2,0)
    Appel au renderer -- classMatch (3,0)
    Appel au renderer -- classMatch (4,0)
    Appel au renderer -- classMatch (5,0)
    ...
    ...et en plus le nombre de "passages" ne correspond pas du tout à ce que le modèle suggère (à savoir 40 passages, je ne sais pas pourquoi le renderer est appelé deux fois pour chaque ajout dans le modèle)
    Cela explique pourquoi je n'ai qu'une seule ligne...

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,



    Citation Envoyé par hurukan Voir le message
    1. Est-ce une bonne idée d'avoir deux JTable sur la même fenêtre ?
    Il n'y aucun souci particulier d'avoir plusieurs JTable dans une même JFrame.

    Citation Envoyé par hurukan Voir le message
    2. Comment expliquer que JTable fasse appel à son "renderer" qu'une seule fois sur 20 ?
    Tout d'abord, le fonctionnement du renderer au sein de la JTable n'est pas tout à fait identique au fonctionnement de n'importe quel autre vue Swing.
    Une JTable n'est pas une gigantesque arborescence de composants car ça pourrait devenir très lourd à gérer. Le renderer est plutôt une sorte de générateur d'images. La JTable l'utilise au besoin pour générer l'image qui représente une cellule.
    Au besoin, c'est-à-dire si et quand elle estime quand il faut invoquer (une première fois ou à nouveau) le renderer, en fonction des données du modèles, des filtres, des tris, des cellules visibles, des interactions utilisateurs, changement de focus ou sélection, etc. Pour ça elle utilise des signaux (des événements) qu'elle génère elle-même sur certains processus et certains qu'on doit lui envoyer (quand on change les données dans le modèle en particulier). Tout ça est optimisé pour chercher le maximum de fluidité et évidemment un rendu complet. Aussi, il faut respecter certains principes pour contribuer à cette fluidité.
    Le nombre d'invocations de la méthode getTableCellRendererComponent est à estimer en fonction des besoins qu'estime la JTable, pas de ce qu'on pense qu'elle devrait faire.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    import java.awt.BorderLayout;
    import java.awt.Component;
    import java.awt.FlowLayout;
    import java.util.Arrays;
    import java.util.concurrent.ThreadLocalRandom;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.concurrent.atomic.AtomicReference;
    import java.util.function.Supplier;
    import java.util.stream.Stream;
     
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.DefaultTableModel;
     
    public class JTableExemple {
     
    	public static void main(String[] args) {
     
    		JFrame frame = new JFrame();
     
    		String[] col = {"Col 1","Col 2"};
     
    		AtomicInteger idfactory = new AtomicInteger(1);
    		Supplier<Object[]> rowgenerator = ()-> new Object[] { idfactory.getAndIncrement(), ThreadLocalRandom.current().nextInt() };
    		Object[][] data = Stream.generate(rowgenerator).limit(100).toArray(Object[][]::new);
     
    		DefaultTableModel tableModel = new DefaultTableModel(data,col);
    		JTable table = new JTable(tableModel);
     
    		AtomicInteger clickCount = new AtomicInteger();
    		String traceFormat = "Invocation getTableCellRendererComponent pour %1$s.%nNombre de lignes : %2$d.%n";
    		AtomicReference<String> formatRef = new AtomicReference<>(traceFormat);
    		String rowTraceFormat = "ligne %d, column %d, %s";
    		class MyRenderer extends DefaultTableCellRenderer {
    			public MyRenderer() {
    				setHorizontalAlignment(JLabel.RIGHT);
    			}
    			public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    				Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    				Object[] rowData = { tableModel.getValueAt(row, 0), tableModel.getValueAt(row, 1) };
    				System.out.printf(
    						formatRef.get(), 
    						String.format(rowTraceFormat, row, column, Arrays.toString(rowData)), 
    						table.getRowCount(), 
    						clickCount.get());
    				return component;
    			};
    		};
     
    		table.setDefaultRenderer(Object.class, new MyRenderer());
     
    		JPanel panel = new JPanel(new BorderLayout());
    		panel.add(new JScrollPane(table));
    		frame.add(panel);
     
    		JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    		JButton button = new JButton("Ajouter une ligne");
    		button.addActionListener(e->{
    			clickCount.incrementAndGet();
    			String newtraceFormat = "Ajout d'une ligne %3$d.%n" + traceFormat;
    			formatRef.set(newtraceFormat);
    			tableModel.addRow(rowgenerator.get());
    		});
    		buttonPanel.add(button);
    		panel.add(buttonPanel,BorderLayout.SOUTH);
     
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setSize(600,400);
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
     
    	}
     
    }
    L'affichage avant de cliquer sur le bouton :
    Invocation getTableCellRendererComponent pour ligne 0, column 0, [1, 366167011].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 0, column 1, [1, 366167011].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 1, column 0, [2, -1702220055].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 1, column 1, [2, -1702220055].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 2, column 0, [3, 1489430607].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 2, column 1, [3, 1489430607].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 3, column 0, [4, -86647432].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 3, column 1, [4, -86647432].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 4, column 0, [5, -722846418].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 4, column 1, [5, -722846418].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 5, column 0, [6, -186805478].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 5, column 1, [6, -186805478].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 6, column 0, [7, 1087626999].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 6, column 1, [7, 1087626999].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 7, column 0, [8, 616411156].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 7, column 1, [8, 616411156].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 8, column 0, [9, 947709073].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 8, column 1, [9, 947709073].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 9, column 0, [10, -1665835107].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 9, column 1, [10, -1665835107].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 10, column 0, [11, 1891308892].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 10, column 1, [11, 1891308892].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 11, column 0, [12, -1537931540].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 11, column 1, [12, -1537931540].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 12, column 0, [13, -1932611427].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 12, column 1, [13, -1932611427].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 13, column 0, [14, 50961568].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 13, column 1, [14, 50961568].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 14, column 0, [15, -181799284].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 14, column 1, [15, -181799284].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 15, column 0, [16, 1305536022].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 15, column 1, [16, 1305536022].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 16, column 0, [17, -429787450].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 16, column 1, [17, -429787450].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 17, column 0, [18, 432956467].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 17, column 1, [18, 432956467].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 18, column 0, [19, 718849351].
    Nombre de lignes : 100.
    Invocation getTableCellRendererComponent pour ligne 18, column 1, [19, 718849351].
    Nombre de lignes : 100.
    
    Puis je clique sur le bouton :
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 0, column 0, [1, 366167011].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 0, column 1, [1, 366167011].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 1, column 0, [2, -1702220055].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 1, column 1, [2, -1702220055].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 2, column 0, [3, 1489430607].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 2, column 1, [3, 1489430607].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 3, column 0, [4, -86647432].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 3, column 1, [4, -86647432].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 4, column 0, [5, -722846418].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 4, column 1, [5, -722846418].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 5, column 0, [6, -186805478].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 5, column 1, [6, -186805478].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 6, column 0, [7, 1087626999].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 6, column 1, [7, 1087626999].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 7, column 0, [8, 616411156].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 7, column 1, [8, 616411156].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 8, column 0, [9, 947709073].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 8, column 1, [9, 947709073].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 9, column 0, [10, -1665835107].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 9, column 1, [10, -1665835107].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 10, column 0, [11, 1891308892].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 10, column 1, [11, 1891308892].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 11, column 0, [12, -1537931540].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 11, column 1, [12, -1537931540].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 12, column 0, [13, -1932611427].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 12, column 1, [13, -1932611427].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 13, column 0, [14, 50961568].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 13, column 1, [14, 50961568].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 14, column 0, [15, -181799284].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 14, column 1, [15, -181799284].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 15, column 0, [16, 1305536022].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 15, column 1, [16, 1305536022].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 16, column 0, [17, -429787450].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 16, column 1, [17, -429787450].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 17, column 0, [18, 432956467].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 17, column 1, [18, 432956467].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 18, column 0, [19, 718849351].
    Nombre de lignes : 101.
    Ajout d'une ligne 1.
    Invocation getTableCellRendererComponent pour ligne 18, column 1, [19, 718849351].
    Nombre de lignes : 101.
    
    Le nombre d'invocation n'est pas du tout en rapport avec le nombre de lignes (100 puis 101) et de renderers (1). Pour le click sur le bouton, la nouvelle ligne n'est pas visible (à priori, selon la taille de police par défaut), et, alors qu'on ajoute qu'une seule ligne, le renderer est réinvoqué pour toutes les lignes, sur mon environnement en tout cas).


    Aussi le renderer est déterminé en fonction des caractéristiques de son affectation. Tu procèdes à une affectation par type, donc la détermination est faite par rapport au type, qui lui est déterminé par le modèle, par la méthode getColumnClass().


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.FlowLayout;
    import java.util.Arrays;
    import java.util.concurrent.ThreadLocalRandom;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.concurrent.atomic.AtomicReference;
    import java.util.function.Supplier;
    import java.util.stream.Stream;
     
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.DefaultTableModel;
     
    public class JTableExemple2 {
     
    	public static void main(String[] args) {
     
    		JFrame frame = new JFrame();
     
    		String[] col = {"Col 1","Col 2"};
     
    		AtomicInteger idfactory = new AtomicInteger(1);
    		Supplier<Object[]> rowgenerator = ()-> new Object[] { idfactory.getAndIncrement(), ThreadLocalRandom.current().nextInt() };
    		Object[][] data = Stream.generate(rowgenerator).limit(3).toArray(Object[][]::new);
     
    		DefaultTableModel tableModel = new DefaultTableModel(data,col) {
    			public java.lang.Class<?> getColumnClass(int columnIndex) {
    				switch (columnIndex) {
    				case 0: {
    					return Integer.class;
    				}
    				default:
    					return super.getColumnClass(columnIndex);
    				}
    			};
    		};
    		JTable table = new JTable(tableModel);
     
    		AtomicInteger clickCount = new AtomicInteger();
    		String traceFormat = "Invocation getTableCellRendererComponent pour %1$s.%nNombre de lignes : %2$d.%n";
    		AtomicReference<String> formatRef = new AtomicReference<>(traceFormat);
    		String rowTraceFormat = "ligne %d, column %d, %s";
    		class MyRenderer extends DefaultTableCellRenderer {
    			public MyRenderer() {
    				setHorizontalAlignment(JLabel.RIGHT);
    			}
    			public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    				Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    				Object[] rowData = { tableModel.getValueAt(row, 0), tableModel.getValueAt(row, 1) };
    				System.out.printf(
    						formatRef.get(), 
    						String.format(rowTraceFormat, row, column, Arrays.toString(rowData)), 
    						table.getRowCount(), 
    						clickCount.get());
    				component.setForeground(Color.RED);
    				return component;
    			};
    		};
     
    		table.setDefaultRenderer(Integer.class, new MyRenderer());
     
    		JPanel panel = new JPanel(new BorderLayout());
    		panel.add(new JScrollPane(table));
    		frame.add(panel);
     
    		JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    		JButton button = new JButton("Ajouter une ligne");
    		button.addActionListener(e->{
    			clickCount.incrementAndGet();
    			String newtraceFormat = "Ajout d'une ligne %3$d.%n" + traceFormat;
    			formatRef.set(newtraceFormat);
    			tableModel.addRow(rowgenerator.get());
    		});
    		buttonPanel.add(button);
    		panel.add(buttonPanel,BorderLayout.SOUTH);
     
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setSize(600,400);
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
     
    	}
     
    }
    Invocation getTableCellRendererComponent pour ligne 0, column 0, [1, -1615650745].
    Nombre de lignes : 3.
    Invocation getTableCellRendererComponent pour ligne 1, column 0, [2, -152100304].
    Nombre de lignes : 3.
    Invocation getTableCellRendererComponent pour ligne 2, column 0, [3, -2145649358].
    Nombre de lignes : 3.
    
    Ici, le renderer est associé au type Integer. Malgré que toutes les données soient de type Integer, il n'est invoqué que pour la première colonne. En effet, pour la JTable, c'est la seule qui est de ce type.


    Citation Envoyé par hurukan Voir le message
    La première affiche des données on va dire brutes, la seconde affiche des données en provenance d'une autre Table de la base de données avec des données un peu plus précises.
    Comment ça "en provenance" ? Comment se fait la récupération et le transfert ?

    Citation Envoyé par hurukan Voir le message
    La première JTable fonctionne à merveilles, aucun soucis, bon c'est lent mais c'est peut-être ma manière d'approcher la chose qui n'est pas optimisée (le refraichissement du contenu suite à des ajouts n'est pas instantané en tous cas).
    Si le code de remplissage du modèle est du même genre que celui de la seconde JTable, celui que tu montres, il y a probablement des choses à revoir. Par ailleurs, je pense que tu n'utilises pas de SwingWorker pour la récupération des données de la base, ce qui introduit probablement un gel temporaire de l'UI.

    1. int CurrentRow=Donnees.length-1;.
      CurrentRow est la dernière ligne du tableau Donnees. C'est assez étrange par rapport au fait d'ajouter une ligne. La nouvelle ligne ajoutée a l'index Donnees.length normalement...
    2. Object saved[][]=new Object[Donnees.length][titres.length];.
      Le tableau instancié ne sert à rien. Il est immédiatement remplacé dans l'instruction suivante. Il consomme de la mémoire pour rien. Il charge le Garbage Collector pour rien. Comme on fait ça à chaque ajout de ligne, on consomme beaucoup de ressource pour rien. Pour 20 lignes, ce n'est pas très grave. S'il y en avait 10000, ça serait conséquent.
    3. saved=Donnees;.
      Autant écrire directement :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      Object[][] saved=Donnees;

    4. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      Donnees=new Object[Donnees.length+1][titres.length];
      for(int cpt=CurrentRow-1;cpt>=0;cpt--) Donnees[cpt]=saved[cpt];
      Ici aussi on créé plein de tableau de taille titres.length et on les remplace immédiatement après par de nouveaux tableau.
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      Donnees=new Object[Donnees.length+1][0];
      for(int cpt=CurrentRow-1;cpt>=0;cpt--) Donnees[cpt]=saved[cpt];
      A noter que ce code ne fait pas une copie, donc une modification de Donnees[a][b] modifie aussi saved[a][b].
      En plus tu copies toutes les lignes, sauf la dernière... c'est voulu ? Ta méthode s'appelle addRow, alors qu'elle remplace la dernière ligne.

      Pour faire une copie de tableau, il est préférable d'utiliser une méthode optimisée plutôt que de faire une copie ligne à ligne par for beaucoup plus lente.

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      int[][] tableau = new int[10][10];
      /* remplissage */
      int[][] nouveauTableau = Arrays.copyOf(tableau, tableau.length+1);
      nouveauTableau[tableau.length] = new int[10];
      Pour une vrai copie complète (donc où si modifie nouveauTableau[a][b] on ne modifie pas tableau[a][b], il faudra effectivement être obligé de faire une boucle :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      public static int[][] deepCopyOf(int[][] array) {
       
      		int[][] copy = new int[array.length+1][0];
       
      		int max=0;
      		for(int i=0; i<array.length; i++) {
      			copy[i] = new int[array[i].length];
      			System.arraycopy(array, 0, copy, 0, array.length);
      			max = Math.max(array.length, max);
      		}
      		copy[array.length]=new int[max]; // la taille de la dernière ligne est la taille de la plus grande ligne (en général les tableaux ayant des lignes de même taille, elle aura bien la même taille que les autres dans ce cas (si le tableau d'origine est vide, la taille sera 0)
      		return copy;
       
      }
      Mais pour gérer ce genre de choses, il vaut mieux utiliser une ArrayList. Elle gère en interne un tableau, mais limite le nombre de copies, en l'agrandissant par lot, plutôt qu'en ajoutant une ligne à chaque ajout. Le DefaultTableModel fait d'ailleurs ça en interne de cette manière, en utilisant un Vector, une sorte d'ArrayList synchronisée. Pour une implémentation de AbstractTableModel, il est préférable d'utiliser une ArrayList, ou une Collections.synchronizedList() selon les besoins d'interactivité de dynamisme. Et ça simplifie nettement le code.
    5. Donnees[CurrentRow][...].
      Au final, tu ajoutes les nouvelles données dans l'avant dernière ligne du nouveau tableau, la dernière ligne restant à null. Je ne sais pas comment est implémenté le modèle. Si getRowCount() retourne Donnees.length, cela doit provoquer des NullPointerException. Pourquoi cette ligne null ?
    6. fireTableDataChanged();Ceci indique que tout à changer dans le modèle, le nombre de lignes, de colonnes, les types, etc.
      fireTableRowsInserted(currentRow, currentRow); est plus efficient.


    Citation Envoyé par hurukan Voir le message
    Par contre la seconde JTable, elle, me pose soucis: j'ai 20 enregistrements à afficher dans cette table, et elle n'affichera jamais qu'une seule "row" (ligne).
    Avant de s'intéresser au renderer pour expliquer pourquoi une seule ligne est affiché, il faudrait s'intéresser au modèle.
    Montre-nous son code.

    Ensuite au sujet du renderer, il faut éviter de reconstruire la hiérarchie de composants à chaque invocation de getTableCellRendererComponent.
    On construit la hiérarchie dans le constructeur. On peut rendre visible ou pas certains composants. En général, le renderer est le même pour toutes les lignes d'une colonne. Si ce n'est pas le cas, on peut procéder par délégation.

    Aussi, il faut éviter de modifier des caractéristiques de la JTable, ou de ses colonnes dans le modèle.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(colonne==ma_tablemodel.COL) LaTable.getColumnModel().getColumn(colonne).setMinWidth(160);
    On fait ça une et une seule fois à la création.

    1. add(new JTextField((String)source))Si le renderer de la colonne est un JTextField, faire un renderer qui étend JTextField, pas renderer qui étend un panel avec un layout Flow.Center qui contient un JTextField. L'affichage doit être super bizarre : on honore même pas les largeurs de colonnes.


      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      import java.awt.BorderLayout;
      import java.awt.Component;
      import java.awt.FlowLayout;
       
      import javax.swing.JFrame;
      import javax.swing.JPanel;
      import javax.swing.JScrollPane;
      import javax.swing.JTable;
      import javax.swing.JTextField;
      import javax.swing.table.DefaultTableModel;
      import javax.swing.table.TableCellRenderer;
       
      public class JTableExemple3 {
       
      	public static void main(String[] args) {
       
      		JFrame frame = new JFrame();
       
      		String[] col = {"Col 1","Col 2"};
       
      		Object[][] data = {
      				{"machin","truc"},
      				{"bidule","chose"}
      		};
       
      		DefaultTableModel tableModel = new DefaultTableModel(data,col) {
      			public java.lang.Class<?> getColumnClass(int columnIndex) {
      				return String.class;
      			};
      		};
      		JTable table = new JTable(tableModel);
       
      		class MyRenderer extends JPanel implements TableCellRenderer {
      			private JTextField textfield;
      			public MyRenderer() {
      				super(new FlowLayout(FlowLayout.CENTER));
      				textfield = new JTextField();
      				add(textfield);
       
      			}
      			public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
      				textfield.setText((String)value);
      				return this;
      			};
      		};
       
      		table.setDefaultRenderer(String.class, new MyRenderer());
       
      		JPanel panel = new JPanel(new BorderLayout());
      		panel.add(new JScrollPane(table));
      		frame.add(panel);
       
      		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      		frame.setSize(600,400);
      		frame.setLocationRelativeTo(null);
      		frame.setVisible(true);
       
      	}
       
      }
      Nom : Capture.PNG
Affichages : 112
Taille : 7,2 Ko
      C'est plutôt bof, non ?
    2. int keyLevelP=Integer.valueOf((String)source);Passe par le modèle pour traiter les données dans le bon type. Le renderer doit avoir à faire le moins d'interprétation et de conversion. Une donnée directement classMatch.Levels.get(keyLevelP) dans le modèle. En plus ça permet d'avoir des tris et des filtres.
    3. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      this.getComponent(this.getComponentCount()-1).setFont(new Font("Liberation Mono", Font.BOLD, 12));
      .
      Ce genre de combine est à éviter.


    A noter que l'implémentation du renderer fait fi de toutes les notions de présentation standard, en cas de sélection, de focus, etc.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Merci pour la guidance ^^

    J'ai trouvé une autre solution... j'ai revu mon GUI. Maintenant mes deux tables ajoutent leurs nouvelles lignes.

    Je trouve que le scroll est buggé, je fais un mouvement vers le bas, la table défile avec une de ces lenteurs c'est juste pas possible, par contre le défilement aux boutons fonctionne bien.

    Par rapport au code, je me suis basé sur des exemples de vieux bouquins qui parlaient de JAVA 2 (!!) je réutilise toujours le même "template" pour la gestion des modèles de tables depuis 2011 ^^

    Concernant les manipulations des tableaux en 2D, je pense que si je ne fais pas comme cela, le modèle "perd" les données précédentes et n'affiche que la nouvelle ligne ajoutée... là aussi, "j'ai toujours fait comme ça"

    Par rapport au swing.worker je me rappelle avoir eu déjà des conseils à ce propos mais ce n'était pas dans le même cadre, il faudrait que je retrouve mes sources à ce propos.

    Merci des conseils, je me dépatouille, à la base c'était pour assurer une portabilité maximum que je me suis dit que j'allais recourrir à Java, et manque de bol pour moi, sous Windows ça ne marche pas ^^
    Du coup je suis plus très motivé: la ligne de commande proposée par netbeans pour lancer l'application ne fonctionne pas sous Windows j'ai à chaque fois Class Not Found et j'exècre tellement Windows que
    j'ai pas envie de commencer à chipotter.

  6. #6
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Merci pour la guidance ^^

    J'ai trouvé une autre solution... j'ai revu mon GUI. Maintenant mes deux tables ajoutent leurs nouvelles lignes.

    Citation Envoyé par hurukan Voir le message
    Je trouve que le scroll est buggé, je fais un mouvement vers le bas, la table défile avec une de ces lenteurs c'est juste pas possible, par contre le défilement aux boutons fonctionne bien.
    Forcément si le rendering prend du temps, ça se sent dans le scroll. Toutes ces manipulations de construction d'UI ne doivent pas être faits dans le processus de rendu. Aussi, le scroll peut être ajusté au besoin.

    Citation Envoyé par hurukan Voir le message
    Par rapport au code, je me suis basé sur des exemples de vieux bouquins qui parlaient de JAVA 2 (!!) je réutilise toujours le même "template" pour la gestion des modèles de tables depuis 2011 ^^
    Si ton code pour le renderer provient de ces bouquins, il faut changer de bouquin. C'est n'importe quoi.

    Citation Envoyé par hurukan Voir le message
    Concernant les manipulations des tableaux en 2D, je pense que si je ne fais pas comme cela, le modèle "perd" les données précédentes et n'affiche que la nouvelle ligne ajoutée... là aussi, "j'ai toujours fait comme ça"
    On peut très bien implémenter correctement le modèle sans perdre de données et sans avoir un code qui consomme trop de ressources.


    Citation Envoyé par hurukan Voir le message
    Par rapport au swing.worker je me rappelle avoir eu déjà des conseils à ce propos mais ce n'était pas dans le même cadre, il faudrait que je retrouve mes sources à ce propos.
    Lors du remplissage d'une JTable à partir d'une base de données, il faudrait systématiquement passer par un SwingWorker.

    Citation Envoyé par hurukan Voir le message
    Du coup je suis plus très motivé: la ligne de commande proposée par netbeans pour lancer l'application ne fonctionne pas sous Windows j'ai à chaque fois Class Not Found et j'exècre tellement Windows que
    j'ai pas envie de commencer à chipotter.
    Je ne sais pas ce que cette ligne de commande de NetBeans. Mais si il y a des ClassNotFound, c'est qu'il manque des bibliothèques dans le classpath.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 13/02/2013, 13h27
  2. QWidget::sizeHint() n'est appelé qu'une fois
    Par Invité dans le forum Qt
    Réponses: 12
    Dernier message: 31/05/2010, 12h02
  3. Réponses: 0
    Dernier message: 08/03/2010, 15h19
  4. Réponses: 1
    Dernier message: 22/12/2005, 17h28

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo