Fenster / Views bei größeren Projekten organisieren + Verändern der Elemente aus Xcode (z.B. NSTableView)

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Jetzt möchte ich, dass das TableView unter einem NSTextField auftaucht und die Eingabevorschläge anzeigt.
    Man soll nur die Eingaben aus dem TableView übernehmen können. Angaben welche von den Vorschlägen im NSTableView abweichen, sollen nicht angenommen werden.
  • Ich verstehe überhaupt nicht wie ich die Sache rangehen soll. Soll ich delegates benutzen ?

    Hier ist mein Code für das TableView:

    Quellcode

    1. -(NSInteger) numberOfRowsInTableView:(NSTableView *)tableView{
    2. NSMutableArray* a=[[NSMutableArray alloc] initWithObjects:@"ABC",@"DEF",@"GHI", nil];
    3. return [a count];
    4. }
    5. -(id) tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{
    6. NSMutableArray* b=[[NSMutableArray alloc] initWithObjects:@"ABC",@"DEF",@"GHI", nil];
    7. return [b objectAtIndex:row];
    8. }
    Es ist in einer NSViewController Klasse geschrieben.

    Und ich verstehe den nächsten Schritt nicht. Schreibe ich in diese beiden Funktionen das "Hidden" ? Schreibe ich es in viewDidLoad oder in awakeFromNib ?

    Wie sage ich es dem TableView, dass er unter einem bestimmten NSTextField bleiben soll, egal wo ich es verschiebe ? Und es soll nur erscheinen wenn man tippt.

    Hier mal eine kleine Skizze wie ich mir das vorstelle:


    ---------------------------------/
    NSTextField /
    ---------------------------------/
    /
    /
    NSTableView mit /
    Vorschlagen /
    -Vorschlag 1 /
    -Vorschlag 2 /
    -Vorschlag 3 /
    --------------------------------/

    Der untere Teil, also das NSTableView soll nur erscheinen wenn man in den oberen Teil, also das NSTextField etwas tippt.
  • dass es erscheint oder wieder verschwindet regelst du eben in der delegate des textfields (du willst es ja nur haben wenn getippt wird, also dann setHidden:NO, nachher sobald es wieder verschwinden soll (eventuell durch timer oder was auch immer) eben wieder auf setHidden:YES.

    die daten der table erstellt man nicht in den datasource-methoden aber ich denke mal dass das nur ein test hier ist für dich.

    mit AutoLayout kannst du die tabelle ja direkt unter das textfield pappen und ein gemeinsames leading und trailing geben und eine höhe definieren.

    mach doch eins nach dem anderen und nicht alles auf einmal.

    sobald du alle einzelpunkte geschafft hast, kannst du versucehn es zu vereinen.
  • Hallo,

    Ich mache gute Fortschritte. Nun habe ich eine "Delegate-Klasse" erstellt und sie dem NSTextField als Delegate vermittelt. Anbei mein Code:

    Delegate_Klasse.h

    Quellcode

    1. #import <Foundation/Foundation.h>
    2. #import <Cocoa/Cocoa.h>
    3. @interface Delegate_Klasse : NSTextField <NSTextFieldDelegate>{
    4. IBOutlet NSTableView* table1;
    5. IBOutlet NSScrollView* View;
    6. }



    Delegate_Klasse.m

    Quellcode

    1. #import "Delegate_Klasse.h"
    2. @implementation Delegate_Klasse
    3. - (void)controlTextDidChange:(NSNotification *)obj{
    4. [table1 setHidden:NO];
    5. View.hidden = NO;
    6. NSLog(@"Text hat sich geändert");
    7. }
    8. -(void) controlTextDidEndEditing:(NSNotification *)obj{
    9. [table1 setHidden:YES];
    10. View.hidden = YES;
    11. }
    Alles anzeigen
    Dann hatte ich das Problem, dass das NSTableView immer angezeigt wurde. Dies war die Lösung:


    Quellcode

    1. - (void)viewDidLoad {
    2. [super viewDidLoad];
    3. [table1 setHidden:YES];
    4. VIEW2.hidden = YES;

    Nun möchte ich eine andere Delegate Methode schreiben. Das TableView soll erscheinen, sobald der Benutzer das TextFeld anklickt. Ich habe herausgefunden, dass man hierzu die Methode "-(void)mouseDown:(NSEvent*) theEvent" verwenden kann. Jedoch scheint sie bei mir nicht zu funktionieren. Das einfache Beispiel lässt nichts in der Konsole erscheinen:


    Quellcode

    1. -(void)mouseDown:(NSEvent*) theEvent {
    2. NSLog(@"ABC");
    3. }
  • also

    1. du musst dafür nicht eine eigene klasse schreiben, du kannst auch deine aktuelle klasse als delegate verwenden
    2. klassen- und variablen namen sind sehr schlecht gewählt
    3. warum verwendest du einmal die eine schreibweise setHidden:YES und einmal die andere .hidden = YES?
    4. du musst nur die scrollview auf hidden setzen oder nicht denn die enthält den tableview. dafür brauchst du aber kein eigenes outlet denn du kommst per tableview.enclosingScrollView daran.
    5. dass das scrollview und tableview anfangs nicht sichtbar ist kannst du auch im IB einstellen (dort gibt es eine checkbox für hidden).
    6. mouseDown ist keine delegate sondern eine methode welche du in einer subclass überschreiben kannst. also subklasse erstellen und überschreiben. in deinem fall aber besser becomeFirstResponder überschreiben.
  • Hallo,

    1. Ich habe für das NSTextField eine eigene Klasse geschrieben, da ich 2 NSTextFields auf dem Storyboard habe, die zu unterschiedlichen Zeiten (also wenn auf die Textfelder geklickt wird)
    einen NSTableView unter sich aufklappen sollen. Wenn ich 2 NSTextFields habe, jedoch nur eine Delegate Klasse (also sich selbst) dann erscheinen beide NSTextFields. Das möchte ich nicht. Gibt es einen Weg, 2 Delegate Methoden zu implementieren und sie anschließend den NSTextFields zuweisen ?

    2. Warum sind die Namen schlecht gewählt ? Der Compiler muss doch nur die Unterscheide erkennen ? Oder meinst du, dass die Namen für den Programmierer verwirrend sind ?

    3. Ich habe beide Methoden aktualisiert. Nun steht dort: [View setHidden:YES]; bzw. [View setHidden:NO];

    4. Das Outlet habe ich gestrichen. Es funktioniert auch ohne.

    5. Wunderbar ;) Ich habe sie gefunden und angewendet. Der nun überflüssige Code wurde auch gestrichen ;)

    6. Hier liegt mein Verständnisproblem. Ich habe (meiner Meinung nach) eine Klasse von NSTextField überschrieben, aber der Code wird trotzdem nicht aufgerufen.
    Ich habe in die "Delegate_Klasse.m" folgende Funktion eingefügt:

    Quellcode

    1. -(void)mouseDown:(NSEvent *)theEvent{
    2. NSLog(@"Maus hat Sollkontofeld angeklickt");
    3. }
    Leider wird es nicht aufgerufen ;(

    Vielen Dank für deine Hilfe ! Ich lerne hier wirklich viel !
  • 1. du kannst in den delegate-methoden jeweils rausfinden um welches text-field es geht.

    2. weil es bestimmte regelen gibt. zb sollte man englische namen verwenden, klassen beginnen mit großbuchstaben, variablen mit kleinbuchstaben, dazu wird CamelCase verwendet...

    6. du hast hier eine eigene delegate-klasse. das ist ganz was anderes als eine subclass. ergoogle dir ein tutorial wie man eine subclass erstellt und diese im IB zuweist (es fehlen aber grundlagen welche du dir aneignen solltest wenn du den unterschied nicht kennst).
  • Es wird langsam ;)

    2. Ich werde zukünftig versuchen diese Regelung zu beachten. So habe ich den NSScrollView z.B. schon in "viewForNSTableView" umbenannt.

    6. Jetzt habe ich eine Subclass für das NSTextField erstellt und das Feld dieser Klasse zugeordnet im identity inspector. Die Ausgabe "ABC" in der Konsole funktioniert auch, nur leider wird das TableView nicht angezeigt. Hier ist mein Code:

    showField1.h

    Quellcode

    1. #import <Cocoa/Cocoa.h>
    2. @interface showField1 : NSTextField{
    3. IBOutlet NSScrollView* scrollViewForNSTable;
    4. }
    5. @end

    showField1.m

    Quellcode

    1. #import "showField1.h"
    2. @implementation showField1
    3. - (void)drawRect:(NSRect)dirtyRect {
    4. [super drawRect:dirtyRect];
    5. // Drawing code here.
    6. }
    7. -(void) mouseDown:(NSEvent *)theEvent{
    8. NSLog(@"ABC");
    9. [scrollViewForNSTable setHidden:NO];
    10. }
    11. @end
    Alles anzeigen
  • Entschuldigung ich verstehe das nicht.

    1. Warum ist der Name schon wieder schlecht ? Ich habe im "scrollViewForNSTable" und im "showField1.h" das CamelCase verwendet. Ist der Name entscheidend für die Funktionalität des Programms ?

    2. Ich möchte, dass Auftreten des TableViews ändern. Ich habe beschlossen, dass das TableView bereits beim anklicken auftauchen soll. Deshalb möchte ich die Methode mouseDown verwenden. Wenn man das NSTextField anklickt, so erscheint auch der Text "ABC" in der Konsole. Somit finde ich, dass diese Methode geeignet ist.

    3. Wie kann ich in einer anderen Klasse die Subklasse vom NSTextField verwenden ?
  • 1. ich sagte doch bereits dass klassennamen mit großbuchstaben beginnen. auch sollten sie erklären um was es geht. also zb MyExtendedTextField

    2. nein möchtest du nicht. denn du möchtest die tableview sehen sobald das textfeld den fokus bekommt. das kann durch mouse-down passieren, aber auch per tab/enter drücken oder programatisch. also doch das was ich dauernd gesagt habe.

    3. du hast es nicht verstanden oder? du sollst in der subclass an die datasource eine info schicken dass der sender jetzt firstresponder ist. dort drin setzt du dann die table auf sichtbar etc...
  • Beim besten Willen. Ich verstehe es einfach nicht. Das "showField1" ist einer Subklasse von "NSTextField". Wenn ich die Methode "-(BOOL)becomeFirstResponder" in der .m Datei des showField1 überschreibe, dann erscheint auch der Text "ABC" in der Konsole. Das TextField im Interface ist auch als "showField1" eingetragen. Das Delegate ist auf den showField1 gesetzt.
    Also funktioniert die Methode "-(BOOL)becomeFirstResponder" schon mal, bzw. sie wird aufgerufen wenn man den Fokus auf das TextField setzt.

    Bis jetzt versteh ich, dass die Methode "-(BOOL)becomeFirstResponder" auch erfolgreich ausgeführt wird, da in der Konsole der Text erscheint, wenn man auf das NSTextField klickt bzw. es über Tab anwählt. Nur leider werden graphische Elemente nicht angesteuert. Ich habe es mit dem "[scrollViewForNSTable setHidden:YES];" versucht. Auch wenn ich ein "Label" im Interface platziere und den Befehl in den "becomeFirstResponder" schreibe: [Label setStringValue:@"AAAAAAA"]; wird er nicht ausgeführt. Dabei ist das Label (also das NSTextField) mit der Klasse verbunden.