I've got a bit of code that is suppose to change the text displayed in the entry fields depending on which item is selected in the tree view. I've bound the event to both the left mouse and up and down arrow keys and it's sort of working. Problem is the item in the tree that is currently selected isn't the value being displayed in the entry field. If there are three (5, 7, 4) values and the item with value 4 is selected, the entry field will display the item with value 7 in it. It's always one off. I hate to ask a question about this because I feel like the answer is so simple but I'm really at a loss. Here is my code.
# create GUI items to populate frames
self.create_menu()
self.create_edit_display()
self.albumDisplay = Label(self.editFrame)
self.create_import_display()
self.tree.bind("<BackSpace>", self.delete_insert)
self.tree.bind("<Button-1>", self.update_editFrame)
self.tree.bind("<Up>", self.update_editFrame)
self.tree.bind("<Down>", self.update_editFrame)
# selected track can be removed
def delete_insert(self, event):
self.tree.delete(self.tree.focus())
def update_editFrame(self, event):
trackInfo = self.tree.item(self.tree.focus())
print(trackInfo)
if self.tree.focus():
trackInfo = self.tree.item(self.tree.focus())
self.trackNumberEntry.delete(0, END)
#self.trackNumberEntry.insert(0, random.choice([1,2,3,4,5,6,7]))
self.trackNumberEntry.insert(0, trackInfo['values'][0])
else:
self.tree.focus_get()
Through my debugging I've noticed that every time I first click on the tree view I get something like.
{'tags': '', 'text': '', 'values': '', 'image': '', 'open': 0}
{'tags': '', 'text': 'IMPORT# 2', 'values': [6, 'Supersymmetry', '', 'Arcade Fire', 'Arcade Fire', 'Reflektor', '', '', 2013, '00:11:16', '', '', 'arcade_fire_reflektor_06_supersymmetry_.mp3', 'arcade_fire_reflektor.jpg', ''], 'image': '', 'open': 0}
It's that initial call that's messing up the order. I'm not sure why it's doing that before getting right into 'value''s values.
The simple solution is to bind to <<TreeviewSelect>> instead of binding to all the ways that the current item can be changed.
The reason your bindings always seem to be one behind is that they are. Custom bindings on widgets fire before the built-in bindings, and it is the built-in bindings which change the selected item. Thus, in your callbacks you are seeing the state of the tree before the selected item is changed.
For a longer explanation see https://stackoverflow.com/a/11542200/7432
Related
I was wrong i got to do one more update:
The Accepted Answer now includes one way to reference generated Textinput by add_widget, so my Link is still an alternative but by editing the Answer theres a Solution much for all those of you who would like to stick with weakref and maybe its a nice way to start using weakref.
This is the last Edit of my Question:
The Reason i was asking this question was my approach to get TextInput from automatic generated TextInput Widgets and add these text Inputs to a list.
My Approach was completely wrong, and this is the reason i got stuck. As i found a ton of other people asking for the same reason ( getting Textinput from user interface available for py logic) going for the same approach, getting stuck
i do link a "Solution" which worked for me and enabled me to access TextInput without Widget Id:
Right approach
I do really hope to save you guys some time. Anyway i marked the Answer as right because it given the solution for what i did ask for ( my Bad ).
I am really struggling to reference TextInput Widgets after generate them by User Input.
I was trying walk() options already.
self.ids.grid.clear_widgets([i for i in self.ids.grid.children])
label1 = Label(text="Periode")
label2 = Label(text="Gross Income d Geschäftsfeldes")
self.ids.grid.add_widget(label1)
self.ids.grid.add_widget(label2)
for i in range(int(ButtonsZähler[0])):
label = Label(text="GI in Periode: -" + str(i+1))
text = TextInput(text=' ')
self.ids.grid.add_widget(label)
btn1 = Button(text="Close", )
self.ids.grid.add_widget(text)
self.ids['text'] = weakref.ref(text)
and i have the following kivy code related to this:
:
name: 'RisikokapitalOperativesRisikoIII'
GridLayout:
id: Peter
cols: 1
GridLayout:
id: grid
name : grid
cols: 2
GridLayout:
id: grid2
cols: 2
Button:
id:zurruck
text:"Abbrechen"
on_press:
app.root.total_button = 5
on_release:
root.redo()
app.root.current = "RisikokapitalOperativesRisikoI"
root.manager.transition.direction = "left"
i dont know how to reference the text Input. Labels and Text Input are shown correctly. I want to add all text Inputs by User to one List. I have no clue how to work aroound the fact add_widget ist not abled to generate id in my kv File ?
kind regards
UPDATE:
By Using the already given Help i could retrive the following information (a part of a list its given all widgets but i just post one ) in my console:
<weakref at 0x000001E761011D60; to 'TextInput' at 0x000001E760FFC7B0>
Wurst
[<kivy.uix.textinput.TextInput object at 0x000001E760FFC7B0>,
I would like to be abled to acces the TextInput given by User and add this input to a list. As the Documentation is written for experienced users which i am not maybe someone is willing to give a easy to understandable Example ?
Your code:
self.ids['text'] = weakref.ref(text)
is adding the TextInput to the ids, but it is setting the key for all of them to the same value (text). So, if you try to access the TextInput using self.ids.text you will only get the last TextInput added. You can work around this problem by making unique keys for each TextInput, maybe like:
self.ids[str(i+1)] = weakref.ref(text)
or just keep you own list of the TextInput widgets:
self.ti_list = []
.
.
.
for i in range(int(ButtonsZähler[0])):
.
.
.
self.ti_list.append(text)
When looking at your code that creates the TextInputs, the only thing that differentiates the TextInputs is the value of i. Everything else is the same. So that is used to record the TextInputs. In the case of using ids, you would access a TextInput contents by its vale of i as self.ids[str(i+1)].text. Similarly, if you use a list, you can access the same as self.ti_list[i].text.
I have a button in the model sale.order with executes the method action_open_certification_views. This method opens the sale.certification tree view. So the method returns the dictionary of the action which opens the sale.certification views, and I have added the following context to auto-fill in the sale.certification fields (sale_id and line_ids, where line_ids is a One2many field pointing to sale.certification.line):
def action_open_certification_views(self):
...
action['context'] = {
'default_name': 'My Certification',
'default_sale_id': self.id,
'default_line_ids': [
(0, 0, {
'quantity': 5.0,
'sale_line_id': line.id,
}) for line in self.order_line
],
}
return action
When I click on the button, the sale.certification tree view is opened right, and if click on Create button, the context of the action is working well since I see the sale.certification form filled in automatically with the default name My Certification, the right link to sale order, and the same number of certification lines as sale order lines has the sale order. Each of this certification lines has quantity 5.0, and the link to sale order line is right too.
The problem is that the sale.certification.line model has many other fields which are related or which have default values, but these certification lines filled in by default by the action context are not filling in those fields.
For example, there is another field quantity2 in sale.certification.line model, and visible in the view, which always takes by default 1.0. However, the field is empty in all default lines. Same problem with related fields. There are some related fields in the view which take their values through sale_line_id field. These one is filled in OK, but the related fields remain empty. For example, in `sale.certification.line model there is this field:
product_uom = fields.Many2one(
related='sale_line_id.product_uom',
)
In spite of having sale_line_id filled in OK in all lines, they have product_uom empty. Can anyone tell me why? Do I have to specify their values in context too, despite they should have been filled in by theirselves?
Using Tabulator, if you have a 'select' editor and want it to link to values 'Male' and 'Female' but underneath male and female are values from another physical database table with id values of 1 and 2 (which are different than the 'row' id), whats the best way to do something like this?
The 'select' editor has ways to specify the display of items in the drop down and a literal display of the selected value, but no place for a hidden (not displayed) underlying ID of the selected value to pass when saving the data.
We could wrap the select data values in divs with a data attribute for the selects values ids and then pass that when updating, but are not sure this is the best option considering how Tabulator works. We could also just pass the raw selected value and then look it up on the server to get the associated ID, but that seems like a lot of overhead and tightly couples the server to the client, which wouldn't work for something like a 3rd party API where we have no server control.
Any thoughts on how best to handle something like this are appreciated!
The select editor allows for values to be passed in a number of ways, including specifying both the items value and its user visible label
If you want to show a different lable to the value you want to store, you can pass in an object, where the key of each property is the value that will be stored if it is selected, and the value of each property will be the lable displayed for it in the list.
{title:"Name", field:"name", editor:"select", editorParams:{
values:{
"steve":"Steve Boberson",
"bob":"Bob Jimmerson",
"jim":"Jim Stevenson",
}
}}
For more complex option lists you can use an array of objects, that allows you to define option groups, and disabled options.
{title:"Name", field:"name", editor:"select", editorParams:{
values:[
{ //option group
label:"Men",
options:[ //options in option group
{
label:"Steve Boberson",
value:"steve",
},
{
label:"Bob Jimmerson",
value:"bob",
},
]
},
{ //option group
label:"Women",
options:[ //options in option group
{
label:"Jenny Jillerson",
value:"jenny",
},
{
label:"Jill Betterson",
value:"jill",
},
]
},
{//ungrouped option
label:"Other",
value:"other",
},
]
}}
For full details on how to use this editor, checkout the Editor Documentation
Finally figured this out. You need to use the lookup formatter to display the text value using the same params as the select editor. This is not obvious since none of the select editor examples in the docs show use of it. Anyway, here is a simple example showing it in both directions. Of course you would want to abstract the data out instead of literally duplicating it, but here to help show the literal use, it is duplicated:
{
title:"Example",
field:"example",
editor: "select",
editorParams:{
"1": "Cute",
"2": "Fine",
"3": "Scary",
},
formatter:"lookup", // display option, but store value
formatterParams:{
"1": "Cute",
"2": "Fine",
"3": "Scary",
}
}
I want to show a list of suggestions to the user, and as expected I do it like:
new Suggestions('option 1', 'option 2', 'option 3', '...');
But the problem is that this way the suggestions are shown in a single row and the user will have to do horizontal scroll to reach all suggestions.
Instead, I would prefer to organize the suggestions in a table view in order to have multiple rows.
I thought I could get through this using this approach but it doesn't seem to work:
new Table({
dividers: true,
columns: ['header 1', 'header 2', 'header 3'],
rows: [
[new Suggestions('opt 1-1'), new Suggestions('opt 1-2'), new Suggestions('opt 1-3')],
[new Suggestions('opt 2-1'), new Suggestions('opt 2-2'), new Suggestions('opt 2-3')],
]
})
Does anyone know any other way how to achieve this?
There's not really a way to show suggestions within a table. You could show a table of plain text, inviting the user to say one of the options, but you won't get the interactive widgets.
The idea of the suggestion chips is to suggest but not mandate a handful of potential things that the user might say to continue the conversation, and the horizontal row is meant to highlight the most frequent.
Is it possible to iterate through an array to generate the values that populate a select box, rather than hard-coding them in the template?
I'm passing an array of values to the template that I would like available in the select box, but I'm not sure how to go about iterating through it.
Here's how I currently have it:
{{ form_select('profile_status', {
'created' : 'Candidate Created',
'mailed': 'Questionnaire Mailed',
'personal_info': 'Personal Data Filled Out',
'survey': 'Survey Completed',
'primary': 'Waiting for Post-Primary Updates',
'endorsements': 'Endorsements Completed',
'essay': 'Essay Completed',
}, candidate.profile_status, {'class': 'form-control', 'id': 'profile-status'})|raw }}
What I'm not sure how to do is implement a for-loop within an already existing twig tag to replace the hard-coded list of values.
Can someone point me in the right direction?
Thanks!