Combobox values appearing as single string characters - python-3.x

I am new posting to the forums & utilizing python/tkinter in order to create an electronic form to gather issues from manufacturing floor.
I have a (2) comboboxes.
The 1st combobox gains its "values" from a given dictionary.keys() which updates the "values" of a 2nd combobox. However, when selecting the values for the 2nd combobox after selecting for the 1st combobox, the values only show singular characters from the dictionary.values().
Here is the list from the txt file. The first item on each line is the key, while the rest of the items on the same line are its values.
Bondshop, Plies: Layup Difficulty, Plies: Cutting Edge
IB Postbond, POU, Equipment, Inspection, Available Work Space, Big Paint, 1575, QN
General Postbond, Inspection
Seal Area, Inspection
Big Paint, Inspection
Deflash, Inspection
Why does my 2nd combobox appear as so? See below.
"...show singular characters"...
===snip===
def loadcategory(self):
# Reads production areas & cateogries from dictCategory.txt file
self.textfileCategory = open('dictCategory.txt', 'r')
self.lines_category = self.textfileCategory.readlines()
for line in self.lines_category:
splitLine = line.split(',')
dict_category[str(splitLine[0])] = ",".join(splitLine[1:])
self.textfileCategory.close()
===snip===
def UpdateData(self, event):
# Updates Category Combobox based on Production Area selection
self.menu_category.set('---')
category = self.menu_production_area.get()
self.menu_category['values'] = sorted(dict_category[category])
===snip===
self.menu_production_area = ttk.Combobox(Main_Frame, state='readonly', values = sorted(list(dict_category.keys())), width=25)
self.menu_production_area.bind('<<ComboboxSelected>>', self.UpdateData)
self.menu_production_area.grid(row=2, column=1, sticky='w')

Related

Display first ten cols of Altair chart if no user selection?

My graph contains 90 rows of different companies. It's controlled by a dropdown menu that allows users to select an individual company. However, until a user selects a value from the dropdown, ALL the rows are displayed all my graph, which looks messy. Is there anyway to show only the first company by default? Or the first ten companies? Thanks.
Current Output.
Desired Output
I haven't found any solutions thus far. Here is my current code.
dropdown_list = df["Name"].sort_values().unique().tolist()
dropdown = alt.binding_select(options=[None] + dropdown_list, labels = ['All'] + dropdown_list, name = "Operator")
selection = alt.selection_single(fields=["Name"], bind=dropdown)
`(alt.Chart(df).mark_circle(opacity=1, size = 150).transform_window(id='rank()',groupby=['Variable']).encode(alt.X('Percentage:O', sort='ascending', axis=alt.Axis(ticks=False, grid=False)),
alt.Y('Name:N'),
color=alt.Color("Variable:N", scale=alt.Scale(range=cp.CALITP_CATEGORY_BRIGHT_COLORS), legend=None),
tooltip = ['Name', 'Variable'])
.properties(title = "Title Here").add_selection(selection).transform_filter(selection))`

I need help in Python with displaying the contents of a 2D Set into a Tkinter Textbox

