Attaching a scrollbar to a listbox - python-3.x

I know that there have been some other questions about this, but was hoping to get some help with my current frame configuration as seen below in the code snippet. I have also attached some images, first is with no scrollbar set up. Second is when I uncommented out my scrollbar code.
Frame setup:
# -- Top Frame -- #
self.top = Frame(master, height = 71, bg = self.topColor)
self.top.pack(fill = X)
self.bottom = Frame(master, height = 650, bg = self.bottomColor)
self.bottom.pack(fill = X)
Listbox setup:
# myscroll = Scrollbar(self.bottom, orient = VERTICAL)
Label(self.bottom, text = 'Files Chosen:', bg = self.bottomColor).place(x = 4, y = 110)
self.qListBox = Listbox(self.bottom, width = 30, selectmode = SINGLE) # I did have yscrollcommand = myscroll
# myscroll.config(command = self.qListBox.yview)
# myscroll.pack(side = RIGHT, fill = Y)
self.qListBox.place(x = 4, y = 130)
Label(self.bottom, text = 'Deployment Queue:', bg = self.bottomColor).place(x = 360, y = 110)
self.dListBox = Listbox(self.bottom, width = 30, selectmode = MULTIPLE)
self.dListBox.place(x = 360, y = 130)

Figured out how to resolve this. Created three frames that are inside of my master frame as seen below:
my_frame = Frame(self.master)
my_secondF = Frame(self.master)
my_thirdF = Frame(self.master)
Once I did this I simply put my Lisboxes inside of those frames and placed them accordingly and configured my scrollbars
self.qListBox = Listbox(my_frame, yscrollcommand=myscroll_bar, width = 32, selectmode = SINGLE)
I still, however, appreciate all the replies :)

Related

How to change color of mark on topoplot interactively?

I want to create interactive line- and topoplot depending on menu. I figured out how to make red the line chosen in menu, but it doesn't work for topoplot marks (black circles inside topoplot). I can change it manually (cmap[][4] = RGB{N0f8}(1.0,0.0,0.0)), but how to do that interactively?
f = Figure(backgroundcolor = RGBf(0.98, 0.98, 0.98), resolution = (1500, 700))
ax = Axis(f[1:3, 1], xlabel = "Time [s]", ylabel = "Voltage amplitude [µV]")
N = 1:length(pos) #1:4
hidespines!(ax, :t, :r)
GLMakie.xlims!(-0.3, 1.2)
hlines!(0, color = :gray, linewidth = 1)
vlines!(0, color = :gray, linewidth = 1)
times = range(-0.3, length=size(dat_e,2), step=1 ./ 128)
lines = Dict()
for i in N
mean_trial = mean(dat_e[i,:,:],dims=2)[:,1]
line = lines!(times, mean_trial, color = "black")
lines[i] = line
end
hidedecorations!(ax, label = false, ticks = false, ticklabels = false)
topo_axis = Axis(f[2, 2], width = 178, height = 178, aspect = DataAspect())
Makie.xlims!(low = -0.2, high = 1.2)
Makie.ylims!(low = -0.2, high = 1.2)
topoMatrix = eegHeadMatrix(pos[N], (0.5, 0.5), 0.5)
cmap = Observable(collect(ColorScheme(range(colorant"black", colorant"black", length=30))))
#cmap[][4] = RGB{N0f8}(1.0,0.0,0.0)
topo = eeg_topoplot!(topo_axis, N, # averaging all trial of 30 participants on Xth msec
raw.ch_names[1:30];
positions=pos, # produced automatically from ch_names
interpolation=NullInterpolator(),
enlarge=1,
#colorrange = (0, 1), # add the 0 for the white-first color
colormap = cmap[],
label_text=false)
hidedecorations!(current_axis())
hidespines!(current_axis())
num_prev = 0
menu = Menu(f[3, 2], options = raw.ch_names[1:30], default = nothing)#, default = "second")
on(menu.selection) do selected
if selected != nothing
num = findall(x->x==menu.selection[], raw.ch_names[1:30])[]
if num_prev != 0
lines[num_prev].color = "black"
cmap[][num] = RGB{N0f8}(1.0,0.0,0.0)
end
lines[num].color = "red"
cmap[][num] = RGB{N0f8}(1.0,0.0,0.0)
num_prev = num
end
end
notify(menu.selection)
#print(cmap[])
f
We solved this by putting this string at the end of the menu.selection section:
notify(lines)
It works, because lines() automatically creates Observable.

Tkinter How to make listbox appear over a frame

