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.
Picker wheel for lists (not just dates)
-
@bogfard I had already tried but I've never understood why when the wheel rolls too far, data disappear.
Thus, I've stopped to spend time, but you can try this script -
@cvp here's working one ...
# coding: utf-8 from objc_util import ObjCInstance, c, ObjCClass, ns, create_objc_class, NSObject from ctypes import c_void_p import ui # Data for both pickers _data = [ [str(x) for x in range(2000, 2040)], ['xxxx', 'yyyy', 'zzzz'] ] # ObjC classes UIColor = ObjCClass('UIColor') UIPickerView = ObjCClass('UIPickerView') UIFont = ObjCClass('UIFont') NSAttributedString = ObjCClass('NSAttributedString') # Default attributes, no need to recreate them again and again def _str_symbol(name): return ObjCInstance(c_void_p.in_dll(c, name)) _default_attributes = { _str_symbol('NSFontAttributeName'): UIFont.fontWithName_size_(ns('Courier'), 16), _str_symbol('NSForegroundColorAttributeName'): UIColor.redColor(), _str_symbol('NSBackgroundColorAttributeName'): UIColor.greenColor() } # Data source & delegate methods def pickerView_attributedTitleForRow_forComponent_(self, cmd, picker_view, row, component): tag = ObjCInstance(picker_view).tag() return NSAttributedString.alloc().initWithString_attributes_(ns(_data[tag - 1][row]), ns(_default_attributes)).ptr def pickerView_titleForRow_forComponent_(self, cmd, picker_view, row, component): tag = ObjCInstance(picker_view).tag() return ns(_data[tag - 1][row]).ptr def pickerView_numberOfRowsInComponent_(self, cmd, picker_view, component): tag = ObjCInstance(picker_view).tag() return len(_data[tag - 1]) def numberOfComponentsInPickerView_(self, cmd, picker_view): return 1 def rowSize_forComponent_(self, cmd, picker_view, component): return 100 def pickerView_rowHeightForComponent_(self, cmd, picker_view, component): return 30 def pickerView_didSelectRow_inComponent_(self, cmd, picker_view, row, component): tag = ObjCInstance(picker_view).tag() print(f'Did select {_data[tag - 1][row]}') methods = [ numberOfComponentsInPickerView_, pickerView_numberOfRowsInComponent_, rowSize_forComponent_, pickerView_rowHeightForComponent_, pickerView_attributedTitleForRow_forComponent_, pickerView_didSelectRow_inComponent_ ] protocols = ['UIPickerViewDataSource', 'UIPickerViewDelegate'] UIPickerViewDataSourceAndDelegate = create_objc_class( 'UIPickerViewDataSourceAndDelegate', NSObject, methods=methods, protocols=protocols ) # UIPickerView wrapper which behaves like ui.View (in terms of init, layout, ...) class UIPickerViewWrapper(ui.View): def __init__(self, **kwargs): super().__init__(**kwargs) self._picker_view = UIPickerView.alloc().initWithFrame_(ObjCInstance(self).bounds()).autorelease() ObjCInstance(self).addSubview_(self._picker_view) def layout(self): self._picker_view.frame = ObjCInstance(self).bounds() @property def tag(self): return self._picker_view.tag() @tag.setter def tag(self, x): self._picker_view.setTag_(x) @property def delegate(self): return self._picker_view.delegate() @delegate.setter def delegate(self, x): self._picker_view.setDelegate_(x) @property def data_source(self): return self._picker_view.dataSource() @data_source.setter def data_source(self, x): self._picker_view.setDataSource_(x) class MyView(ui.View): def __init__(self, **kwargs): super().__init__(**kwargs) self.background_color = 'white' self.delegate_and_datasource = UIPickerViewDataSourceAndDelegate.alloc().init().autorelease() pv1 = UIPickerViewWrapper(frame=[100, 100, 200, 100]) pv1.delegate = self.delegate_and_datasource pv1.data_source = self.delegate_and_datasource pv1.tag = 1 self.add_subview(pv1) pv2 = UIPickerViewWrapper(frame=[100, 400, 200, 100]) pv2.delegate = self.delegate_and_datasource pv2.data_source = self.delegate_and_datasource pv2.tag = 2 self.add_subview(pv2) if __name__ == '__main__': v = MyView() v.present('full_screen')
-
@zrzka One more time, thanks a lot...
I'm not sure I'll try to write my-self some Objective-C code in the future.
Could you, in some words, tell me why my code was erroneous. -
I am working on a lib of lesser used UI components as well as components I create for my own projects (ie Modal box, web style drop down)
Are you okay if I include your code - with it?
I had intentions of doing it, but since you already have it working pretty well, its a big time saver especially since I don't do objc that well.
Once the module is somewhat stable i will be open sourcing it as MIT and posting here.
I will of course keep any copyright text you deem fit.
-
@reticulated feel free, it's just a snippet. Whatever I put on the forum I consider public domain. Also it's @cvp code, I just modified it a bit.
@cvp honestly I don't know. I just pasted it to Pythonista, rewrite non pythonic parts, ... and it worked :)
-
@zrzka Anyway, once more, thanks for your time.
-
How is the lib coming? I would love to get that!
-
@cvp, @reticulated Hi guys. I've stumbled into this picker wheel for lists snippet and have put it to work. However, I can't figure out how to set a default value (other than the first value in the list) before my view starts. I basically want to reload the last values select when the view was last used. It's probably simple but not obvious to me. Thank you for any help.
-
@vkcatfish sorry for thé delay. If I correctly understood the question
pv1 = UIPickerViewWrapper(frame=[100, 100, 200, 100]) pv1.delegate = self.delegate_and_datasource pv1.data_source = self.delegate_and_datasource pv1.tag = 1 pv1._picker_view.selectRow_inComponent_animated_(1,0,True) self.add_subview(pv1)
-
@cvp Thanks! That works!