RubyMotion and UIPickerView - rubymotion

I want to use UIPickerView to select a number and assign the selected number to a label. I worked out how to do it using the ib gem and using interface builder to create the initial interface and it works fine. However, I would like to do it purely using RubyMotion code and I can't for the life of me get it to work. The best I have managed is for the label to return True and not a number.
I'm using the following standard code for the picker view delegate methods:
def pickerView(pickerView, numberOfRowsInComponent:component)
101
end
def pickerView(pickerView, titleForRow:row, forComponent:component)
row.to_s
end
def numberOfComponentsInPickerView (pickerView)
1
end
def pickerView(pickerView, didSelectRow:row, inComponent:component)
end
def pickerView(pickerView, titleForRow:row, forComponent:component)
" #{row+1}"
end
def submit
totals.addTotals(myPicker.selectedRowInComponent(0))
end
and then the label text is populated like this:
numLabel = UILabel.new
numLabel.text = "Number Selected: #{submit}"
numLabel.font = UIFont.boldSystemFontOfSize(18)
numLabel.frame = [[20,320],[260,340]]
numLabel.numberOfLines = 2
numLabel.adjustsFontSizeToFitWidth = 'YES'
self.view.addSubview numLabel
The totals is a shared client.

Here is how to do it in RubyMotion alone. Note that the label and picker are set up in viewDidLoad. The label gets updated in pickerView:didSelectRow:inComponent:
app_delegate.rb
class AppDelegate
def application(application, didFinishLaunchingWithOptions:launchOptions)
#window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
#window.rootViewController = PickerDemo.new
#window.makeKeyAndVisible
true
end
end
picker_demo.rb
class PickerDemo < UIViewController
def viewDidLoad
view.backgroundColor = UIColor.whiteColor
#numLabel = UILabel.new
#numLabel.text = "Number Selected: 0"
#numLabel.font = UIFont.boldSystemFontOfSize(18)
#numLabel.frame = [[20,100],[260,120]]
#numLabel.numberOfLines = 2
#numLabel.adjustsFontSizeToFitWidth = true
view.addSubview(#numLabel)
#picker = UIPickerView.new
#picker.frame = [[0, 183], [320, 162]]
#picker.delegate = self
#picker.dataSource = self
view.addSubview(#picker)
end
def pickerView(pickerView, numberOfRowsInComponent:component)
101
end
def pickerView(pickerView, titleForRow:row, forComponent:component)
row.to_s
end
def numberOfComponentsInPickerView(pickerView)
1
end
def pickerView(pickerView, didSelectRow:row, inComponent:component)
#numLabel.text = "Number Selected: #{row}"
end
end

Related

how to use Maps with groovy.text.SimpleTemplateEngine

Im unsure how to use Maps with a template engine. Can someone tell me what im doing wrong here?
def engine = new groovy.text.SimpleTemplateEngine()
def binding = [jobs:[[name:'job1',action:'build'], [name:'job2', action:'build']]]
def text = '''
println ${jobs}
println ${jobs[0].name}
${jobs}.each{ job ->
println "name " + job.name
}
'''
def template = engine.createTemplate(text).make(binding)
println template
produces this output
Result
println [[name:job1, action:build], [name:job2, action:build]]
println job1
[[name:job1, action:build], [name:job2, action:build]].each{ job ->
println "name " + job.name
}
The 2nd println shows job1 from this ${jobs[0].name} which looks good except I want to do that in the iterator, but I'm not sure what that each is showing me. I would expect to get
name job1
name job2
from the iterator. Any ideas how to do this?
all from documentation: https://docs.groovy-lang.org/latest/html/api/groovy/text/SimpleTemplateEngine.html
def engine = new groovy.text.SimpleTemplateEngine()
def binding = [jobs:[[name:'job1',action:'build'], [name:'job2', action:'build']]]
def text = '''
jobs[0].name = ${jobs[0].name}
<% jobs.each{ job -> %>\
name = ${job.name}
<%}%>
'''
def template = engine.createTemplate(text).make(binding)
println template
result:
jobs[0].name = job1
name = job1
name = job2

replacing a new interface with old one in tkinter

I've created a class that has a function called mainScreen(). It simply prints the main screen with two buttons on it. If you press any button, it must go to another function called signup(). I want to clear the whole frame and create new widgets but I can't clear the widgets
class graphics:
def __init__(self, master):
self.root = master
def mainscreen(self):
helv36 = tkFont.Font(family='Century Gothic', size=20)
mainFrame = Frame(self.root)
mainFrame.config(relief='sunken', width=1280, height=720, bg='light
blue')
mainFrame.pack(expand='yes', fill='both')
inButton = Button(mainFrame, text = "Sign up", bd = 10, relief =
GROOVE, font = helv36)
inButton.bind("<Button-1>", self.signup)
inButton.place(bordermode = OUTSIDE, width =160, height = 60, x =
600, y = 300)
upButton = Button(mainFrame, text = "Sign in", bd = 10, relief =
GROOVE, font = helv36)
upButton.bind("<Button-1>", self.signup)
upButton.place(bordermode = OUTSIDE, width =160, height = 60, x =
600, y = 400)
mainFrame.pack_propagate(FALSE)
self.root.mainloop()
def signup(self,event):
signUpShow = Frame(self.root)
signUpShow.config(relief='sunken', width=1280, height=720, bg='light
yellow')
signUpShow.pack(expand='yes', fill='both')
You __init__ needs to have its code indented and it needs a call to mainscreen. The solution to mainFrame being local within mainscreen is to make it also an attribute.
self.mainframe = mainFrame = Frame(self.root)
Then you can access self.mainframe within signup.

Tkinter/python: how to create a checkbutton to select all checkbuttons

I created a list of checkboxes with Tkinter but I would like to select all checkboxes with a single checkbox.
Here is part of my code:
root = tk.Tk()
root.title("SOMETHING")
buttons=[]
#If it is checked, then run the file
def callback():
for var, name in buttons:
if var.get():
subprocess.call("python " + "scripts/" + name)
for name in os.listdir("scripts"):
if name.endswith('.py') or name.endswith('.pyc'):
if name not in ("____.py", "_____.pyc"):
var = tk.BooleanVar()
cb = tk.Checkbutton(root, text=name, variable=var)
cb.pack()
buttons.append((var,name))
def select_all():
if var1.get():
for i in cb:
i.select(0,END)
def deselect_all():
if var2.get():
for i in cb:
i.deselect_set(0,END)
var1=tk.BooleanVar()
selectButton = tk.Checkbutton(root, text="Select All", command=select_all, variable=var1)
selectButton.pack()
var2=tk.BooleanVar()
deselectButton = tk.Checkbutton(root, text="None", command=deselect_all, variable=var2)
deselectButton.pack()
submitButton = tk.Button(root, text="Run", command=callback)
submitButton.pack()
root.mainloop()
When I run the file and press "select all", I get this error: 'str' object has no attribute 'select'.
Please help thanks :)
I have reviewed your code and attached a working tkinter code. Will leave you to resolve the issue with using subprocess.
My main comment is that your use of control variable and how to use it to get and set their value was inappropriate. I have remove the unnecessary codes. Also, shown you how to extract information from your list. Hope this helps your tkinter coding journey.
Working code:
import tkinter as tk
import os, subprocess
#If it is checked, then run the file
def callback():
if var.get():
for i in buttons:
cmd = "python3 " + filedir +"/" + i[1] #Note:Runs python3 and not python2
print(cmd)
subprocess.call(cmd)
def select_all(): # Corrected
for item in buttons:
v , n = item
if v.get():
v.set(0)
else:
v.set(1)
root = tk.Tk()
root.title("SOMETHING")
filedir = 'test'
buttons=[]
for name in os.listdir(filedir):
if name.endswith('.py') or name.endswith('.pyc'):
if name not in ("____.py", "_____.pyc"):
var = tk.IntVar()
var.set(0)
cb = tk.Checkbutton(root, text=name, variable=var)
cb.pack()
buttons.append((var,name))
var1=tk.IntVar()
var1.set(0)
selectButton = tk.Checkbutton(root, text="Select All", command=select_all,
variable=var1)
selectButton.pack()
submitButton = tk.Button(root, text="Run", command=callback)
submitButton.pack()
root.mainloop()

Promotion/bubble-wrap TableScreen data

I'm stuck on this:
I need to populate data into my app.
I'm using Promotion for the very first time....
Without ProMotion I use to fetch the data in the init method
Now my code looks like below:
class Parties < ProMotion::TableScreen
attr_accessor :_cells
#news = []
include MyUiModules
title 'Yazarlar'
refreshable callback: :on_refresh,
pull_message: "Pull to refresh",
refreshing: "Refreshing data…",
updated_format: "Last updated at %s",
updated_time_format: "%l:%M %p"
def on_refresh
#MyItems.pull_from_server do |items|
##my_items = items
end_refreshing
#update_table_data
# end
end
def table_data
_cells = []
[{
title: nil,
cells: create_cells(_cells)
}]
end
def will_appear
Barbutton.create_bar(self)
set_attributes self.view, {
backgroundColor: hex_color("DBDBDB")
}
end
def go_to_next
App.delegate.slide_menu.show_menu
end
def create_cells(_cells)
BW::HTTP.get(URL) do |response|
json = BW::JSON.parse response.body.to_str
for line in json
_cells << { title: line["val_for_title"]}
end
end
_cells
end
end
Unfotunately this does return an empty array, and I can't figure out how to solve it.
Thx for your help
You can't do that because BW::HTTP.get is asynchronous !
Instead try something like this:
def on_init
#data = []
end
def table_data
[
{
title: nil,
cells: #data
}
]
end
def on_refresh
BW::HTTP.get(URL) do |response|
#data = []
json = BW::JSON.parse(response.body.to_str)
json.each do |hash|
#data << { title: hash["val_for_title"]}
end
update_table_data
end_refreshing
end
end
Hope it helps :-)

Django: How to add an extra form to a formset after it has been constructed?

This is roughly what I'm trying to do:
def post(request):
VehicleFormSet = formset_factory(StaffVehicleForm)
if request.method == 'POST':
vehicle_formset = VehicleFormSet(request.POST)
if 'add_vehicle' in request.POST:
if vehicle_formset.is_valid():
form_count = vehicle_formset.total_form_count()
vehicle_formset.forms.append(vehicle_formset._construct_form(form_count))
Basically, if a user clicks the "Add" button and their entry is valid, I want to add another blank form to the formset, and hide the previous one.
The problem with the code above is that I can't figure out how to increase total_form_count(). The way I have it now, it will work once, and then if you press it again, nothing will happen, presumably because form_count is the same. I also don't like calling _construct_form and relying on the internals.
class RequiredFormSet(BaseFormSet):
def add_form(self, **kwargs):
# add the form
tfc = self.total_form_count()
self.forms.append(self._construct_form(tfc, **kwargs))
self.forms[tfc].is_bound = False
# make data mutable
self.data = self.data.copy()
# increase hidden form counts
total_count_name = '%s-%s' % (self.management_form.prefix, TOTAL_FORM_COUNT)
initial_count_name = '%s-%s' % (self.management_form.prefix, INITIAL_FORM_COUNT)
self.data[total_count_name] = self.management_form.cleaned_data[TOTAL_FORM_COUNT] + 1
self.data[initial_count_name] = self.management_form.cleaned_data[INITIAL_FORM_COUNT] + 1
def add_fields(self, form, index):
super(RequiredFormSet, self).add_fields(form, index)
form.empty_permitted = False
That will do it. Only took 7 hours to figure out. And I still don't know why I need .is_bound = False to make the initial values not screw up.
I do this using javascript. Since the formset renders three management fields
<input type="hidden" id="id_TOTAL_FORMS" value="1" name="TOTAL_FORMS">
<input type="hidden" id="id_INITIAL_FORMS" value="1" name="INITIAL_FORMS">.
<input type="hidden" id="id_MAX_NUM_FORMS" name="MAX_NUM_FORMS">
you can use javascript to increment the id_TOTAL_FORMS value, and just add in the extra fields. So I'd create my fieldset like this:
VehicleFormSet = modelformset_factory(StaffVehicleForm, extra = 0, max_num = None)
The tricky thing is to create the extra form fields in javascript. I usually use AJAX to fetch a new row from a custom view.
For posterity here is another way which works without JS (or alongside JS) and which does not require intimate knowledge of formset methods. Instead, you can just inspect the POST data and adjust it as if JS had done some work client-side. The following makes sure that there is always (at least) one empty form at the end of the formset:
def hsview( request):
HS_formset = formset_factory( HSTestForm, extra=3 )
prefix='XYZZY'
testinpost, empty = 'key', '' # field in the form and its default/empty value
extra=3
# I prefer to do the short init of unbound forms first, so I invert the usual test ...
if request.method != 'POST':
formset = HS_formset( prefix=prefix)
else:
# process POSTed forms data.
# pull all relevant things out of POST data, because POST itself is not mutable
# (it doesn't matter if prefix allows in extraneous items)
data = { k:v for k,v in request.POST.items() if k.startswith(prefix) }
#if there are no spare empty forms, tell it we want another form, in place of or extra to client-side JS
#don't want to crash if unvalidated POST data is nbg so catch all ...
try:
n = int( data[ prefix + '-TOTAL_FORMS'])
test = '{}-{}-{}'.format(prefix, n-1, testinpost)
#print(test)
test = data.get( test, empty)
except Exception:
test = 'bleagh'
# log the error if it matters enough ...
if test != empty:
data[ prefix + '-TOTAL_FORMS'] = n + 1
# now the usual formset processing ...
formset = HS_formset( data, prefix=prefix)
# other_form = OtherForm( request.POST)
if formset.is_valid():
...
I use RegEx in my Vue.js method:
addForm: function () {
this.count++
let form_count = this.count
form_count++
let formID = 'id_form-' + this.count
incremented_form = this.vue_form.replace(/form-\d/g, 'form-' + this.count)
this.formList.push(incremented_form)
this.$nextTick(() => {
let total_forms = document.getElementsByName('form-TOTAL_FORMS').forEach
(function (ele, idx) {
ele.value = form_count
})
})
},
delForm: function () {
if (this.count != 0) {
this.count--
let form_count = this.count
form_count++
let formID = 'id_form-' + this.count
this.formList.pop()
this.$nextTick(() => {
let total_forms = document.getElementsByName('form-TOTAL_FORMS').forEach
(function (ele, idx) {
ele.value = form_count
})
})
}
else return
},