Afficher/rafraà®chir une NSView en cliquant sur bouton

6ix6ix Membre
00:51 modifié dans API AppKit #1
Salut tout le monde,

Je suis relativement débutant avec cocoa, et là  je dois dire que je ne trouve nulle part ce que je voudrais...

En fait, j'ai une sous-classe de NSView, qui dessine plusieurs segments regroupés dans une liste; il est possible depuis la GUI de définir le nombre de segments, puis il faut cliquer sur un bouton pour construire et afficher la View.

Je ne trouve aucun exemple, tuto, discussion,... sur le sujet, et cela me serait bien utile, car j'ai  quelques petits problèmes!

Du style:
- la méthode drawRect est (si j'ai bien compris) appelée dès l'ouverture de l'application; comment faire pour qu'elle ne le soit qu'au clic sur le bouton (pour n'afficher la vue qu'à  ce moment-là )?
- je rencontre des difficultés pour faire le lien entre la classe controller et la sous-classe de view; la classe controller contient la méthode draw() appelée au clic du bouton qui récupère le nbre de segments et rafraà®chit ensuite la View, qui a besoin dans drawRect du nombre de segments

Je le fais en Java, mais aucun problème si les exemples ou tutos sont en Obj-C (j'adapterai...). Toute aide sera la bienvenue!

Réponses

  • BruBru Membre
    00:51 modifié #2
    dans 1159728979:

    - la méthode drawRect est (si j'ai bien compris) appelée dès l'ouverture de l'application; comment faire pour qu'elle ne le soit qu'au clic sur le bouton (pour n'afficher la vue qu'à  ce moment-là )?


    Non, drawRect est appelé à  chaque fois que la vue nécessite un réaffichage.
    Tu peux "manuellement" forcer le réaffichage de cette vue via la méthode setNeedsDisplay(true).
    Donc en mettant cette méthode dans le code de ton bouton, ça rafraà®chira la vue.


    dans 1159728979:

    - je rencontre des difficultés pour faire le lien entre la classe controller et la sous-classe de view; la classe controller contient la méthode draw() appelée au clic du bouton qui récupère le nbre de segments et rafraà®chit ensuite la View, qui a besoin dans drawRect du nombre de segments


    Normalement, tu devrais avoir un outlet entre ton contrôleur et ton custom-view. C'est ça le lien.

    .
  • 6ix6ix Membre
    octobre 2006 modifié #3
    dans 1159731119:

    Normalement, tu devrais avoir un outlet entre ton contrôleur et ton custom-view. C'est ça le lien.


    Oui effectivement, et j'en ai un. Il faudrait que je développe un peu plus, alors voilà  mon code, avec les 2 classes en question:

    <br />public class MazeController {<br /><br />&nbsp; &nbsp; public NSPopUpButton cellForm; /* IBOutlet */<br />&nbsp; &nbsp; public NSTextField cols; /* IBOutlet */<br />&nbsp; &nbsp; public NSView mazeView; /* IBOutlet */&nbsp;  [b]&lt;-- ma NSView[/b]<br />&nbsp; &nbsp; public NSTextField randSeed; /* IBOutlet */<br />&nbsp; &nbsp; public NSTextField rows; /* IBOutlet */<br />	<br />	// Initialisation avant affichage<br />	public void awakeFromNib() {<br />		...<br />	}<br />	<br />	// Génère le dessin<br />&nbsp; &nbsp; public void draw(Object sender) { /* IBAction */<br />		// Valeurs<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  int _rows = rows.intValue();<br />		int _cols = cols.intValue();<br />		long _randSeed = (long) randSeed.doubleValue();<br />		int _cellForm = cellForm.indexOfSelectedItem();<br /><br />		Maze maze = new Maze(_cols, _rows, _cellForm);<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  Drawing drawing = new Drawing();<br />		maze.destroyWalls(_randSeed);<br />		drawing = maze.draw();<br />		<br />		mazeView.setModel(drawing);&nbsp; [b]&lt;-- me renvoie une erreur[/b]<br />		mazeView.setNeedsDisplay(true);	// Appelle drawRect<br />&nbsp; &nbsp; }<br />}<br />
    


    Un clic appelle draw(), qui va modifier le modèle (voir classe ci-dessous) et réafficher la View

    <br />public class mazeView extends NSView {<br />	private Drawing model = new Drawing();<br />	<br />	public mazeView(NSRect rect) {<br />		super(rect);<br />	}<br />	<br />	public void drawRect(NSRect aRect) {<br />		NSBezierPath bezier = new NSBezierPath();<br />		<br />&nbsp; &nbsp; &nbsp; // Dessine chaque segment de la liste		<br />&nbsp; &nbsp; &nbsp; for (Segment segment : model.getSegments()) {<br />			bezier.moveToPoint(new NSPoint(segment.getP1().x(), segment.getP1().y()));<br />			bezier.lineToPoint(new NSPoint(segment.getP1().x(), segment.getP1().y()));<br />		}<br />		<br />		NSColor.blueColor().set();	// Contour bleu<br />		bezier.stroke();	// Dessine le contour<br />	}<br />	<br />	public void setModel(Drawing model) {&nbsp;  &lt;-- [b]modifie le modèle (utilisée par controller)[/b]<br />		this.model = model;<br />	}<br />}<br />
    


    J'ai une erreur "Cannot find symbol", c'est peut-être tout con, mais vu que j'ai pas trop l'habitude...

    Si vous connaissez des exemples ou tutos d'une vue réagissant au clic d'un bouton, je suis preneur, je n'en trouve pas, et ça évite les coups d'essais peu méthodiques!
  • BruBru Membre
    00:51 modifié #4
    Je ne sais pas ce qu'est la classe Drawing.

    Par contre, il faut dans le fichier de la classe MazeController "importer" la classe mazeView pour que le vérificateur Java puisse lier correctement la méthode setModel.
    Je n'ai jamais fait de Java sous cocoa, mais je pense qu'un import MazeController devrait suffir.

    Là  est une des limites de Java par rapport à  Objective-C : le dynamisme.
    Le même programme en Obj-C aurait compilé normalement (mais avec un warning indiquant que la méthode setModel n'est pas connue).

    .
  • 6ix6ix Membre
    00:51 modifié #5

    Je ne sais pas ce qu'est la classe Drawing.


    <br />import com.apple.cocoa.foundation.*;<br />import java.util.ArrayList;<br />import java.util.List;<br /><br />public class Drawing {<br /><br />&nbsp; &nbsp; // Valeurs min/max des 2 axes; permet mise à  l&#39;échelle automatique<br />&nbsp; &nbsp; private double minX = Float.POSITIVE_INFINITY;<br />&nbsp; &nbsp; private double maxX = Float.NEGATIVE_INFINITY;<br />&nbsp; &nbsp; private double minY = Float.POSITIVE_INFINITY;<br />&nbsp; &nbsp; private double maxY = Float.NEGATIVE_INFINITY;<br /><br />&nbsp; &nbsp; private ArrayList&lt;Segment&gt; segments = new ArrayList&lt;Segment&gt;();	// Liste des segments<br /><br />	public Drawing() {}<br /><br />&nbsp; &nbsp; // Ajoute une nouvelle ligne de segments au dessin<br />&nbsp; &nbsp; public void addSegment(NSPoint p1, NSPoint p2) {<br />&nbsp; &nbsp; &nbsp; &nbsp; segments.add(new Segment(p1, p2));	// Ajoute le segment<br /><br />		updateExtremas(p1);	// Met à  jour les coordonnées<br />&nbsp; &nbsp; &nbsp; &nbsp; updateExtremas(p2);<br />&nbsp; &nbsp; }<br /><br />&nbsp; &nbsp; // Retourne la liste des segments<br />&nbsp; &nbsp; public List&lt;Segment&gt; getSegments() {<br />&nbsp; &nbsp; &nbsp; &nbsp; return segments;<br />&nbsp; &nbsp; }<br /><br />&nbsp; &nbsp; // Contrôle si les coordonnées du point p sont en-dehors des extremums et les modifie si nécessaire<br />&nbsp; &nbsp; private void updateExtremas(NSPoint p) {<br />&nbsp; &nbsp; &nbsp; &nbsp; if (p.x() &lt; minX)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; minX = p.x();<br />&nbsp; &nbsp; &nbsp; &nbsp; if (p.x() &gt; maxX)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; maxX = p.x();<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; if (p.y() &lt; minY)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; minY = p.y();<br />&nbsp; &nbsp; &nbsp; &nbsp; if (p.y() &gt; maxY)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; maxY = p.y();<br />&nbsp; &nbsp; }<br />	<br />	// Retourne les min et max<br />&nbsp; &nbsp; public double getMinX() {<br />&nbsp; &nbsp; &nbsp; &nbsp; return minX;<br />&nbsp; &nbsp; }<br /><br />&nbsp; &nbsp; public double getMaxX() {<br />&nbsp; &nbsp; &nbsp; &nbsp; return maxX;<br />&nbsp; &nbsp; }<br /><br />&nbsp; &nbsp; public double getMinY() {<br />&nbsp; &nbsp; &nbsp; &nbsp; return minY;<br />&nbsp; &nbsp; }<br /><br />&nbsp; &nbsp; public double getMaxY() {<br />&nbsp; &nbsp; &nbsp; &nbsp; return maxY;<br />&nbsp; &nbsp; }<br />}<br />
    

    Drawing contient donc la liste de segments, Segment étant juste définie par deux points.

    Je n'ai jamais fait de Java sous cocoa, mais je pense qu'un import MazeController devrait suffir.

    C'est la 1e pour moi aussi en fait; j'essaie de refaire sous cocoa un programme crée avant en java pur.
    Le import n'est pas reconnu; j'ai essayé plusieurs trucs, mais il prend pas... Je n'ai pas défini de package, mais peut-être Xcode en crée un par défaut, qu'il faut ajouter avant le nom de la classe?

    Mais pourquoi devrais-je importer la classe MazeView, si ma mazeView est déjà  déclarée dans le MazeController (NSView mazeView;)? D'ailleurs, je ne rencontre pas de problème sur le mazeView.setNeedsDisplay(true);
  • 6ix6ix Membre
    00:51 modifié #6
    Finalement pour ce problème j'ai trouvé un moyen (est-ce l'idéal? je sais pas...).

    Dans MazeController, ma vue était déclarée comme ceci:
    NSView mazeView; //IB Outlet

    J'ai changé en:
    MazeView mazeView;, étant donné que MazeView hérite de NSView.
Connectez-vous ou Inscrivez-vous pour répondre.