[Résolu] IBOutlet: Le menu de mon StatusItem ne s'affiche pas
sisopetron
Membre
Bonjour à tous,
Je continue l'exploration de cocoa et je suis confronté à un problème que je n'arrive pas à résoudre seul. C'est encore surement une bêtise mais voilà ...
J'arrive à afficher une icône dans la StatusBar. Par contre je n'arrive pas à binder le menu que j'ai créé à cette icône. Je vous laisse mon code pour que vous puissiez trouver où ça coince :
StatusIcon.h :
StatusIcon.m :
AppController.h :
AppController.m (une partie en tout cas ) :
Dans IB, j'ai relié ma classe StatusIcon au menu via son outlet statusMenu.
Pourquoi le menu ne s'affiche-t-il pas ? Ou est mon erreur ?
Merci de me donner un coup de main.
tata !
Je continue l'exploration de cocoa et je suis confronté à un problème que je n'arrive pas à résoudre seul. C'est encore surement une bêtise mais voilà ...
J'arrive à afficher une icône dans la StatusBar. Par contre je n'arrive pas à binder le menu que j'ai créé à cette icône. Je vous laisse mon code pour que vous puissiez trouver où ça coince :
StatusIcon.h :
@interface StatusIcon : NSObject {<br /> <br /> IBOutlet NSMenu *statusMenu;<br /> <br /> NSStatusItem *statusItem;<br /><br /> NSImage *statusImage;<br /> NSImage *statusAltImage;<br /><br />}<br /><br />- (void)afficheIcone;<br /><br />@end<br />
StatusIcon.m :
@implementation StatusIcon<br /><br />- (void)afficheIcone<br />{<br /> // création d'un statusItem de longueur NSSquareStatusItemLength, constante définie par NSStatusBar<br /> statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];<br /><br /> // on détecte où se trouvent les fichiers de l'application<br /> NSBundle *bundle = [NSBundle mainBundle];<br /> statusImage = [[NSImage alloc] initWithContentsOfFile: [bundle pathForResource: @"anniv_status" ofType: @"png"]];<br /> statusAltImage = [[NSImage alloc] initWithContentsOfFile: [bundle pathForResource: @"anniv_status_alt" ofType: @"png"]];<br /> [statusItem setImage: statusImage];<br /> [statusItem setAlternateImage: statusAltImage];<br /> <br /> [statusItem setHighlightMode: YES];<br /> [statusItem setMenu: statusMenu];<br /> [statusItem setToolTip: @"anniversaires"];<br /> [statusItem setEnabled: YES];<br />}<br /><br />- (void)dealloc<br />{<br /> [[NSStatusBar systemStatusBar] removeStatusItem:statusItem];<br /> [statusItem release];<br /> [statusImage release];<br /> [statusAltImage release];<br /> [super dealloc];<br />}<br /><br /><br />@end<br />
AppController.h :
#import <Cocoa/Cocoa.h><br />@class StatusIcon;<br />@class SplashScreen;<br /><br />@interface AppController : NSObject {<br /> <br /> StatusIcon *myStatusIcon;<br /> SplashScreen *mySplashScreen;<br /> <br />}<br />@end
AppController.m (une partie en tout cas ) :
#import "AppController.h"<br />#import "StatusIcon.h"<br />#import "SplashScreen.h"<br /><br /><br />@implementation AppController<br /><br />- (id)init<br />{<br /> if(self = [super init]){ <br /> //Ici le code pour initialiser l'objet ! <br /> }<br /> return self;<br />}<br /> <br />- (void)awakeFromNib<br />{<br /> // affichage du SplashScreen<br /> mySplashScreen = [[SplashScreen alloc] init];<br /> [mySplashScreen afficheSplashScreen];<br /> <br /> // affichage de l'icône de la statusbar<br /> myStatusIcon = [[StatusIcon alloc] init];<br /> [myStatusIcon afficheIcone];<br />}<br />
Dans IB, j'ai relié ma classe StatusIcon au menu via son outlet statusMenu.
Pourquoi le menu ne s'affiche-t-il pas ? Ou est mon erreur ?
Merci de me donner un coup de main.
tata !
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Et ça crée un fouilli dans lequel on (tu) se perd.
Si j'ai bien compris il y a une instance de StatusIcon dans le nib, dont l'outlet est bien connecté au menu.
Mais alors pourquoi le controlleur instancie-t-il une autre instance de StatusIcon ?
Cette instance là n'est pas dans le nib et son outlet vers le menu n'est pas connecté.
Evidemment, dans le NIB c'est la classe mère (si j'ose dire) qui apparait et à laquelle est relié le menu.
Ce n'est pas ainsi que je dois procéder ?
Si un reste au plus près de ta conception:
Merci de m'aider.
Penses aux NSWindows qu'y s'y trouvent souvent par exemple.
Tu les y configures en taille, type, contenu divers que tu agences au mieux possible etc..
Bref en y réfléchissant, tu vois bien que ce que tu configures dans ton XIB c'est pas La Classe NSWindow, mais Une Instance toute particulière avec des réglages pré-établis par tes soins dans le XIB.
Et, même si c'est, par exemple, un MyDocument.Xib, donc que, dans ce cas, plusieurs fenêtres jumelles peuvent être affichées dans ton appli, n'oublies pas qu'alors chaque fois (chaque document ici) le XIB est chargé en mémoire et instancie ta fenêtre selon tes choix.
Quand tu crée un objet perso dans un XIB (le petit cube bleu comme pour les WC ) il en est de même.
Tu donnes à IB le nom de la classe que tu dois instancier.
Au chargement du XIB l'instance de ta classe est crée, ET ses outlets connectés.
Du reste les outlets ne sont pas des variables de classe mais bien des variables d'instance.
Sinon tu parles d'un bordel si toutes les fenêtres (donc toutes les instances de NSWindow partageant l'unique 'outlet de classe') d'une appli devaient partager le même outlets "delegate" etc ... ;D
Une réponse de 14 lignes en 23 secondes ! :brule:
Oui, je n'avais pas pensé à ça.
Mais il me semble bien avoir fait ça : l'outlet de mon menu (IBOutlet NSMenu *statusMenu;) est déclaré dans la classe StatusIcon et relié à ma classe StatusIcon de façon à ce que chaque instance de ma classe StatusIcon possède un menu.
Or ce menu ne s'affiche pas. Pratiquement au vu du code que j'ai édité plus haut, où se trouve l'erreur ? J'ai remarqué que si je ne crée pas de classe StatusIcon mais que j'écris simplement dans AppController.m une méthode pour afficher mon icone (le même code que dans le StatusIcon.m), que je crée un outlet statusmenu dans le même AppController et que je relie dans IB mon menu et mon Outlet, le menu s'affiche bien quand je clique sur l'icone. Or je ne fais rien de bien différent que quand je crée ma classe StatusIcon.
Bref, tu l'auras remarqué, il y a encore quelque chose qui m'échappe dans tout cela.
L'outlet est une variable d'instance, il n'est pas "relié" magiquement à la classe.
Chaque instance de ta classe StatusIcon possède un outlet nommé statusMenu.
Mais seule l'instance du XIB (crée lors du chargement du XIB) verra son outlet pointer vers la bonne instance de NSMenu telle que t'en a spécifié les caractéristiques.
Et encore quand je dis pointer il faut préciser que ces "liens" qu'on trace sous IB entre un outlet et "sa cible" ne sont qu'une façon de dire ici au XIB "quand tu te chargera en mémoire et que tu aura instancié mon objet (cube bleu) de la classe StatusIcon et tous les autres objets du XIB (dont le NSMenu) tu donnera à l'outlet statusMenu de l'instance crée de StatusIcon la valeur de l'adresse mémoire de l'instance que tu viens de créer de la classe NSMenu."
Bref, tel que tu l'as fait, seule l'instance (de ta classe StatusIcon) crée "dans" le XIB a un outlet valide pointant vers le menu.
A partir de là c'est de cette instance StatusIcon là et pas une autre qu'il faut utiliser par la suite.
Or ton controlleur ne possède aucune référence vers cette instance.
Donc (première solution simple) tu crées dans ton controlleur un IBOutlet pointant sur ton cube bleu StatusIcon et le controlleur l'utilise pour configuer le statusMenu.
Alors que dans le code que tu donnes ton controlleur instancie "un autre exemplaire" de StatusIcon dont l'outlet reste non initialisé par le XIB et pour cause c'est pas le XIB qui l'a crée.
C'est plus clair ?
En attendant je vais m'instancier un bon verre de cocoa que je ferai pointer vers mon instance de bouche à moi (et pas celle de ma belle mère !)
(toutes les instances de verres de coca ont un outlet prévu pour pointer vers une bouche, mais ceux que j'instancie dans ma cuisine ne pointent jamais sur la bouche de ma belle mère ;D )
Mouais... en même temps t'as mis plus de 2h pour faire la suivante, alors bon... ;D
Eh bien voilà ! Ca marche parfaitement grâce à toi et à tes explications limpides.
Un grand merci !