making an F1 application where users can type in a driver from the current grid [supported via autofill/suggestions], and then API fetches relevant stats
The issue I'm having is that I want the listbox to appear over another frame (called left_frame). However, what this does is that the listbox goes under left_frame , and not over it. Any thoughts of how to make it appear over the frame?
some approaches that I tried:
used .lift(), but .lift() only seems to work when it's relative to objects in the same frame
since I currently use .grid and placed the listbox in the root frame, I initially tried to put it in top_frame, but it then expands the top_frame. Since I have positioned all frames using .place(), I don't think I can use propagate(False) (I tried it , didn't work)
Here's a picture of the issues
Here's my code so far:
#import necessary modules
from tkinter import *
from tkinter import ttk
from PIL import ImageTk, Image
from tkinter import messagebox
import requests
import json
#set up main window components
root = Tk()
root.title("F1 Desktop Application")
root.geometry("500x600")
root.configure(bg="white")
#since same directory, can just use filename
root.iconbitmap("formula1_logo.ico")
#images
#creating canvas for image to go into
#canvas_f1_logo = Canvas(top_frame, width = 5, height = 5)
#canvas.grid(row = 0, column = 1)
#acquire image
#formula1_logo = ImageTk.PhotoImage(Image.open("formula1_logo.png"))
#resize image
#resized_formula1_logo = formula1_logo.resize((3,3), Image.ANTIALIAS)
#new_formula1_logo = ImageTK.PhotoImage(resized_formula1_logo)
#canvas.create_image(5,5, anchor = NW, image = new_formula1_logo)
#functions
#generate 2022 drivers-list [can scale to drivers-list by changing the]
drivers_list_request = requests.get("http://ergast.com/api/f1/2022/drivers.json")
#initialize empty-list
drivers_list = []
drivers_list_object = json.loads(drivers_list_request.content)
for elements in drivers_list_object["MRData"]["DriverTable"]["Drivers"]:
drivers_list.append(elements["givenName"] + " " + elements["familyName"])
#set up frames [main frames, can put frames within frames if needed]
#frame for search bar + magnifying glass
top_frame = LabelFrame(root, padx = 80, pady = 15)
top_frame.place(relx = 0.5, rely = 0.2, anchor = CENTER)
header_label = Label(top_frame, text = "F1 2022 Drivers App", pady = 20, font = ("Arial bold",14))
header_label.grid(row = 0, column = 0, pady = 2 )
search_button = Button(top_frame, text = "search", padx = 2, pady = 2)
search_button.grid(row = 1, column = 1)
# Update the Entry widget with the selected item in list
def check(e):
v= entry.get()
if v=='':
hide_button(menu)
else:
data=[]
for item in drivers_list:
if v.lower() in item.lower():
data.append(item)
update(data)
show_button(menu)
def update(data):
# Clear the Combobox
menu.delete(0, END)
# Add values to the combobox
for value in data:
menu.insert(END,value)
def fillout(event):
try:
entry.delete(0,END)
entry.insert(0,menu.get(menu.curselection()))
#handle a complete deletion of entry-box via cursor double tap
except:
pass
def hide_button(widget):
widget.grid_remove()
def show_button(widget):
widget.grid()
# Create an Entry widget
entry= Entry(top_frame)
entry.grid(row = 1, column = 0)
entry.bind('<KeyRelease>',check)
# Create a Listbox widget to display the list of items
menu= Listbox(root)
menu.grid(row = 2, column = 0, padx = 165, pady = 165)
menu.bind("<<ListboxSelect>>",fillout)
menu.lift()
# Add values to our combobox
hide_button(menu)
left_frame = LabelFrame(root, padx = 30, pady = 30)
left_frame.place(relx = 0.24, rely = 0.5, anchor = CENTER)
bottom_left_frame = LabelFrame(root, padx = 30, pady = 30)
bottom_left_frame.place(relx = 0.24, rely = 0.82, anchor = CENTER)
bottom_right_frame = LabelFrame(root, padx = 30, pady = 30)
bottom_right_frame.place(relx = 0.6, rely = 0.82)
basic_info = Label(left_frame, text = "Basic Info ", font = ("Arial bold",14))
basic_info.grid(row = 0, column = 0, pady = 3)
full_name = Label(left_frame, text = "Full Name : ")
full_name.grid(row = 1, column = 0, pady = 2)
driver_code = Label(left_frame, text = "Driver Code : ")
driver_code.grid(row = 2, column = 0, pady = 2)
nationality = Label(left_frame, text = "Nationality : ")
nationality.grid(row = 3, column = 0, pady = 2)
F1_career = Label(bottom_left_frame, text = "F1 Career ", font = ("Arial bold",14))
F1_career.grid(row = 0, column = 0, pady = 3)
wins = Label(bottom_left_frame, text = "Wins :")
wins.grid(row = 1, column = 0, pady = 2)
poles = Label(bottom_left_frame, text = "Poles :")
poles.grid(row = 2, column = 0, pady = 2)
drivers_championships = Label(bottom_left_frame, text = "Championships :")
drivers_championships.grid(row = 3, column = 0 , pady = 2)
F1_22_stats = Label(bottom_right_frame, text = "F1 22 Stats", font = ("Arial bold",14))
F1_22_stats.grid(row = 0, column = 0, pady = 3)
root.mainloop()
would appreciate the help!

