Comment fermer ma fenêtre ?
sisopetron
Membre
Bonjour à tous,
Je suis débutant en cocoa et je suis confronté à un problème qui, malgré des heures de lecture, résiste à toutes mes tentatives de résolution.
J'essaie d'afficher un splashscreen. Dans IB j'ai créé une fenêtre (NSWindow) supplémentaire dans mon fichier XIB principal. Dans xcode, j'ai créé une classe appelée SplashScreen que j'ai reliée à cette fenêtre. Voici l'implémentation de vette classe :
Toujours dans IB, j'ai associé cette fenêtre à une classe delegate appelée AppCotroller.
Mon problème est le suivant : bien que la case 'Visible at Launch' de ma fenêtre ne soit pas cochée, elle s'affiche d'emblée au démarrage de l'application. Est-ce mon code qui provoque cet affichage ? Et deuxième question : comment puis-je fermer cette fenêtre 'at runtime' ? Que dois-je écrire comme code pour y parvenir ?
Merci de votre aide.
Je suis débutant en cocoa et je suis confronté à un problème qui, malgré des heures de lecture, résiste à toutes mes tentatives de résolution.
J'essaie d'afficher un splashscreen. Dans IB j'ai créé une fenêtre (NSWindow) supplémentaire dans mon fichier XIB principal. Dans xcode, j'ai créé une classe appelée SplashScreen que j'ai reliée à cette fenêtre. Voici l'implémentation de vette classe :
@implementation SplashScreen<br /><br /><br />- (id)initWithContentRect:(NSRect)contentRect <br /> styleMask:(unsigned int)style<br /> backing:(NSBackingStoreType)bufferingType <br /> defer:(BOOL)flag<br />{<br /> // Détermine le centre de l'écran principal.<br /> NSScreen* mainScreen = [NSScreen mainScreen];<br /> NSRect screen = [mainScreen frame];<br /> NSPoint center = NSMakePoint(screen.size.width / 2, screen.size.height / 2);<br /> contentRect.origin.x = center.x - (contentRect.size.width / 2);<br /> contentRect.origin.y = center.y - (contentRect.size.height / 2);<br /> <br /> // Appel à la fonction init héritée, mais passe NSBorderlessWindowMask à la place <br /> // du style normal. Cela donne une fenêtre sans barre de titre ni bords.<br /> id window = [super initWithContentRect:contentRect<br /> styleMask:NSBorderlessWindowMask <br /> backing:bufferingType <br /> defer:flag];<br /> if (window)<br /> {<br /> // Fixe l'opacité de la fenêtre<br /> [window setOpaque:NO];<br /> <br /> // Impose une couleur claire au fond de la fenêtre (sans cela,<br /> // on aurait le fond normal d'OS X : des barres horizontales).<br /> [window setBackgroundColor:[NSColor colorWithDeviceWhite:1.0 alpha:0.0]];<br /> <br /> // Pas d'ombre à la fenêtre.<br /> [window setHasShadow:NO];<br /> <br /> // Place la fenêtre au dessus de toutes les autres. Même d'autres applications. <br /> // Tant qu'elle ne reste pas plus de 2 secondes au dessus des autres, l'utilisateur<br /> // ne s'en plaindra pas, il est cependant possible de choisir un autre niveau<br /> // comme le niveau application de façon à permettre à l'utilisateur de <br /> // continuer à utiliser l'ordinateur pendant que le programme charge. Voir la <br /> // documentation sur NSWindow pour la description d'autres niveaux d'affichage.<br /> [window setLevel:NSFloatingWindowLevel];<br /> }<br /> <br /> return window;<br />}<br />
Toujours dans IB, j'ai associé cette fenêtre à une classe delegate appelée AppCotroller.
Mon problème est le suivant : bien que la case 'Visible at Launch' de ma fenêtre ne soit pas cochée, elle s'affiche d'emblée au démarrage de l'application. Est-ce mon code qui provoque cet affichage ? Et deuxième question : comment puis-je fermer cette fenêtre 'at runtime' ? Que dois-je écrire comme code pour y parvenir ?
Merci de votre aide.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Ou est-ce que je mets cette instruction ? Si je fais
il me retourne un warning : window undeclared
Pratiquement comment je dois-je faire ? Et où dois-je mettre ce code ?
NB: Pardon si mes questions vous paraissent idiotes mais je suis super débutant.
Dans mon example, window est définie en variable d'instance (dans le .h). Mais ça dépend de comment tu déclares ta window, apparemment elle n'est déclarée que dans une seule méthode.
Dans ton cas, si SplashScreen est définie en tant de NSWindow, remplace window par self (qui renvoie donc à ta fenêtre) :
et évidemment ma fenêtre ne se ferme pas.
Comment l'a tu déclarée ?
Dans l'interface de mon SplashScreen.h il y a :
Comment la déclarer autrement ?
Alors où as-tu écris la suggestion d'apocaalypso ?
Dans l'implémentation de ton SplashScreen ?
Vu que tu veux mettre ça dans le didFinishLaunched, j'ai dans l'idée que t'as écris ça dans ton appDélagate ... non ?
Alors ton appDelegate doit garder un pointeur vers ton SplashScreen.
genre, dans le fichier de déclaration d'interface (.h) de ton AppDelegate:
Puis dans son implémentation (.m) tu mets le code qui ouvre la fenêtre , tu y mets la référence vers cette SplashScreen genre.
Tu te retrouves là avec une référence valide qui te permetra plus tard, dans le didFinishLaunching d'écrire:
J'ai encore une erreur :
Et je ne la comprends pas celle-là .
ça t'indique qu'il n'arrive pas à déterminer le type exacte de maSplashScreen.
ça arrive, par exemple, quand la déclaration indique un type (SplashScreen* ...) mais que dans l'implémentation on l'initialise avec un autre type (NSWindow*...)
A priori ça vient de là : id window = [super initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask
Dans ton initialisation tu appèles le super pour qu'il te renvoie ce qu'il sait faire (une NSWindow).
Nulle part tu lui demandes d'initialiser ton SplashScreen, tu renvoie ensuite la NSWindow ainsi crée comme résultat de l'initialisation de ta SplashScreen ... il est perdu.
Remplace tous les window par self
Tu veux bien y jeter un oeil ? Merci.
Si c'est du copier/collé de ton code, ça m'étonnerait qu'axakeFromNib soit appelé.
A moins que tu n'ai une méthode awakeFromNib qui appèle à son tour axakeFromNib ?
Une idée de comment je peux corriger ça ?
Copie-nous tout ton AppDelegate, ça sera plus simple.
Tu l'as dit
Voilà l'AppController :
Ne serait-ce pas plutôt dans IB que le problème se pose ? J'y ai définit la classe AppController comme delegate de ma fenêtre SplashScreen. Ne devrais-je pas créer un outlet de ma fenêtre SplashScreen ? Et si oui, qu'en faire ?
Merci de m'aider.
Surtout s'il pleut ;D
Avant tout faudrait que ton code ne soit pas juste du copié-collé de prototypes de méthodes.
Si tu ne défini pas contentRect, windowStyle, bufferingType, deferCreation ni screen ça risque pas de faire quoique ce soit.
Je crois surtout que tu devrais faire quelques tuto cocoa pour mieux appréhender l'ObjC avant tout, puis les frameWorks.
Même s'il y a pleins de commodités et d'automatismes dans les frameworks et qu'IB est un outil puissant pour gérer l'interface, y'a pas de magie non plus et faut tout de même maitriser un peu le code.
Je fais, je fais. Mais tu as raison, il y a un truc qui m'échappe là et j'essaie juste de comprendre.
Juste une petite question encore : contentRect, windowStyle, bufferingType, deferCreation sont définis dans la classe SplashScreen. Il faut que je les redéfinisse dans mon AppController ? Ne puis-je pas me contenter d'un
tout simple ?
Pour moi cette fenêtre doit apparaitre le plus tôt possible et disparaitre dès que l'application est chargé.
Voici un lien : http://wisky2.blogspot.com/2009/10/creer-une-fenetre-dattente-efficace-en.html
Ah merci, c'est très intéressant ça. Je m'y plonge.
Je vais suivre ta suggestion et essayer comme ça. Merci.
Cela t'évitera peu être d'autre déboire 8--)
J'ai cependant un warning qui manifestement n'empèche pas le splashscreen de d'afficher : à la ligne [splashScreen setDelegate:self]; j'ai : un warning qui me dit "class AppController does not implement the NSWindowDelegate protocol."
Tu peux m'expliquer la raison de ce warning ? Merci.
Merci pour ce lien. Si j'ai bien compris, setDelegate permet de définir un delegate pour une classe à la volée dans le code.
Dans le cas qui m'occupe ici, c'est à dire le code donné par wisky, cette ligne ([splashScreen setDelegate:self]; ) n'est pas indispensable au bon fonctionnement du programme : si on la commente la compilation et l'exécution se déroulent sans problème.
A quoi cela sert-il ici de définir un delegate alors ici ?
NB: je suis désolé si mes questions vous paraissent triviales : je suis une débutant au tout début du début de l'apprentissage de cocoa.
J'ai dans l'idée que ça fait bail que ça te démange de te lancer dans l'aventure
Dans ton cas ce n'est pas obligatoire. Je vais corriger ça sur mon blog !
Tout objet acceptant un delegate permet de le changer à la volé. Il faut cependant implémenter le protocole correspondant.
Le delegate permet à un objet d'envoyer des messages à un objet spécifié pour effectuer des opération lié à l'évènement cela évite de passer par le centre de notification. En tout cas je le vois comme ça 8--)
PS : N'hésite pas à laisser un message sur mon blog !
Comment as-tu deviné ?
A apocaalypso et wisky, merci pour vos explications. Je continue mon exploration de cocoa (si mon travail me laisse un peu de temps) et j'aurai dans peu de temps sûrement encore pleins de questions à vous poser sur ce forum.
A+