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
-
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')
-
As your Player is an ui.View, it needs to be presented to be visible.
-
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 callwhite = 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
-
@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:
- do it at the piece (Player) level and, if needed, use ui.convert_point() to convert from piece coordinates to board coordinates, or
- set touch_enabled = False on the piece to make it "transparent" to touches.
-
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')
-
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!
❤