Builiding a selection from a Dataframe

i want to build a selection from a dataframe based on double search-arguments. In detail:
I have build a search within a given Dataframe based on one value. This value can be given multiple times. The difference can be found in the row of the value. Here is a example:
TECHNIKART FSZ BEZEICHNUNG FIRMA PRODUKT_SPANNUNG KLIMA EW_KW MENGE_KW LEISTUNG_KW Ü
I get this Dataframe from following search in a bigger Dataframe:
key = '71E'
try:
geraet_dat2 = geraet_dat[geraet_dat.FSZ == key]
lang = len(geraet_dat2.index)
print(geraet_dat2)
My idea is now to have a if-else-query based on the length of the Dataframe. If the Dataframe has the lenght 1 i will print the values of the needed cells. If the Dataframe is longer than 1 the following popup appears:
def abfrage_selektion():
popup_selektion = Tk()
frame_selek = Frame(popup_selektion)
frame_selek.pack()
popup_selektion.configure(bg="Snow2")
popup_selektion.geometry('300x250')
popup_selektion.title('Bitte Gerät auswählen!')
LABEL_SELEKTION = LabelFrame(popup_selektion, text="Bitte Gerät auswählen: ")
LABEL_SELEKTION.place(x = 2, y = 2, width = 296, height = 246)
INFO = ttk.Label(LABEL_SELEKTION, justify=CENTER, text="Diese FSZ ist mehrfach verfügbar! \nBitte das entsprechende Gerät wählen!")
INFO.place(x = 50, y = 5)
SEPTR_1 = ttk.Separator(LABEL_SELEKTION, orient=HORIZONTAL)
SEPTR_1.place(x = 5, y = 40, width = 280)
GERAET = ttk.LabelFrame(LABEL_SELEKTION, text="Geräte: ")
GERAET.place(x = 15, y = 50, width = 260, height = 120)
LISTE = Listbox(GERAET, yscrollcommand=True)
LISTE.insert(1, '1')
LISTE.insert(2, '2')
LISTE.insert(3, '3')
LISTE.insert(4, '4')
LISTE.place(x = 5, y = 2, width = 240, height = 90)
SEPTR_2 = ttk.Separator(LABEL_SELEKTION, orient=HORIZONTAL)
SEPTR_2.place(x = 5, y = 180, width = 280)
BUTTON_OK = ttk.Button(LABEL_SELEKTION, text="OK")
BUTTON_OK.place(x = 5, y = 190, width = 280, height = 30)
that far everything is nice an clear for me.
But now the point i dont know how to solve:
In the popup i want a selection from the given Dataframe with more than one Dataset to select the wanted Data. The criteria for the selection should be 'BEZEICHNUNG' and 'PRODUKT_SPANNUNG'.
Do you have any ideas how i can do this? I searched in the web but didnt find a good solution for that.
Thank you for you help!

How to change background color in ttk python

