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.


    set_needs_display() explained

    Pythonista
    beginners ui.view
    4
    6
    5092
    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.
    • sGiForceOne
      sGiForceOne last edited by

      Hello everybody

      I try to get to know pythonistas ui-module. I would like to code the ui manually, so far I refuse editors, because I think I'd miss some learning. And I need some. Please :)
      Anyway, my try is a "Merrills" -game. The board is the ui.View.
      I'm struggling to put the players pieces on it. Following is the shortened code as it is now. A Player-class should paint the bricks.
      I made it also ui.View because otherwise I couldn't make it shown.
      But that brings other problems, like that the touch from the root ui.View Board doesn't work anymore where Player exist etc.
      So, I should probably have another way. Because of this I'm asking generally how to use set_needs_display, I think there could be the trick.
      Hoping anyone understands somthing of my request :P
      Thank you very much in advance :)

      import ui
      
      class Player(ui.View):
      	def __init__(self, pos, color):
      		#self.bring_to_front()
      		print(pos)
      		self.xpos, self.ypos = pos
      		self.color = color
      	def draw(self):	
      		ui.set_color(self.color)
      		self.piece = ui.Path.oval(self.xpos, self.ypos, 50, 50)
      		self.piece.fill()
      
      class Board(ui.View):
      	def __init__(self):
      		self.height, self.width = 500, 500
      		self.background_color = 0.8, 0.7, 0.5 
      		self.name = "Mill"
      		self.positions = []
      		
      	def draw(self):
      		ui.set_color('black')
      		upper = int(self.width//2-50)
      		lower = int(self.width//4-25)
      		for x, size in zip(range(upper, -1, -lower), range(lower, 501, upper)):
      			if x == 0: 
      				x += 20
      				size -= 40
      			rect = ui.Path.rect(x, x, size, size)
      			rect.line_width = 10
      			rect.stroke()
      		def strokeLine(fx, fy, tx, ty):
      			line = ui.Path()
      			line.move_to(fx, fy)
      			line.line_to(tx, ty)
      			line.line_width = 5
      			line.stroke()					
      		strokeLine(self.width/2, 20, self.width/2, upper)
      		strokeLine(self.width/2, self.height-20, self.width/2, upper+lower)
      		strokeLine(20, self.height/2, upper, self.height/2)
      		strokeLine(self.width-20, self.height/2, upper+lower, self.height/2)
      
      	def touch_began(self, touch):
      		black = Player(touch.location, 'black')
      		self.add_subview(black)
      
      
      v = Board()
      v.present('sheet')
      
      1 Reply Last reply Reply Quote 0
      • cvp
        cvp last edited by

        As your Player is an ui.View, it needs to be presented to be visible.

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

          I'm sorry the code I've pasted is not a working one: But the ui.View (Player) is already "visible", it takes place in the upper left corner of the board. The board can't detect touch event at this place, and the touch events it can, won't show up because these coordinates are out of Players area.
          When I call

          white = Player((5,5) ,'white')
          v.add_subview(white)
          

          it shows up, visible. The call with touch.location doesn't work, my bad. I know :( So here I am and need another way, exactly because of this - Players view covers Board's view and the latter can't detect touch events anymore ¯\_(ツ)_/¯ I don't see how .present() helps, I even tried and it produces an error (view already presented.). Thank you

          mikael 1 Reply Last reply Reply Quote 0
          • mikael
            mikael @sGiForceOne last edited by

            @sGiForceOne, you should not need set_needs_display. present() is only needed once, for the underlying view, which I understand is your board.

            For catching the touches, you can either:

            1. do it at the piece (Player) level and, if needed, use ui.convert_point() to convert from piece coordinates to board coordinates, or
            2. set touch_enabled = False on the piece to make it "transparent" to touches.
            1 Reply Last reply Reply Quote 0
            • abcabc
              abcabc last edited by

              Here is the code to place the players. Moved the draw part of the player code to board and call "set_needs_display" in touch function.
              Also added code to find the coordinates of the players and to validate the positions.

              import ui
              from math import floor
              
              class Player(object):
                  def __init__(self, i, j, color):
                      self.i, self.j = i, j
                      self.xpos, self.ypos = self.i*60+5, self.j*60+5
                      self.color = color
                      self.piece = None
              
              class Board(ui.View):
                  def __init__(self):
                      self.height, self.width = 400, 400
                      self.background_color = 0.8, 0.7, 0.5 
                      self.name = "Mill"
                      self.toggle = True
                      self.positions = []
                      self.players = []
                      self.valid_positions = set([(0,0), (3,0), (6,0),
                                                  (1,1), (3,1), (5,1),
                                                  (2,2), (3,2), (4,2),
                                                  (0,3),(1,3),(2,3),(4,3),(5,3),(6,3),
                                                  (2,4), (3,4), (4,4),
                                                  (1,5), (3,5), (5,5),
                                                  (0,6), (3,6), (6,6)])
                      self.occupied = set()
                      
                  def draw(self):
                      ui.set_color('black')
                      for i in range(3):
                          rect = ui.Path.rect(i*60+20, i*60+20, (3-i)*120, (3-i)*120)
                          rect.line_width = 10
                          rect.stroke()
                      def strokeLine(fx, fy, tx, ty):
                          line = ui.Path()
                          line.move_to(fx, fy)
                          line.line_to(tx, ty)
                          line.line_width = 5
                          line.stroke()                   
                      strokeLine(200, 20, 200, 140)
                      strokeLine(200, 260, 200, 380)
                      strokeLine(20, 200, 140, 200)
                      strokeLine(260, 200, 380, 200)
                      for p in self.players:
                          ui.set_color(p.color)
                          p.piece = ui.Path.oval(p.xpos, p.ypos, 30, 30)
                          p.piece.fill()
              
                  def touch_began(self, touch):
                      x,y = touch.location
                      i = (floor(x)//60)
                      j = (floor(y)//60) 
                      if (i,j) in self.valid_positions and (i,j) not in self.occupied:
                          self.occupied.add((i,j))
                          color = 'black' if self.toggle else 'gray'
                          self.toggle = not self.toggle
                          player = Player(i, j, color)
                          self.players.append(player)
                          self.set_needs_display()
                      
              v = Board()
              v.present('sheet')
              
              
              1 Reply Last reply Reply Quote 0
              • sGiForceOne
                sGiForceOne last edited by

                Thank you very much!
                I wasn't checking for a few days, now I have even someone writing code for me, wasn't intended by request - @abcabc thank you very much for your effort, you shouldn't have :)
                also a big thank you @mikael! Made things clearer.
                I think I get it from here. As I'm already thanking, some heartful of thankyous also to @omz for the great Pythonista app!
                ❤

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post
                Powered by NodeBB Forums | Contributors