Edition dans une table view comme iTunes

wiskywisky Membre
12:51 modifié dans API AppKit #1
Je veut arriver à  refaire le mode d'édition d'iTunes dans mon logiciel.
Donc comment faire pour:
2 click = action
1 click + un peut de temps + 1 click (comme sur le finder) = édition du champs

:why?:

Réponses

  • janvier 2006 modifié #2
    Tu envoies setDoubleAction: à  ta NSTableView avec comme argument le sélecteur qui sera appelé en cas de doubleclick.

    EDIT: ne marche qui les cellules ne sont pas éditables.
  • 12:51 modifié #3
    Voilà , et puis après pour l'édition ben si tu implémentes la méthode de la tableview qui permet d'éditer (je ne me souviens plus laquelle mais tu l'as implémenté pour la table de gauche ds ton movielibrary).
    Si ça marche pas peut-être que si jou un peu ça pourrait le faire :
    Je dès que j'ai cliqué sur une row du tableau, je lance un timer.
    Si je reclique dessus au bout de 1 seconde, tu lances l'action associée.
    Si je reclique dessus au bout de 2 ou 3 secondes, tu lances l'édition de la table.
    et si on reclique pas, il faudrait relacher le timer au bout de 4-5 secondes..

    Enfin bon ça c'est à  utilisé en cas d'urgence
  • wiskywisky Membre
    12:51 modifié #4
    Dans iTunes il semble que c'est un [tt]NSTextField[/tt] qui vient se positionner au dessus de la ligne sélectionné pour l'édition.
    Pour le timer, je le fait avec [tt]NSTimer[/tt]??
  • janvier 2006 modifié #5
    Oui mais attend  :o La solution de Renaud marche bien mais je sais pas si tu pourras éditer ta table ducoup.
    <br />[myTbView setDoubleAction:@selector(action:)];
    

    Après tu implémentes
    - (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
    

    Sans oublier de passer par le nib pour rendre les columns éditables

    [edit] viens de voir le post de Renaud modifié ! Donc c'est bien ce que je pensais, tu ne peux pas faire les 2 en même temps il me semblait bien avoir déjà  fait le test.
    Donc pour ma soluce qui n'est peut-être pas la meilleur :
    Ta tableview doit gérer le clique gauche souris (repérer quand et où tu auras cliqué).
    Pour cela utilse NSEvent. Une fois que tu auras cliqué, tu récupères la location ds ta fenêtre :
    locFMouse = [theEvent locationInWindow]; // locFMouse est du type NSPoint
    

    à  ce moment là , tu lances un timer qui dure 1 seconde, qui aura pour action : verifTimer, et qui sera répété (repeats:YES).
    Voici ce qu'invalideTimer fera :
    - (void)verifTimer:(NSTimer *)timer<br />{<br />seconds = seconds + 1; // seconds est un int defini ds le header (int seconds;)<br />if(seconds==5){<br />seconds = 0; // le temps est écoulé on remet à  0 et on tue le timer<br />[timer invalidate];<br />}
    

    Ensuite, si tu reclique une fois sur la row :
    - (void)mouseDown:(NSEvent *)theEvent<br />{<br />// Nouveau code ajouté<br />if(seconds==1||seconds==2)<br />[self doSumthin]; // Ben la tu executes l&#39;action que tu veux (celle du double-clique en fait)<br />else if(seconds&gt;2&amp;&amp;seconds&lt;5){<br />// ici tu rend l&#39;édition de la tableColumn possible (je te laisse te débrouiller il est un peu tard pour moi ...<br />}<br /><br />// Code d&#39;avant :p<br />locFMouse = [theEvent locationInWindow];<br />if(seconds==0) // on ne lance le timer que si les secondes sont à  0<br />[NSTimer scheduledTimerWithTimeInterval:1<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; target:self<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; selector:@selector(verifTimer:)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; userInfo:nil<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; repeats:YES];<br />}
    


    Bon par contre attention parce que là  au niveau du timer je t'ai donné en secondes et je te conseille d'utiliser float plutôt qu'integer à  cause de la rapidité de certains utilisateurs
    Un double clique comme on a l'habitude de faire doit durer un peu moins d'une secondes (donc d'après mon code les seconds seront encore à  0 donc ça lancera un 2eme timer et ça c'est pas bon du tout).

    Bon allez bon courage moi je suis KO
    :p
  • janvier 2006 modifié #6
    Plutôt que d'utiliser un timer pour savoir si tu as affaire à  un double clic, il est plus simple d'utiliser [theEvent clickCount];

    Sur cette base, on peut plutôt partir sur cette voie:
    EDIT: code incomplet, voir plus bas pour le bon.
    [tt]-(void)mouseDown:(NSEvent*)event {
    NSPoint p = [self convertPoint:[event locationInWindow] fromView:nil];

    BOOL flag = [event buttonNumber] == NSLeftMouseDown;

    int i = [self rowAtPoint:p];
    if (flag && i != [self selectedRow]) {
    [self selectRowsAtIndexes:[NSIndexSet indexSetWithIndex:i];
    } else if (flag && [event clickCount] == 1) {
    // la méthode pour éditer une cellule, faut bien que je te laisse un peu de boulot
    } else if (flag && [event clickCount] == 2) {
    [[self target] performSelector:[self doubleAction] withObject:self];
    } else {
    [super mouseDown:event];
    }

    }[/tt]

    Ce n'est pas la meilleure, mais au vu de l'heure, pô envie de trop réfléchir.
  • AliGatorAliGator Membre, Modérateur
    12:51 modifié #7
    Oui mais comme je te le disais renaud, là  ça distingue ces 3 cas là  :
    cas 1 : la ligne cliquée n'était pas sélectionnée. Alors on la sélectionne
    cas 2 : on a cliqué sur la ligne qui était déjà  sélectionnée. Alors on l'édite
    cas 3 : on a double-cliqué sur la ligne qui était déjà  sélectionnée. Alors on execute doubleAction pour faire une action sur cette ligne (sous iTunes, c'est jouer la chanson)

    Mais le hic c'est le cas 2 : avec ta solution, simple il est vrai, il y a un truc qui diffère de ce que fait iTunes : si on clique sur la ligne déjà  sélectionnée, on l'édite... mais même si on clique que 5 minutes après le premier clic qui a servi à  la sélectionner.
    Et puis si on sélectionne les lignes 1 et 2, puis qu'on désélectionne (avec la touche pomme) la ligne 2, et qu'on clique sur la ligne 1, alors on édite la ligne 1...

    Alors que iTunes, lui, c'est plutôt : si c'est un vrai double-clic (clics très rapprochés, ça c'est le système qui gère), alors doubleAction, mais si 2 clics un peu rapprochés (genre à  moins de 5-6 secondes d'intervalle), mais moins rapprochés qu'un double-clic pour autant, alors c'est édition. Et si les 2 clics sont élloignés dans le temps (plus de 6 secondes, disons), alors ça ne fait rien de plus.

    Cependant, la solution du NSTimer est clairement à  proscrire, en plus c'est bouffeur de ressources pour rien. Non, il suffit de noter dans une variable d'instance la valeur de l'heure courante (ou de l'uptime, ou ce genre de données temporelle). A chaque simple-clic, on compare l'uptime au moment du clic avec l'uptime enregistré du précédent clic, et on fait la différence. Bien plus simple et surtout moins consommateur qu'un NSTimer.
  • 12:51 modifié #8
    D'accord, mais tu conviendras qu'il aurait été plus court de formuler une réponse que d'expliquer le problème en long et en large, vu la simplicité de la solution. D'abord parce que ton exemple est mauvais: iTunes ne met pas de limite supérieure pour l'édition, et ensuite car il y avait un autre problème que tu aurais du relever: c'est que la condition où le clickCount valait 2 n'aurait jamais été réalisée, car avant d'atteindre le 2, il aurait fallu passer par le 1 et le passage par le 1 entraà®nait d'office la création d'un éditeur qui aurait pris le first responder.

    [tt]-(void)mouseDown:(NSEvent*)event {
    NSPoint p = [self convertPoint:[event locationInWindow] fromView:nil];

    BOOL flag = [event buttonNumber] == NSLeftMouseDown;
    NSTimeInterval secSinceLastClick = _previousClickDate - [event timeStamp];
    //_previousClickDate est une variable d'instance de type NSTimeInterval

    int i = [self rowAtPoint:p];
    if (flag && i != [self selectedRow]) {
    [super mouseDown:event]; //plus prudent que le précédent (pour la sélection multiple notamment)
    _previousClickDate = [event timeStamp];
    } else if (flag && [event clickCount] == 1 && secSinceLastClick > 0.5) {
    //0.5 est peut être un peu court: le double click peut être très lent suivant les prefs utilisateur
    // la méthode pour éditer une cellule, faut bien que je te laisse un peu de boulot
    } else if (flag && [event clickCount] == 2) {
    [[self target] performSelector:[self doubleAction] withObject:self];
    } else {
    [super mouseDown:event]; //optionnel en fait
    }

    }[/tt]

    PS: et en plus pour ton cas 2, tu t'es fais eu: il n'y a pas de limite de temps dans iTunes pour éditer le titre d'une chanson, par contre il faut cliquer sur le texte et sur une zone sans texte (ce qui n'est pas le cas d'une table standard).
Connectez-vous ou Inscrivez-vous pour répondre.