I've made a simple gui age converter app but i want to change its bg color to black.
The problem is in the ttk frame.i don't know how to configure its bg color.
I have tried different methods but that didn't work.
i would be grateful if you guys could help.
here is the code
from tkinter import *
from tkinter import ttk
from PIL import Image
def calculate(*args):
try:
age_sec = int(age.get())
age_sec = age_sec * 12 * 365 * 24 * 60 * 60
age_seconds.set(age_sec)
except:
age_seconds.set('Either the field is empty or \n value is not numeric.')
root = Tk()
root.title("Converter")
root.configure(background="black")
mainframe = ttk.Frame(root, padding = "6 6 12 12")
mainframe.grid(column = 0, row = 0, sticky = (N, W, E, S))
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
#mainframe['borderwidth'] = 2
#mainframe['relief'] = 'groove'
age = StringVar()
age_seconds = StringVar()
ttk.Label(mainframe, foreground = "#4D4E4F", text = "Enter your Age: ").grid(column = 1, row = 1, sticky = E)
age_entry = ttk.Entry(mainframe, width = 30, textvariable = age)
age_entry.grid(column = 2, row = 1, sticky = (W, E))
ttk.Label(mainframe, foreground = "#4D4E4F", text = "your age in seconds is ").grid(column = 1, row = 2, sticky = (E))
ttk.Label(mainframe, textvariable = age_seconds, background = "lightyellow", foreground = "#727475", width = 30).grid(column = 2, row = 2, sticky = W)
#Mouse Events...\\
butt_image = PhotoImage(file = 'images.gif')
ttk.Button(mainframe, compound = TOP, text = "Hit Now", image =butt_image, cursor = "hand2", width= 30, command = calculate).grid(column = 2, row = 4, sticky = W)
l2 = ttk.Label(mainframe,foreground = "#4D4E4F", text = "Mouse Events: ").grid(column = 1, row = 3, sticky = E)
l = ttk.Label(mainframe,background = "lightyellow", foreground = "#727475", text = 'Measurement is starting...', width = 30)
l.grid(column = 2, row = 3, sticky = W)
l.bind('<Enter>', lambda e: l.configure(text = 'Moved Mouse Inside'))
l.bind('<Leave>', lambda e: l.configure(text = 'Mouse Moved Out'))
l.bind('<1>', lambda e: l.configure(text = 'left Mouse clicked'))
l.bind('<Double-1>', lambda e: l.configure(text = 'Double clicked'))
l.bind('<B1-Motion>', lambda e: l.configure(text = 'Left button drag to %d, %d' %(e.x, e.y)))
image = PhotoImage(file = 'waves.gif')
ttk.Label(mainframe, compound = CENTER, text = "Image text", font = ('roman', 9, 'normal'), foreground ='green', image = image).grid(column = 3, row = 1, sticky = (N, E))
#if '__name__' == '__main__':
for child in mainframe.winfo_children(): child.grid_configure(padx = 15, pady = 15)
age_entry.focus()
root.bind('<Return>', calculate)
root.mainloop()
A ttk.Frame does not have a background / bg option. To change it you need to use style.
See ttk.Frame Info
If you don't really need to use a ttk.Frame you can just switch to a tkinter.Frame

updating tkinter window for text background changes

Trying to show a green or red background in the text field of the answer to the simple addition quizzer.
Currently in PyCHarm complains that:
Entry.grid_configure(background = "red")
TypeError: grid_configure() missing 1 required positional argument: 'self'
0
I can't seem to figure this out. Any help is appreciated.
Here's the code so far:
from tkinter import *
import random
class MainGUI:
def __init__(self):
window = Tk() # Create the window
window.title("Addition Quizzer") # Set the title
#window.width(len(window.title()))
self.number1 = random.randint(0, 9)
self.number2 = random.randint(0, 9)
Label(window, text = "+").grid(row = 2, column = 1, sticky = E)
Label(window, text = "Answer").grid(row = 3, column = 1, sticky = W)
self.firstNumber = StringVar()
Label(window, text = self.number1, justify = RIGHT).grid(row = 1, column = 2)
self.secondNumber = StringVar()
Label(window, text = self.number2, justify = RIGHT).grid(row = 2, column = 2)
self.entry = StringVar()
Entry(window, textvariable = self.entry, justify = CENTER, width = 4, background = "grey").grid(row = 3, column = 2)
Button(window, text = "Answer:", command = self.computeAnswer).grid(row = 4, column = 1, sticky = E)
self.result = StringVar()
Label(window, textvariable = self.result).grid(row = 4, column = 2)
window.mainloop() # Create the event loop
def computeAnswer(self):
self.result.set(format(self.number1 + self.number2))
if self.entry == self.result:
self.displayCorrect()
else:
self.displayIncorrect()
def displayCorrect(self):
# self.correctAnswer = "Correct"
# Label(self.window, text = self.correctAnswer, background = "green", justify = RIGHT).grid(row = 5, column = 2)
Entry.grid_configure(background = "green")
def displayIncorrect(self):
# self.incorrectAnswer = "Incorrect"
# Label(self.window, text = self.incorrectAnswer, background = "red", justify = RIGHT).grid(row = 5, column = 2)
Entry.grid_configure(background = "red")
MainGUI()
If you had read and followed this in the Help Center material, you would have reduced your code to the following, which still gets the same error message.
from tkinter import *
Entry.grid_configure()
The message refers to the fact that Python instance methods require an instance. This is usually done by calling the method on an instance instead of the class. Otherwise, an instance must be given as the first argument. Consider
mylist = []
mylist.append(1)
list.append(mylist, 2)
print(mylist)
# [1, 2]
You need to save a reference to your Entry box. Change
Entry(window, ..., background = "grey").grid(...)
to
self.entry = Entry(window, ..., background = "grey").grid(...)
I do not know if calling .grid_configure(background=color will do what you want.
This will, I am sure.
self.entry['background'] = 'red'

Resources