Disclaimer: I have only begun to learn about Python. I took a crash course just to learn the very basics about a month ago and the rest of my efforts to learn have all been research thru Google and looking at solutions here in Stack Overflow.
I am trying to create an application that will read all PDF files stored in a folder and extract their filenames, page numbers, and the contents of the first page, and store this information into a 2D set. Once this is done, the application will create a tkinter GUI with 2 listboxes and 1 text box.
The application should display the PDF filenames in the first listbox, and the corresponding page numbers of each file in the second listbox. Both listboxes are synched in scrolling.
The text box should display the text contents on the first page of the PDF.
What I want to happen is that each time I click a PDF filename in the first listbox with the mouse or with up or down arrow keys, the application should display the contents of the first page of the selected file in the text box.
This is how my GUI looks and how it should function
https://i.stack.imgur.com/xrkvo.jpg
I have been successful in all other requirements so far except the part where when I select a filename in the first listbox, the contents of the first page of the PDF should be displayed in the text box.
Here is my code for populating the listboxes and text box. The contents of my 2D set pdfFiles is [['PDF1 filename', 'PDF1 total pages', 'PDF1 text content of first page'], ['PDF2 filename', 'PDF2 total pages', 'PDF2 text content of first page'], ... etc.
===========Setting the Listboxes and Textbox=========
scrollbar = Scrollbar(list_2)
scrollbar.pack(side=RIGHT, fill=Y)
list_1.config(yscrollcommand=scrollbar.set)
list_1.bind("<MouseWheel>", scrolllistbox2)
list_2.config(yscrollcommand=scrollbar.set)
list_2.bind("<MouseWheel>", scrolllistbox1)
txt_3 = tk.Text(my_window, font='Arial 10', wrap=WORD)
txt_3.place(relx=0.5, rely=0.12, relwidth=0.472, relheight=0.86)
scrollbar = Scrollbar(txt_3)
scrollbar.pack(side=RIGHT, fill=Y)
list_1.bind("<<ListboxSelect>>", CurSelect)
============Populating the Listboxes with the content of the 2D Set===
i = 0
while i < count:
list_1.insert(tk.END, pdfFiles[i][0])
list_2.insert(tk.END, pdfFiles[i][1])
i = i + 1
============Here is my code for CurSelect function========
def CurSelect(evt):
values = [list_1.get(idx) for idx in list_1.curselection()]
print(", ".join(values)) ????
========================
The print command above is just my test command to show that I have successfully extracted the selected item in the listbox. What I need now is to somehow link that information to its corresponding page content in my 2D list and display it in the text box.
Something like:
1) select the filename in the listbox
2) link the selected filename to the filenames stored in the pdfFilename 2D set
3) once filename is found, identify the corresponding text of the first page
4) display the text of the first page of the selected file in the text box
I hope I am making sense. Please help.
You don't need much to finish it. You just need some small things:
1. Get the selected item of your listbox:
selected_indexes = list_1.curselection()
first_selected = selected_indexes[0] # it's possible to select multiple items
2. Get the corresponding PDF text:
pdf_text = pdfFiles[first_selected][2]
3. Change the text of your Text widget: (from https://stackoverflow.com/a/20908371/8733066)
txt_3.delete("1.0", tk.END)
txt_3.insert(tk.END, pdf_text)
so replace your CurSelect(evt) method with this:
def CurSelect(evt):
selected_indexes = list_1.curselection()
first_selected = selected_indexes[0]
pdf_text = pdfFiles[first_selected][2]
txt_3.delete("1.0", tk.END)
txt_3.insert(tk.END, pdf_text)

Interactive labeling of images in jupyter notebook

I have a list of pictures:
pictures = {im1,im2,im3,im4,im5,im6}
Where
im1:
im2:
im3:
im4:
im5:
im6:
I want to assign the pictures to labels (1,2,3,4 etc.)
For instance, here pictures 1 to 3 belong to label 1, picture 4 belongs to label 2, picture 5 to label 3, and picture 6 to label 4.
-> label = {1,1,1,2,3,4}
Since I need to see the images when I label them, I need a method to do that while labeling them. I was thinking of creating an array of images:
And then I define the ranges by clicking on the first and last picture belonging to the same labels, so for example:
What do you think ? Is this somehow possible ?
I would like to assign different labels to different ranges of pictures.
For instance: When one has finished selecting the first label one could indicate it by a Double-click and then do the selection of the second label range, then Double-click, then do the selection of the third label range, then Double-click, then do the selection of the fourth label range, etc.
It does not have to be Double-clicking to change the selection of the labels, it could also just be a buttom or any other idea that you might have.
In the end one should have the list of labels.
Essentially, most of the interaction you are looking for boils down to being able to display images, and detect clicks on them in real time. As that is the case, you can use the jupyter widgets (aka ipywidgets) module to achieve most (if not all) of what you are looking for.
Take a look at the button widget which is described here with explanation on how to register to its click event. The problem - we can't display an image on a button, and I didn't find any way to do this within the ipywidgets documentation. There is an image widget, but it does not provide an on_click event. So construct a custom layout, with a button underneath each image:
COLS = 4
ROWS = 2
IMAGES = ...
IMG_WIDTH = 200
IMG_HEIGHT = 200
def on_click(index):
print('Image %d clicked' % index)
import ipywidgets as widgets
import functools
rows = []
for row in range(ROWS):
cols = []
for col in range(COLS):
index = row * COLS + col
image = widgets.Image(
value=IMAGES[index], width=IMG_WIDTH, height=IMG_HEIGHT
)
button = widgets.Button(description='Image %d' % index)
# Bind the click event to the on_click function, with our index as argument
button.on_click(functools.partial(on_click, index))
# Create a vertical layout box, image above the button
box = widgets.VBox([image, button])
cols.append(box)
# Create a horizontal layout box, grouping all the columns together
rows.append(widgets.HBox(cols))
# Create a vertical layout box, grouping all the rows together
result = widgets.VBox(rows)
You can technically also write a custom widget to display an image and listen for a click, but I simply don't believe it's worth your time and effort.
Good luck!
The qsl package provides widgets that do this. For your case, the following code would allow you to label images in batches. Full disclosure, qsl is a project I started because I, like you, wanted to label images from inside Jupyter notebooks.
import qsl
from IPython.display import display
labeler = qsl.MediaLabeler(
items=[
{"target": "https://i.stack.imgur.com/cML6z.jpg"},
{"target": "https://i.stack.imgur.com/6EVAP.jpg"},
{"target": "https://i.stack.imgur.com/CAxUw.jpg"},
{"target": "https://i.stack.imgur.com/8fhan.jpg"},
{"target": "https://i.stack.imgur.com/eMXn5.jpg"},
{"target": "https://i.stack.imgur.com/YFBfM.jpg"}
],
# Optional, you can also configure the labeler from
# the UI.
config={
"image": [
{
"name": "Type",
"options": [
{"name": "Foo"},
{"name": "Bar"}
]
}
]
},
# Optional, set to 1 if you want to label
# one image at a time.
batch_size=4,
# Optionally, save labels to JSON. You
# can also get the labels using `labeler.items`.
jsonpath="labels.json"
)
display(labeler)
This generates a UI that looks like this.
Here is a Google Colab notebook that shows how to do this in Google Colab.

populate a list box with .csv items

I have this.
scrollbar = tk.Scrollbar(listbox)
scrollbar.pack(side=RIGHT, fill=Y)
listbox = tk.Listbox(root)
listbox.insert(1,'a')
listbox.pack()
listbox.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=listbox.yview)
with open('testCUR.csv', newline='') as csvfile:
spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
for row in spamreader:
print(', '.join(row),'\n')
I was wondering how to correctly populate the listbox with values from a .csv file?
And also why I cannot use the scroll bar correctly?
Once the list box is populated I would like to put the value of the last cell from the selection to a variable for use in a URL string. I havent found any tutorials for this so was looking for help here.
I have tried this.
listbox = tk.Listbox(root, height=1)
listbox.place(x=300,y=75)
with open('testCUR.csv', 'r') as f:
reader = csv.reader(f)
your_list = list(reader)
for item in your_list:
listbox.insert(end, item)
or this inputs only first entry
with open('testCUR.csv', 'r') as f:
reader = csv.reader(f)
your_list = list(reader)
for item in your_list:
listbox.insert(1, item)
Once I have all the values in the list box and it is scrollable which I would love if it was just damn.
listbox = tk.Listbox(root, height=1, scroll=auto)
I need to be able to use only the currency code which is the last value in the .csv file and use it as the selected value and then use it in a variable for the url. The .csv file looks like this.
Algeria د.ج DZD
Andorra € EUR
Angola Kz AOA
Anguilla $ XCD
Antigua and Barbuda $ XCD
Argentina $ ARS
Armenia AMD
Aruba ƒ AWG
Ascension Island £ (*none*)
I am also trying pandas but am new to it because it looks much easier and cleaner to use.
csv_file = ('testCUR.csv')
df = pd.read_csv(csv_file)
saved_col = df['CODE']
for item in df:
listbox.insert(end, saved_col)
Always error. NameError: name 'end' is not defined.
Happens with END also
I was wondering how to correctly populate the listbox with values from a .csv file?
To insert text into a listbox you must give it an index to tell it where to insert. The index is a string that is either a number, or the string "end". In your case you used a variable named end, which of course doesn't exist.
You can insert the text like this:
listbox.insert("end", item)
And also why I cannot use the scroll bar correctly?
You haven't described why your scrollbar is not correct.
Making a scrollbar works requires two-way conversation. The scrollbar must be told what widget to scroll (via the command attribute, and the widget needs to know which scrollbar to update when it is scrolled (via the yscrollcommand or xscrollcommand attribute).
It's also good to explicitly set whether the scrollbar is horizontal or vertical, though in your case it's vertical which is the default.
And finally, it's generally the best practice to make the scrollbar and the widget being scrolled to have the same parent. You made the mistake of making the scrollbar a child of the listbox. Instead, make it a child of whatever the listbox is a child of. You also made the mistake of trying to make it the parent of the listbox before you created the listbox. A widget must exist before you can give it children.
Here is how to create the listbox and scrollbar:
listbox = tk.Listbox(root)
scrollbar = tk.Scrollbar(root, orient="vertical", command=listbox.yview)
listbox.configure(yscrollcommand=scrollbar.set)

Refer to views, models and widgets using variables in PyQt

I am using Pyqt5 and I have a tab widget which has 4 tabs which contain exactly the same layout of widgets - a table view and a few buttons. The difference is that each tab displays a slightly different view of the data based on one database field which is an integer of 1 to 4. Below is a snippet of code which sets up the model and view:
def setup_folio1(self):
self.folio1_model = QSqlQueryModel(self)
self.folio1_model.setQuery("SELECT trans_timestamp, person, charge_code, description, dr, cr, id from "
" transactions where folio = 1 and account = '{0}' ORDER BY trans_timestamp".format(myapp.res_id))
self.folio1_model.setHeaderData(0, Qt.Horizontal, "Time stamp")
self.folio1_model.setHeaderData(1, Qt.Horizontal, "User")
self.folio1_model.setHeaderData(2, Qt.Horizontal, "Charge code")
self.folio1_model.setHeaderData(3, Qt.Horizontal, "Description")
self.folio1_model.setHeaderData(4, Qt.Horizontal, "Debit")
self.folio1_model.setHeaderData(5, Qt.Horizontal, "Credit")
self.folio1_view = self.ui.folio1_1
self.folio1_view.setModel(self.folio1_model)
self.folio1_view.setColumnWidth(0, 120)
self.folio1_view.setColumnWidth(1, 80)
self.folio1_view.setColumnWidth(2, 80)
self.folio1_view.setColumnWidth(3, 395)
self.folio1_view.setColumnWidth(4, 50)
self.folio1_view.setColumnWidth(5, 50)
self.folio1_view.setColumnHidden(6, True)
self.folio1_view.setSelectionBehavior(QTableView.SelectRows)
self.folio1_view.setDragEnabled(True)
cr_total = dr_total = 0
for i in range(self.folio1_model.rowCount()):
dr_total = dr_total + self.folio1_model.index(i,4).data()
cr_total = cr_total + self.folio1_model.index(i,5).data()
self.ui.folio1_balance.setText(str(dr_total - cr_total))
def setup_folio2(self):
self.folio2_model = QSqlQueryModel(self)
As you can see, I am repeating much of the same code to set up what is essentially different by one digit - whether it is a parameter on the SQL query or more importantly the names of widgets.
As being new to PyQT I haven't been able to figure out how I can refer to these models, views and widgets variably. I would like to have a method like
def setup_folios(self, folio_num=0):
and either loop to call the method or loop inside the method. I would like to vary the number of tabs based on the data but that is phase II. I have found tabwidgets.count() but I would like to refer to the models, views and widgets in the code using an integer.

Resources