how to using keyboard to select data in treeview without mouse - python

Firstly, When my cursor is in the entry box (entrybox.focus()), I would like to using F4 key on keyboard (GUI.bind('<F4>', directselection)) to select the first data in my treeview directly instead of using mouse.
I don't have any idea to create the function. I'm trying to use
def directselection(event = None):
treeviewtable.focus()
but it doesn't work.

Use .get_children() to get a list of row IDs and then use .selection_set() to select the first row:
def directselection(event=None):
# get all row IDs
idlist = treeviewtable.get_children()
if idlist:
# select and focus on first row
treeviewtable.selection_set(idlist[0])
treeviewtable.focus(idlist[0])
# transfer keyboard focus to treeviewtable
treeviewtable.focus_force()

Related

How to write the if clause when iterating through a treeview?

I have a function that checks if a barcode is known to the warehouse. If so, the function grabs the row from the dataframe (occupied by an imported excel file) and will be inserted into a treeview with known items. If the barcode is unknown it will be inserted into a listbox.
The function works and does what it is supposed to do, but I want to expand it by updating the row in the treeview by increasing its quantity by 1 when adding the same barcode to the treeview. See the picture for the current behaviour. Known items treeview
# Function to process new entered barcodes by filtering known and unknown items and adding them to treeview
def scan_check(event):
scanned_item = scan_entry.get()
for code in df.iloc[:, 1]: # column with barcodes
if code == scanned_item:
for row in df.to_numpy().tolist(): # dataframe with item / barcode / item description / size / quantity
if scanned_item in row:
quantity_count = 1
row.insert(4, quantity_count)
scanTree.insert(parent='', index='end', value=row)
for child in scanTree.get_children():
if scanTree.item(child, option='values'[3]) in scanTree.get_children():
quantity_count += 1
scanTree.set(child, 'Quantity', quantity_count)
scan_entry.delete(0, tkinter.END)
break # to prevent adding item to unknown products listbox as well
else:
unknown_listbox.insert(tkinter.END, scanned_item)
scan_entry.delete(0, tkinter.END)
My question is: How would I write the if clause, after iterating throught the children, when I want to check if the added row from the dataframe is already in my treeview?
My attempts at the if clause did not work obviously. I was hoping anyone could help me with my problem. Thanks for reading.
You can simplify the logic:
Search the treeview first for the barcode, if found, update the quantity
If not found, search the dataframe. If found, insert new record into treeview, otherwise insert the barcode to the unknown listbox
def scan_check(event):
scanned_item = scan_entry.get().strip()
if scanned_item == '':
# do nothing if empty string is input
return
# search treeview
for child in scanTree.get_children():
row = scanTree.set(child)
if row['Barcode'] == scanned_item:
# update quantity
scanTree.set(child, 'Quantity', int(row['Quantity'])+1)
break # prevent executing else block
else:
# search dataframe
result = df.loc[df['Barcode'].astype(str) == scanned_item]
if result.empty:
# should check whether barcode already exists?
unknown_listbox.insert('end', scanned_item)
else:
scanTree.insert('', 'end', values=result.iloc[0].to_list()+[1])
scan_entry.delete(0, 'end')

mongodb documents values in treeview in python

I want to display mongodb documents values in treeview in python.
Below is my code, but it not displays data in proper manner in treeview.
collection = myDB['students']
rows = list(collection.find())
if len(rows)!=0:
self.student_table.delete(*self.student_table.get_children())
for row in rows:
self.student_table.insert("",END,values=row.values())
You need to change row.values() (type dict_values) to list:
for row in rows:
self.student_table.insert("", END, values=list(row.values()))

Postgres/Python subfield sanity check

