omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Child nodes are not anchored within their parent node

    Pythonista
    4
    7
    4798
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ccc
      ccc last edited by ccc

      The docs say that After a child is added to the node tree, it is positioned inside its parent’s coordinate system by setting its position attribute but clearly that is not the case... The BoardSquare at position 0, 0 is not placed at the 0, 0 pixel of its parent, the CheckerBoard.

      """
      CheckersScene contains:
          One CheckersBoard ShapeNode painted White contains:
              64 CheckersSquare ShapeNodes painted Red and Blue
      """
      
      from scene import *
      
      colorWhite = (1, 1, 1)
      colorRed   = (1, 0, 0)
      colorBlue  = (0, 0, 1)
      
      
      class CheckersScene(Scene):
          def setup(self):
              self.board = CheckersBoard(self)
      
          def squareAtCenterOfScreen(self):
              theMin = min(self.size.w, self.size.h)
              theRect = Rect(0, 0, theMin, theMin)
              theOffset = abs(self.size.w - self.size.h) / 2
              if self.size.w > self.size.h:
                  theRect.x = theOffset # landscape
              else:
                  theRect.y = theOffset # portrait
              return theRect
      
      
      class CheckersBoard(ShapeNode):
          def __init__(self, parent, inSquaresPerRow = 8):
              x, y, w, h = parent.squareAtCenterOfScreen()
              super().__init__(ui.Path.rect(x, y, w, h), fill_color='white', # anchor_point=(0, 0),
                               parent=parent, position=parent.bounds.center())
              # self.anchor_point = (0, 0)
              sq_size = w / inSquaresPerRow
              for i in range(inSquaresPerRow):
                  for j in range(inSquaresPerRow):
                      frame = (j * sq_size, i * sq_size, sq_size, sq_size)
                      theSquare = BoardSquare(self, frame, (i, j))
      
      
      class BoardSquare(ShapeNode):
          def __init__(self, parent, frame, inLocation):
              x, y, w, h = frame
              print(frame)
              super().__init__(ui.Path.rect(x, y, w, h), # anchor_point = (0, 0),
                               parent=parent, position=(x, y))
              # self.anchor_point = (0, 0)
              odd = (inLocation[0] + inLocation[1]) % 2
              self.fill_color = colorRed if odd else colorBlue
      
      
      run(CheckersScene())
      
      1 Reply Last reply Reply Quote 0
      • zipit
        zipit last edited by zipit

        Your CheckerBoard class is sitting at position=parent.bounds.center(), so I do not understand what you do mean with 'is not placed at the 0, 0 pixel', it seems to be working as intended expected. If you want the board to sit whithin screen bounds you have to choose your Board center somewhere in the lower left corner.

        1 Reply Last reply Reply Quote 0
        • ccc
          ccc last edited by ccc

          Please reread the question. Placing a Node within a Scene is not the problem. Placing a Node within a Node is the problem. CheckersBoard is properly placed in CheckersScene but the BoardSquares are not properly placed in CheckersBoard.

          1 Reply Last reply Reply Quote 0
          • omz
            omz last edited by

            @ccc The (0, 0) coordinate within a node is its center by default. You can set the anchor_point property to change that – it defaults to (0.5, 0.5).

            1 Reply Last reply Reply Quote 0
            • ccc
              ccc last edited by ccc

              @omz. Thanks but I tried that in four different locations in this code without success. Can you please provide me more precision on where in the code above to place anchor_point = (0, 0).

              I updated the code above to show the four places where I tried anchor_point = (0, 0). The first two moved the CheckersBoard offscreen :-( without moving the BoardSquares. The second two had no effect at all.

              1 Reply Last reply Reply Quote 0
              • JonB
                JonB last edited by JonB

                The confusing bit is that anchor_point not only defines how a node is placed within its parent, but also defines the origin of the node as children relate to it.

                This works fine if everybody's anchor_point is the same, but may be confusing when you want a node centered on the scene, but subnodes referenced from corner.

                For your code, the easiest fix is when the board is anchored at (.5,.5), to center it in the scene, you need to subtract size/2 from the square positions (anchored at 0,0)

                class BoardSquare(ShapeNode):
                    def __init__(self, parent, frame, inLocation):
                        x, y, w, h = frame
                        print(frame)
                        super().__init__(ui.Path.rect(0,0, w, h),
                                         parent=parent, position=(x,y)-parent.size/2,anchor_point = (0.0, 0.0))
                        odd = (inLocation[0] + inLocation[1]) % 2
                        self.fill_color = colorRed if odd else colorBlue
                

                Ideally, there would have been something like a "frame anchor" and "bounds anchor".

                1 Reply Last reply Reply Quote 1
                • ccc
                  ccc last edited by ccc

                  @JonB Thanks. Now it makes sense to me.

                  I think the approach that I will take is to just anchor_point all Nodes to (0, 0) because that seems to fit my brain better for complex layouts.

                  """
                  CheckersScene contains:
                      One CheckersBoard ShapeNode painted White contains:
                          64 CheckersSquare ShapeNodes painted Red and Blue
                  """
                  
                  from scene import *
                  
                  colorWhite = (1, 1, 1)
                  colorRed   = (1, 0, 0)
                  colorBlue  = (0, 0, 1)
                  
                  
                  class CheckersScene(Scene):
                      def setup(self):
                          self.board = CheckersBoard(self)
                  
                      def squareAtCenterOfScreen(self):
                          theMin = min(self.size.w, self.size.h)
                          theRect = Rect(0, 0, theMin, theMin)
                          theOffset = abs(self.size.w - self.size.h) / 2
                          if self.size.w > self.size.h:
                              theRect.x = theOffset  # landscape
                          else:
                              theRect.y = theOffset  # portrait
                          return theRect
                  
                  
                  class CheckersBoard(ShapeNode):
                      def __init__(self, parent, squares_per_row=8):
                          x, y, w, h = parent.squareAtCenterOfScreen()
                          super().__init__(ui.Path.rect(x, y, w, h), anchor_point=(0, 0),
                                           fill_color='white', parent=parent, position=(x, y))
                          sq_size = w / squares_per_row
                          for i in range(squares_per_row):
                              for j in range(squares_per_row):
                                  frame = (j * sq_size, i * sq_size, sq_size, sq_size)
                                  BoardSquare(self, frame, (i, j))
                  
                  
                  class BoardSquare(ShapeNode):
                      def __init__(self, parent, frame, inLocation):
                          x, y, w, h = frame
                          fill = colorRed if (inLocation[0] + inLocation[1]) % 2 else colorBlue
                          super().__init__(ui.Path.rect(x, y, w, h), anchor_point=(0, 0),
                                           fill_color=fill, parent=parent, position=(x, y))
                  
                  
                  run(CheckersScene())
                  
                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post
                  Powered by NodeBB Forums | Contributors