17 votes

Comment créer une action à partir de la sélection d'une ligne dans un NSTableView ?

Lorsque je sélectionne une ligne dans NSTableView il n'exécute pas le code de tableViewSelectionDidChange méthode. J'avais mis des points d'arrêt dans cette méthode et elle n'est même pas entrée dans la méthode.

Des idées ? Est-ce que j'ai oublié quelque chose dans mon initialisateur ?

PersonController.h

#import <Foundation/Foundation.h>

@interface Person : NSObject {
  IBOutlet NSTableView *personsTable;
  NSMutableArray *personsList;
  NSMutableArray *personCollection;

  IBOutlet NSTextField *selectedPersonName;
  IBOutlet NSTextField *selectedPersonGender;
@private

}

- (void)tableViewSelectionDidChange:(NSNotification *)aNotification;

@end

PersonController.m

#import "PersonController.h"
#import "Person.h"

@implementation PersonController

- (id)init
{
    self = [super init];
    if (self) {
        personsList = [[NSMutableArray alloc] init];
        Person *person = [[Person alloc] init];

        // Create person 1
        person.name = @"Bob";
        person.gender = @"male";

        // Append to array
        [personsList addObject:person];
        [person release];

        // Create person 2
        person = [[Person alloc] init];
        person.name = @"Fred";
        person.gender = @"Unknown";

        // Append to array
        [personsList addObject:person];
        [person release];

        [personsTable reloadData];
    }

    return self;
}

- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
    return [personsList count];
}

- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    Person *person = [personsList objectAtIndex:row];
    NSString *identifier = [tableColumn identifier];

    return [person valueForKey:identifier];
}

- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
{
    NSInteger selectedRow = [personsTable selectedRow];
    if (selectedRow == -1)
    {
        // these should be localized, but use string constants here for clarity
        [selectedPersonName setStringValue:@"No selection"];
        [selectedPersonGender setStringValue:@"No selection"];
    }
    else
    {
        Person *selectedPerson = [personCollection objectAtIndex:selectedRow];

        [selectedPersonName setStringValue:[selectedPerson name]];
        [selectedPersonGender setStringValue:[selectedPerson gender]];
    }
}

- (void)dealloc
{
    [super dealloc];
}

@end

27voto

Coderama Points 1955

Donc le problème ici était que j'essayais d'utiliser le tableViewSelectionChange pour déclencher un événement lorsqu'une ligne de la NSTableColumn a été cliquée. Comme je n'ai pas réussi à faire fonctionner cette méthode, j'ai adopté une autre approche, qui consistait à créer un fichier de type IBAction et le lier au NSTableView. J'ai constaté que cela fonctionne bien.

Pour ce faire, j'ai fait ce qui suit :

  1. Borrar - (void)tableViewSelectionDidChange
  2. Créer une IBAction
  3. Dans le fichier XIB, créez un Received Actions Lien entre l'IBAction et le NSTableView, dans l'inspecteur de connexion du NSTableView, sous "action envoyée", il y a une action "sélecteur", connectez ce "sélecteur" avec l'IBAction que vous voulez déclencher.

Voici l'IBAction dans PersonController.m

- (IBAction)columnChangeSelected:(id)sender
{
    NSInteger selectedRow = [personsTable selectedRow];

    if (selectedRow != -1) {
        NSLog(@"Do something with selectedRow!");
    }
    else {
        // No row was selected
    }
}

4voto

Andrew Points 4419

Pour développer la réponse de Coderama, l'équivalent en code est :

tableView.target = self;
tableView.action = @selector(tableViewClicked:);

puis implémenter la méthode dans la même classe :

- (void)tableViewClicked:(id)sender {
    // This will return -1 if the click did not land on a row
    NSLog(@"tableView.clickedRow = %ld", tableView.clickedRow);

    // This will return -1 if there is no row selected.
    NSLog(@"tableView.selectedRow = %ld", tableView.selectedRow);
}

La vue tableau appellera sa méthode d'action sur la cible que vous avez définie chaque fois que la vue est cliquée. Cela vous permettra de savoir chaque fois qu'une ligne est sélectionnée, même si elle l'est déjà.

3voto

Maor Points 1266

Solution en Swift 3 pour la plupart des événements :

Dans le contrôleur de vue Tableview :

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.target = self
    tableView.action = #selector(tableViewDidClick)
}

func tableViewDidClick(){
    let row = tableView.clickedRow
    let column = tableView.clickedColumn
    let unselected = -1

    if row == unselected && column == unselected{
        tableViewDidDeselectRow()
        return
    }else if row != unselected && column != unselected{
        tableViewDidSelectRow(row)
        return
    }else if column != unselected && row == unselected{
        tableviewDidSelectHeader(column)
    }
}

private func tableViewDidDeselectRow() {
    // clicked outside row
}

private func tableViewDidSelectRow(_ row : Int){
    // row did select
}

private func tableviewDidSelectHeader(_ column : Int){
    // header did select
}

2voto

Martin Hering Points 248

Assurez-vous que l'instance de PersonController est connectée à personsTable en tant qu'instance de délégué . Je ne sais pas comment vous avez créé le NSTableView, mais si vous utilisez Nibs, vous pouvez définir le délégué dans Interface Builder. Sinon, vous pouvez ajouter [personsTable setDelgate:self] dans le init méthode et [personsTable setDelegate:nil] dans le dealloc méthode.

Aussi, vous êtes qui fuit Liste des personnes. Ajouter [personsList release] à votre méthode de délégation.

2voto

user88975 Points 1318

Pour les autres qui rencontrent ce problème : une autre raison pour laquelle ce délégué n'est pas appelé pourrait être que la ligne est déjà sélectionnée. Il ne sera donc pas notifié à moins qu'une nouvelle sélection soit faite. Si vous voulez toujours être en mesure de recevoir des notifications à chaque clic, désélectionnez toutes les lignes une fois que vous êtes notifié.

Maintenant, cela va faire 2 appels à votre délégué, un pour être sélectionné et l'autre pour être désélectionné. Le deuxième appel n'est pas nécessaire, donc ajoutez une condition au dessus pour vérifier la présence de l'option [tableView selectedRow] ce qui donnerait -1 lorsqu'aucune ligne n'est sélectionnée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X