I am struggling with a sanity check. I have a PostgreSQL database on dbeaver and a table named Album. I am trying to automate a sanity check. In the column ArtistId I have a small click-in window on the right, once I click on it I get a new window with ArtistId and Name. For every distinct ArtistId I wish to check whether the name is the corresponding ArtistId. So far I managed to get the table (Album) in a data-frame but I can not reach the sub-field. Thank you in advance for any help.
Problem 1: I need to access the sub-field (Database window picture).
Problem 2: I need to check for every row of the sub-field whether the artist name is 'Iron Maiden' or the corresponding artist name based on ArtistId that the user provided.
My code retrieves the entries in the database.
def get_entries(artistID):
artistID = int(input("Enter an artist_id from the available in postgresql :"))
df = pd.read_sql("SELECT * FROM Album WHERE ArtistId = %s",connection, params=(artistID,) )
return df
For problem 1) I found the following code SELECT x.* FROM Artist x WHERE x.ArtistId = 4 which can give me access to the sub-field.
Database Database window Database er diagram
The solution to the Problem 1 was a simple query:
SELECT *
FROM Album a
CROSS JOIN Artist b
Where a.ArtistId = b.ArtistId
AND a.ArtistId = 90
The solution to the Problem 2 was python line:
#This line returns the rows in my dataframe that are not same to the user_input
df.loc[df.ArtistId != artistID]

Populate Unique ID field after Sorting, Python

I am trying to create an new unique id field in an access table. I already have one field called SITE_ID_FD, but it is historical. The format of the unique value in that field isn't what our current format is, so I am creating a new field with the new format.
Old Format = M001, M002, K003, K004, S005, M006, etc
New format = 12001, 12002, 12003, 12004, 12005, 12006, etc
I wrote the following script:
fc = r"Z:\test.gdb\testfc"
x = 12001
cursor = arcpy.UpdateCursor(fc)
for row in cursor:
row.setValue("SITE_ID", x)
cursor.updateRow(row)
x+= 1
This works fine, but it populates the new id field based on the default sorting of objectID. I need to sort 2 fields first and then populate the new id field based on that sorting (I want to sort by a field called SITE and then by the old id field SITE_ID_FD)
I tried manually sorting the 2 fields in hopes that Python would honor the sort, but it doesn't. I'm not sure how to do this in Python. Can anyone suggest a method?
A possible solution is when you are creating your update cursor. you can specify to the cursor the fields by which you wish it to be sorted (sorry for my english..), they explain this in the documentation: http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//000v0000003m000000
so it goes like this:
UpdateCursor(dataset, {where_clause}, {spatial_reference}, {fields}, {sort_fields})
and you are intrested only in the sort_fields so assuming that your code will work well on a sorted table and that you want the table ordered asscending the second part of your code should look like this:
fc = r"Z:\test.gdb\testfc"
x = 12001
cursor = arcpy.UpdateCursor(fc,"","","","SITE A, SITE_ID_FD A")
#if you want to sort it descending you need to write it with a D
#>> cursor = arcpy.UpdateCursor(fc,"","","","SITE D, SITE_ID_FD D")
for row in cursor:
row.setValue("SITE_ID", x)
cursor.updateRow(row)
x+= 1
i hope this helps
Added a link to the arcpy docs in a comment, but from what I can tell, this will create a new, sorted dataset--
import arcpy
from arcpy import env
env.workspace = r"z:\test.gdb"
arcpy.Sort_management("testfc", "testfc_sort", [["SITE", "ASCENDING"],
["SITE_IF_FD", "ASCENDING]])
And this will, on the sorted dataset, do what you want:
fc = r"Z:\test.gdb\testfc_sort"
x = 12001
cursor = arcpy.UpdateCursor(fc)
for row in cursor:
row.setValue("SITE_ID", x)
cursor.updateRow(row)
x+= 1
I'm assuming there's some way to just copy the sorted/modified dataset back over the original, so it's all good?
I'll admit, I don't use arcpy, and the docs could be a lot more explicit.

PyGtk: Scrollist with Entry, can I set an Id

I have a scroll list on my window that I am going to insert 2 entry for each row, I am trying to understand how I can catch the entry that has been changed and update my array with this value.
I will explain what is my code:
I have an array that has 2 fields: Name and Description
Each row has 2 entry, Name and Description
When I am going to modify the row number 2 I want to update my object on my array:
rows[1].name = XXX rows[1].description = YYY
You might also want to consider using Gtk.TreeView with editable cells. The underlying Gtk.ListStore could replace your array.
But you can also use your existing entries and pass any data you want as "user data" to the callback for the "changed" signal.
def on_entry_changed(entry, data):
print("Row %d, Column %s - %s", data[0], data[1], entry.get_text())
for i in xrange(10):
name = Gtk.Entry()
name.connect("changed", on_entry_changed, (i, "name"))
description = Gtk.Entry()
description.connect("changed", on_entry_changed, (i, "description"))
# add your entries to a box or whatever

Categories