kivy: badly aligned widgets - layout
Example code fragment from a base class:
def build_extra_content(self):
grp = 'choice_dialog'
extra_content = GridLayout(cols=2)
lb_width = self.width - 2 * self.choice_height
for choice in self.choices:
cb = CheckBox(group=grp,
size_hint=(None, None), size=(self.choice_height, self.choice_height))
lb = Label(markup=True, text=choice, halign='left', valign='middle',
size_hint=(None, None), size=(lb_width, self.choice_height))
lb.texture_size = (lb_width, self.choice_height)
extra_content.add_widget(cb)
extra_content.add_widget(lb)
# TODO: check the checkbox when the label is touched.
def _lb_press(*args):
print(args)
cb.bind(on_touch_down=_lb_press)
return extra_content
The content is displayed in this dialog:
I have two questions. First: why the text is aligned to the center? I have already set absolute sizes for both the label and its texture size, and set halign='left'. But the text is still aligned to the center. Why?
Second: I wanted the labels to be clickable/touchable. E.g. the checkboxes should be selected by touching their corresponding labels. Whenever I click on a single label or checkbox, this is printed:
(<kivy.uix.checkbox.CheckBox object at 0x0B2C01B8>, <MouseMotionEvent button="left" device="mouse" double_tap_time="0" dpos="(0.0, 0.0)" dsx="0.0" dsy="0.0" dsz="0.0" dx="0.0" dy="0.0" dz="0.0" grab_current="None" grab_exclusive_class="None" grab_list="[]" grab_state="False" id="mouse3" is_double_tap="False" is_mouse_scrolling="False" is_touch="True" is_triple_tap="False" opos="(644.0, 379.0)" osx="0.503125" osy="0.47375" osz="0.0" ox="644.0" oy="379.0" oz="0.0" pos="(644.0, 379.0)" ppos="(644.0, 379.0)" profile="['pos', 'button']" psx="0.503125" psy="0.47375" psz="0.0" push_attrs="('x', 'y', 'z', 'dx', 'dy', 'dz', 'ox', 'oy', 'oz', 'px', 'py', 'pz', 'pos')" push_attrs_stack="[]" px="644.0" py="379.0" pz="0.0" shape="None" spos="(0.503125, 0.47375)" sx="0.503125" sy="0.47375" sz="0.0" time_end="-1" time_start="1507722998.229789" time_update="1507722998.229789" triple_tap_time="0" ud="{}" uid="3" x="644.0" y="379.0" z="0.0">)
(<kivy.uix.checkbox.CheckBox object at 0x0B5FC2D0>, <MouseMotionEvent button="left" device="mouse" double_tap_time="0" dpos="(0.0, 0.0)" dsx="0.0" dsy="0.0" dsz="0.0" dx="0.0" dy="0.0" dz="0.0" grab_current="None" grab_exclusive_class="None" grab_list="[]" grab_state="False" id="mouse3" is_double_tap="False" is_mouse_scrolling="False" is_touch="True" is_triple_tap="False" opos="(644.0, 379.0)" osx="0.503125" osy="0.47375" osz="0.0" ox="644.0" oy="379.0" oz="0.0" pos="(644.0, 379.0)" ppos="(644.0, 379.0)" profile="['pos', 'button']" psx="0.503125" psy="0.47375" psz="0.0" push_attrs="('x', 'y', 'z', 'dx', 'dy', 'dz', 'ox', 'oy', 'oz', 'px', 'py', 'pz', 'pos')" push_attrs_stack="[]" px="644.0" py="379.0" pz="0.0" shape="None" spos="(0.503125, 0.47375)" sx="0.503125" sy="0.47375" sz="0.0" time_end="-1" time_start="1507722998.229789" time_update="1507722998.229789" triple_tap_time="0" ud="{}" uid="3" x="644.0" y="379.0" z="0.0">)
(<kivy.uix.checkbox.CheckBox object at 0x0B5F3768>, <MouseMotionEvent button="left" device="mouse" double_tap_time="0" dpos="(0.0, 0.0)" dsx="0.0" dsy="0.0" dsz="0.0" dx="0.0" dy="0.0" dz="0.0" grab_current="None" grab_exclusive_class="None" grab_list="[]" grab_state="False" id="mouse3" is_double_tap="False" is_mouse_scrolling="False" is_touch="True" is_triple_tap="False" opos="(644.0, 379.0)" osx="0.503125" osy="0.47375" osz="0.0" ox="644.0" oy="379.0" oz="0.0" pos="(644.0, 379.0)" ppos="(644.0, 379.0)" profile="['pos', 'button']" psx="0.503125" psy="0.47375" psz="0.0" push_attrs="('x', 'y', 'z', 'dx', 'dy', 'dz', 'ox', 'oy', 'oz', 'px', 'py', 'pz', 'pos')" push_attrs_stack="[]" px="644.0" py="379.0" pz="0.0" shape="None" spos="(0.503125, 0.47375)" sx="0.503125" sy="0.47375" sz="0.0" time_end="-1" time_start="1507722998.229789" time_update="1507722998.229789" triple_tap_time="0" ud="{}" uid="3" x="644.0" y="379.0" z="0.0">)
Actually it doesn't matter where I click. Even if I click outside the GridLayout, always all labels will trigger the touch event. But why? I only want the one under my finger.
Thanks
First: why the text is aligned to the center? I
have already set absolute sizes for both the label and its texture
size, and set halign='left'. But the text is still aligned to the
center. Why?
You're setting texture_size, but you should set text_size instead.
Second: I wanted the labels to be clickable/touchable. E.g. the
checkboxes should be selected by touching their corresponding labels.
Whenever I click on a single label or checkbox, this is printed:
In Kivy every widget receive touch event. You should check if touch happened inside your label manually:
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
# The touch has occurred inside the widgets area. Do stuff!
pass
Here is the answer to your second question.
Note
By default, touch events are dispatched to all currently displayed
widgets. This means widgets receive the touch event whether it occurs
within their physical area or not.
In order to provide the maximum flexibility, Kivy dispatches the
events to all the widgets and lets them decide how to react to them.
If you only want to respond to touch events inside the widget, you
simply check:
Example
class ProjectSelectButton(Button):
def click_on_button(self, instance, touch, *args):
print(instance)
if self.collide_point(*touch.pos):
if touch.button == 'right':
print(self.id, "right mouse clicked")
elif touch.buttom == 'left':
print(self.id, "left mouse clicked")
return True
return super(ProjectSelectButton, self).on_touch_down(touch)
Related
Blitting an image in pygame immediately disappears after I release my mouse
def options(): options = True while options: for event in pygame.event.get(): win.fill(WHITE) win.blit(background, (0, 0)) ... # Blitting text and switch buttons options_x, options_y = pygame.mouse.get_pos() if event.type == pygame.QUIT: # Exit button pygame.QUIT() quit() elif event.type == pygame.MOUSEBUTTONDOWN: # Sound effect tuning if 470 > options_x > 390 and 220 > options_y > 185: # Checking if mouse click is on the ON SWITCH mouse_click.play() screen.blit(off_switch, (off_switch_x, off_switch_y)) pygame.mixer.stop() # But doesn't stop sound from playing when I quit options section # Music effect tuning elif 470 > options_x > 390 and 300 > options_y > 260: # Checking if mouse click is on the ON SWITCH mouse_click.play() screen.blit(off_switch, (off_switch_x, off_switch_y)) pygame.mixer.music.stop() # Interactive BACK button elif 90 > options_x > 42 and 75 > options_y > 25: mouse_click.play() options = False pygame.display.update() So this is a part of my HANGMAN game where I try to set up the OPTIONS section which allows you to configure the volume. The problem is in the "Music" and "Sound" effect tuning. Pressing on the ON SWITCH button for both "Music" and "Sound" will display the OFF SWITCH, but as soon as I release my mouse, they go back to their original state. The music stops, but not the sound effects (mouse clicks, plop sounds, etc...). I would like the image blitting to be saved, and the sounds effects to be stopped. How can I fix this?
You undo the blit in every loop. At the top I see code which clears\resets everything. win.fill(WHITE) win.blit(background, (0, 0)) .... You blit the change inside the event handler: screen.blit(off_switch, (off_switch_x, off_switch_y)) The event switch blit will be cleared at the next event loop (probably mouse move). Think of the game as a series of states. The code at the top of the loop should draw the current state of the game. for event in pygame.event.get(): win.fill(WHITE) win.blit(background, (0, 0)) if SwitchIsOn: screen.blit(on_switch, (on_switch_x, on_switch_y)) else: screen.blit(off_switch, (off_switch_x, off_switch_y)) .... The event handler should be used to change the game state. if 470 > options_x > 390 and 220 > options_y > 185: # Checking if mouse click is on the ON SWITCH mouse_click.play() SwitchIsOn = not SwitchIsOn # reverse switch position This will prevent your event changes from being cleared.
cannot set position of wx.frame on openbox
i am playing with wxPython and try to set position of frame: import wx app = wx.App() p = wx.Point(200, 200) frame = wx.Frame(None, title = 'test position', pos = p) frame.Show(True) print('frame position: ', frame.GetPosition()) app.MainLoop() even though print('frame position: ', frame.GetPosition()) shows the correct postion, the frame is shown in top left corner of screen. Alternatively i tried frame.SetPosition(p) frame.Move(p) without success. my environment: ArchLinux 5.3.13, python 3.8.0, wxpython 4.0.7, openbox 3.6.1 On cinnamom the code works as expected. How to solve this on openbox? edit 07,12,2019: i could set postion of a dialog in openbox config ~/.config/openbox/rc.xml: <application name="fahrplan.py" class="Fahrplan.py" groupname="fahrplan.py" groupclass="Fahrplan.py" title="Fahrplan *" type="dialog"> <position force="no"> <x>760</x> <y>415</y> </position> </application> i got name, class etc. from obxprop. x and y are calculated to center a dialog of 400 x 250 px on screen of 1920 x 1080 px. This static solution is not suitable for me. I want to place dynamically generated popups.
I had the same problem under Windows and played around with the style flags. With wxICONIZE sytle set active the window finally used the positioning information
The position is provided to the window manager as a "hint". It is totally up to the window manager whether it will actually honor the hint or not. Check the openbox settings or preferences and see if there is anything relevant that can be changed.
How can I draw a tree with TikZ using PyLatex?
I have a homework assignment where I need to generate a PDF file containing a tree image using Python 3 and LaTeX's tikz package. It'd be really helpful if someone has a simple sample code. I need to know how to create a child node. from pylatex import (Document, TikZ, TikZNode, TikZDraw,TikZCoordinate,TikZUserPath, TikZOptions) doc = Document() # add our sample drawings with doc.create(TikZ()) as pic: node_kwargs = {'align': 'center', 'shape' : 'circle','minimum size': '50pt', 'fill': 'black!20'} # create our test node box = TikZNode(text='My block', handle='box', options=TikZOptions('draw', 'rounded corners', **node_kwargs)) n_kw = {'shape' : 'circle', 'minimum size': '50pt', 'fill': 'black!20'} #I DONT KNOW HOW TO PUT A CHILD NODE !! box.child = TikZNode(text='My block 2', handle='box2', options=TikZOptions('draw', 'rounded corners', **node_kwargs)) pic.append(box) pic.append(box.child) doc.generate_pdf('tikzdraw', clean_tex=False)
Deriving boolean expressions from hand drawn logic gate diagrams with python OpenCv
Using tensorflow I identified all the gates, letters and nodes. When identifying all above components, it draws a rectangle box around each component. Therefore, in the following array it contains list of all the components detected. Each list is in the following order. Name of component X, Y coordinates of top left corner of rectangle X, Y coordinates of right bottom of rectangle Nodes (Black Points) are used to indicate a bridge over a line without crossing. Array of all above components. labels =[['NODE',(1002.9702758789062, 896.4686675071716), (1220.212585389614, 1067.1142654418945)], ['NODE',(1032.444071739912, 635.7160077095032),(1211.6839590370655, 763.4382424354553)],['M', (57.093908578157425,607.6229677200317),(311.9765570014715,833.807623386383)],['NODE', (344.5295810997486, 806.3690414428711), (501.8982524871826, 930.6454839706421)], ['Z', (21.986433800309896, 1327.9791088104248), (266.36098374426365, 1565.158670425415)], ['OR', (476.0066536962986, 574.401759147644), (918.3125713765621, 1177.1423168182373)], ['NODE', (333.50814148783684, 1058.0092916488647), (497.6142471432686, 1202.9034795761108)], ['K', (37.06201596558094, 870.0414619445801), (311.77860628068447, 1105.8665227890015)], ['AND', (665.9987451732159, 1227.940999031067), (1062.7052736580372, 1594.6843948364258)],['AND', (1373.9987451732159, 204.940999031067), (1703.7052736580372, 612.6843948364258)], ['NOT', (694.2882044911385, 260.5083291530609), (1027.812717139721, 450.35294365882874)], ['XOR', (2027.6711627840996, 593.0362477302551), (2457.9011510014534, 1093.9836854934692)], ['J', (85.69029207900167, 253.8458535671234), (334.48535946011543, 456.5887498855591)], ['OUTPUT', (2657.3825285434723, 670.8418045043945), (2929.8974316120148, 975.4852895736694)]] Then, using line detection algorithm I identified all the 17 lines connecting each component. All above 17 lines take as a list of arrays, and those lines are not in a correct order and each line has 2 end points. lines = [[(60, 1502), (787, 1467)], [(125, 1031), (691, 988)], [(128, 772), (685, 758)], [(131, 336),(709,347)], [(927,350),(1455, 348)], [(400, 1361), (792, 1369)], [(834, 843), (2343, 939)], [(915, 1430), (1119, 1424)], [(1125, 468), (1453, 470)], [(1587, 399), (1911, 405)], [(1884, 755), (2245, 814)],[(2372, 831), (2918, 859)], [(1891, 397), (1901, 767)], [(1138, 457), (1128, 738)], [(441, 738), (421, 903)], [(1125, 946), (1101, 1437)], [(420, 1098), (408, 1373)]] When connecting those lines, it is must to consider following scenario. It means nodes are used to indicate a bridge without crossing lines. M is an input to the AND gate and (M.Z) is an input to the other AND gate. So how can I generate the following Boolean Expression using above 2 arrays and above scenario? This should be a function that works for all logic gates. It can be assumed that image is always going to read from left to right.
Kivy FileChooserListView - Modifying the display of the file list?
I was wondering if anyone knew how to add numbers (purely for reference) to Kivy's FileChooserListView such that the file list is displayed like: # Name Size 1. File 1 2k 2. File 2 2k 3. File 3 2k ...
OK, it's not a perfect answer but here's what I tried to do: First thing was to edit kivy's default filechooser.py file. Find this section: ctx = {'name': basename(fn), 'get_nice_size': get_nice_size, 'path': fn, 'controller': wself, 'isdir': self.file_system.is_dir(fn), 'parent': parent, 'sep': sep} and change it to: ctx = {'name': basename(fn), 'get_nice_size': get_nice_size, 'path': fn, 'controller': wself, 'isdir': self.file_system.is_dir(fn), 'parent': parent, 'sep': sep, 'index': index} Next up, find kivy's style.kv file (you could probably create a custom class to do this but I was being lazy!). Look for this section [FileListEntry#FloatLayout+TreeViewNode]: I then took this part: Label: id: filename text_size: self.width, None halign: 'left' shorten: True text: ctx.name and changed it to: Label: id: filename text_size: self.width, None halign: 'left' shorten: True text: "{}. {}".format(ctx.index, ctx.name) As per my comment above, it seems to throw an error if you try to navigate folders. It may be the case that one of the kivy experts knows a better way of doing this.
I know this is quite late but to complete the answer of elParaguayo, you also have to replace the lines pardir = self._create_entry_widget(dict( name=back, size='', path=new_path, controller=ref(self), isdir=True, parent=None, sep=sep, get_nice_size=lambda: '')) with pardir = self._create_entry_widget(dict( name=back, size='', path=new_path, controller=ref(self), isdir=True, parent=None, sep=sep, get_nice_size=lambda: '', index= 0)) (be careful there are 2 occurences of these lines). This is what throws the exception when you navigate: the parent directory ../ is not created with the same lines as the other files. Also, I would advise to create a local copy of filechooser.py and style.kv and load them into your app instead of modifying the source code of the kivy modules.