Tkinter: Widget not being applied to the top right hand corner of the screen(grid) - user-interface

I want to make a GUI for a voice assistant and for that when I try to use the grid option the label's get aligned at the centre of the screen when specified as column 2/3/4/5.
import tkinter
from tkinter import Canvas, Frame, Image, Label, StringVar, Tk, font
from tkinter.constants import ANCHOR, BOTTOM, E, END, GROOVE, RAISED, RIDGE, RIGHT, SUNKEN, TOP, Y
from typing import Text
window = tkinter.Tk()
window.title("App name")
window.geometry("320x640")
f = Frame(window)
x = f.grid_size()
# Add image file
bg = tkinter.PhotoImage(file = "Greybg.png")
# Show image using label
label1 = tkinter.Label( window, image = bg)
label1.place(x = 0, y = 0)
userimg = tkinter.PhotoImage(file = 'user1.png')
userlabel = tkinter.Label(window, image = userimg, bg = '#3D4154')
userlabel.place(relx = 1.0, rely = 0.01, anchor = 'ne')
def clicked():
print("Wow no error")
# Creating a photoimage object to use image
photo = tkinter.PhotoImage(file = "mic.png")
# here, image option is used to
# set image on button
micbtn = tkinter.Button(window, text = 'Click Me !', image = photo, bg = '#808588', border = 0, command = clicked).place(x = 142,y=580)
string_variable = tkinter.StringVar()
string_variable.set("User Text Here")
text = tkinter.Label(window, textvariable = string_variable, bg = "#80EAF7", wraplength= 250, pady = 1, padx = 1, fg = '#020402')
text.grid(row = 0, column=1, sticky=E,)
string_variable1 = tkinter.StringVar()
string_variable1.set("Assistant Reply here")
text1 = tkinter.Label(window, textvariable = string_variable1, wraplength= 250, pady = 1, padx = 1, fg = '#020402', font = ('Helvetica',8,'bold'))
text1.grid(row = 1, column=0)
window.resizable(0, 0)
window.mainloop()
In the above code, the icons get aligned like this, whereas I want the "User Text Here" to be at the top right-hand corner of the screen, how do I do that?

You can make columns 0 and 1 to use all the horizontal available space using
window.columnconfigure((0,1), weight=1)
Credit to https://stackoverflow.com/users/5317403/acw1668

Related

Tkinter Scrollbar works but scrollbar isnt visible

I have a scrollable text frame that scrolls properly, however, the scrollbar is not visible and im not sure why. I think it is because of the way im doing the scrollbar.pack but im not sure how to change it to get it to appear properly.
helpWin = Toplevel(root)
helpWin.title('')
helpWin.geometry("650x375")
helpWin.resizable(False, False)
helpFrame = Frame(helpWin)
helpFrame.place(x = 0, y = 0)
scrollbar = Scrollbar(helpFrame, orient = VERTICAL)
help_area = Text(helpFrame, wrap = Tkinter.WORD, font=('Georgia', 8), bg=bgColor, fg='black', yscrollcommand = scrollbar.set)
scrollbar.config(command = help_area.yview)
scrollbar.pack(side = 'right', fill = "y")
help_area.pack(side = "left", fill = "y", padx = (10,0), pady = 15)
Output Window:

Tkinter Scroll Window Does Not Scroll

Probably an easy question for a Tkinter veteran but why can't I scroll in my window?
If you run this code and add multiple data ports with the button, you will see what I mean.
Can anyone modify my code to make the scroll window work please?
I am not very well versed in Tkinter yet as I am with other similar tools in other languages so I'm sure there's going to be a lot to edit here.
from tkinter import *
fields = 'Buffer Depth \n(# of max-sized packets)', 'Payload Size \n(Max=1500bytes) ', 'Duplicate Quantity'
entries =[]
root = Tk()
root.title(string= 'Buffer Testing Tool')#create window title
root.geometry('500x750')#main window dimensions
root.configure(bg= 'crimson')
canvas = Canvas(root, height = 1000)
scroll_y = Scrollbar(root, orient="vertical", command=canvas.yview)
frame = Frame()
options = ["Transmit", "Receive"]
def makeform(root, fields):#this will organize and align the labels of the entries plus the entry fields
numberCheck =0
for field in fields:
row = Frame(canvas)
if (numberCheck==0):
firstES = Label(row, text= "Data Port 1", anchor = 'center', fg = "blue")#first ES label
firstES.pack()
DPtype = Label(row, text = 'Type', width=19, anchor = 'nw')
DPtype.pack(side= LEFT)
clicked= StringVar()
clicked.set(options[0])
drop = OptionMenu(row, clicked, *options)
drop.pack(side = LEFT, padx=5, pady= 5)
numberCheck=1
row.pack(side=TOP, fill=X, padx=5, pady= 5)
entries.append((field, clicked))
rowNew= Frame(canvas)
lab = Label(rowNew, width=20, text=field, anchor = 'w')
lab.pack(side=LEFT)
ent = Entry(rowNew)
ent.pack(side=RIGHT, expand = YES, fill=X)
rowNew.pack(side=TOP, fill=X, padx=5, pady= 5)
entries.append((field, ent))
else:
lab = Label(row, width=20, text=field, anchor = 'w')
ent = Entry(row)
row.pack(side=TOP, fill=X, padx=5, pady= 5)
lab.pack(side=LEFT)
ent.pack(side=RIGHT, expand = YES, fill=X)
entries.append((field, ent))
#return entries
def addEntryField():
next_row = int(len(entries)/4)+1
numberCheck =0
for field in fields:
row = Frame(canvas)
if (numberCheck==0):
nextES = Label(row, text= ('Data Port ' +str(next_row)), anchor = 'center', fg = "blue")
nextES.pack()
DPtype = Label(row, text = 'Type', width=19, anchor = 'nw')
DPtype.pack(side= LEFT)
clicked= StringVar()
clicked.set(options[0])
drop = OptionMenu(row, clicked, *options)
drop.pack(side = LEFT, padx=5, pady= 5)
numberCheck=1
row.pack(side=TOP, fill=X, padx=5, pady= 5)
entries.append((field, clicked))
rowNew= Frame(canvas)
lab = Label(rowNew, width=20, text=field, anchor = 'w')
lab.pack(side=LEFT)
ent = Entry(rowNew)
ent.pack(side=RIGHT, expand = YES, fill=X)
rowNew.pack(side=TOP, fill=X, padx=5, pady= 5)
entries.append((field, ent))
else:
lab = Label(row, width=20, text=field, anchor = 'w')
ent = Entry(row)
row.pack(side=TOP, fill=X, padx=5, pady= 5)
lab.pack(side=LEFT)
ent.pack(side=RIGHT, expand = YES, fill=X)
entries.append((field, ent))
#return entries
if __name__=='__main__':
b1 = Button(root, text = 'Generate XML File', command=root.quit, anchor = 'center')
b1.pack(side= BOTTOM, padx=5, pady=5)
b2 = Button(root, text = 'Run TTE-Build', command=root.quit, anchor = 'center')
b2.pack(side= BOTTOM, padx=5, pady=5)
b3 = Button(root, text = 'Run TTE-Plan', command=root.quit, anchor = 'center')
b3.pack(side= BOTTOM, padx=5, pady=5)
addEntryButton = Button(root, text= 'Add Data Port', fg = "Blue", command = addEntryField)
addEntryButton.pack(side= BOTTOM, anchor = 'n', padx=5, pady= 5)
ents = makeform(root, fields)#the creation of the window happens here
root.bind('<Return>', (lambda event, e=ents: fetch(e)))#after hitting 'Enter' this will collect the entered data from the user
canvas.create_window(0, 0, anchor= 'nw', window=frame)
canvas.update_idletasks()
canvas.configure(scrollregion=canvas.bbox("all"), yscrollcommand=scroll_y.set)
canvas.pack(fill='both', expand=True, side='left')
scroll_y.pack(fill='y', side='right')
root.mainloop()
def fetch(entries):#this will print what what the entry fields are named plus what is written down in the entry fields (regardless of the # of fields)
for entry in entries:
field = entry[0]
text = entry[1].get()#collect the entry for the fields
print('%s: "%s"' % (field, text))
def Message1():
XMLdone = Label(root, text= "XML File Generated!!")
XMLdone.pack()
def Message2():
XMLdone = Label(root, text= "TTE-Plan has been completed!!")
XMLdone.pack()
def Message3():
XMLdone = Label(root, text= "TTE-Build has been completed!!")
XMLdone.pack()
#Note: The Payload Size must always be greater than or equal to 18 bytes less than the corresponding VL.
There are several problems with the code. The first is that the frame you're adding to the canvas isn't a child of the canvas, but it needs to be. You should also give this window a more descriptive name than just frame.
So, create the frame like this:
canvas = Canvas(root, height = 1000)
scroll_y = Scrollbar(root, orient="vertical", command=canvas.yview)
inner_frame = Frame(canvas)
canvas.create_window(0, 0, anchor= 'nw', window=inner_frame)
The second problem is that you're not updating the scrollregion of the canvas with the inner frame changes. This is typically done by adding a binding to the <Configure> event of the inner frame:
inner_frame.bind("<Configure>", lambda event: canvas.configure(scrollregion=canvas.bbox("all")))
The third problem is that you're adding rows to the canvas rather than to the frame. You need to make your rows children of this inner frame.
for field in fields:
row = Frame(inner_frame)
...
rowNew= Frame(inner_frame)
...

Interacting with sg.image on a clic or a mouse fly over

I made a code using pysimplegui. it basically shows some images from a database based on a scanned number. it works but sometimes it could be useful to be able to increase the size of the image + it would make my user interface a bit more interactive
i want to have the possibility to either:
when i fly over the image with the mouse, i want the image to increase in size
have the possibility to clic on the image and have a pop-up of the image showing up (in a bigger size)
i am not sure on how to interact with a sg.image()
Below you will find a trunkated part of my code where i show my way of getting the image to show up.
layout = [
[
sg.Text("Numéro de boîte"),
sg.Input(size=(25, 1), key="-FILE-"),
sg.Button("Load Image"),
sg.Button("Update DATA"),
sg.Text("<- useless text ")
],
[sg.Text("Indicateur au max" , size = (120, 1),font = ("Arial", 18), justification = "center")],
[sg.Image(key="-ALV1-"),sg.Image(key="-ALV2-"), sg.Image(key="-ALV3-"), sg.Image(key="-ALV4-"), sg.Image(key="-ALV5-")],
[sg.Image(key="-ALV6-"),sg.Image(key="-ALV7-"), sg.Image(key="-ALV8-"), sg.Image(key="-ALV9-"), sg.Image(key="-ALV10-")],
[sg.Text("_" * 350, size = (120, 1), justification = "center")],
[sg.Text("Indicateur au milieu" , size = (120, 1),font = ("Arial", 18), justification = "center")],
[sg.Image(key="-ALV11-"),sg.Image(key="-ALV12-"), sg.Image(key="-ALV13-"), sg.Image(key="-ALV14-"), sg.Image(key="-ALV15-")],
[sg.Image(key="-ALV16-"),sg.Image(key="-ALV17-"), sg.Image(key="-ALV18-"), sg.Image(key="-ALV19-"), sg.Image(key="-ALV20-")],
[sg.Text("↓↓↓ ↓↓↓" , size = (120, 1),font = ("Arial", 18), justification = "center")],
]
ImageAlv1 = Image.open(PathAlv1)
ImageAlv1.thumbnail((250, 250))
bio1 = io.BytesIO()
ImageAlv1.save(bio1, format="PNG")
window["-ALV1-"].update(data=bio1.getvalue())
Using bind method for events, like
"<Enter>", the user moved the mouse pointer into a visible part of an element.
"<Double-1>", specifies two click events happening close together in time.
Using PIL.Image to resize image and io.BytesIO as buffer.
import base64
from io import BytesIO
from PIL import Image
import PySimpleGUI as sg
def resize(image, size=(256, 256)):
imgdata = base64.b64decode(image)
im = Image.open(BytesIO(imgdata))
width, height = size
w, h = im.size
scale = min(width/w, height/h)
new_size = (int(w*scale+0.5), int(h*scale+0.5))
new_im = im.resize(new_size, resample=Image.LANCZOS)
buffer = BytesIO()
new_im.save(buffer, format="PNG")
return buffer.getvalue()
sg.theme('DarkBlue3')
number = 4
column_layout, line = [], []
limit = len(sg.EMOJI_BASE64_HAPPY_LIST) - 1
for i, image in enumerate(sg.EMOJI_BASE64_HAPPY_LIST):
line.append(sg.Image(data=image, size=(64, 64), pad=(1, 1), background_color='#10C000', expand_y=True, key=f'IMAGE {i}'))
if i % number == number-1 or i == limit:
column_layout.append(line)
line = []
layout = [
[sg.Image(size=(256, 256), pad=(0, 0), expand_x=True, background_color='green', key='-IMAGE-'),
sg.Column(column_layout, expand_y=True, pad=(0, 0))],
]
window = sg.Window("Title", layout, margins=(0, 0), finalize=True)
for i in range(limit+1):
window[f'IMAGE {i}'].bind("<Enter>", "") # Binding for Mouse enter sg.Image
#window[f'IMAGE {i}'].bind("<Double-1>", "") # Binding for Mouse double click on sg.Image
element = window['-IMAGE-']
now = None
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED:
break
elif event.startswith("IMAGE"):
index = int(event.split()[-1])
if index != now:
element.update(data=resize(sg.EMOJI_BASE64_HAPPY_LIST[index]))
now = index
window.close()

Once I have created my rating scales and flipped the screen, they do not appear. What am I doing wrong?

Once I have created the ratingscales in PsychoPy, I cannot get them to show after showing my stimuli. What am I doing wrong?
Preparing experiment
Define window:
win = visual.Window(fullscr=True, color = 'Black')
Preparing stimuli
Pictures
Make list of images in my folder:
images = glob.glob("Yellow/*.jpg")
Randomize the order for pictures:
random.shuffle(images)
Prepare Fixation cross
stim_fix_left = visual.TextStim(win, '+') # Fixation cross is just the character "+". Units are inherited from Window when not explicitly specified.
stim_fix_left.pos = (0.5,0)
stim_fix_right = visual.TextStim(win, '+') # Fixation cross is just the character "+". Units are inherited from Window when not explicitly specified.
stim_fix_right.pos = (-0.5, 0)
Ratings
# the item to-be-rated or respond to:
whichred_left = visual.TextStim(win, text="Does left or right picture contain most red?", height=.04, units='norm')
whichred_left.pos = (0.5,0)
whichred_right = visual.TextStim(win, text="Does left or right picture contain most red?", height=.04, units='norm')
whichred_right.pos = (-0.5, 0)
Create stimuli
Show introduction message:
msg(intro, "white")
Show introduction to block:
msg(block_red, "red")
for i in images:
##Pictures
stim_fix_right.draw()
stim_fix_left.draw()
win.flip()#flip screen
core.wait(1.0)
#Picture 1
img1 = visual.ImageStim(win, image = i)#create visual stimuli
img1.pos = (0.4, 0)
img1.size = (0.5)
#Picture 2
img2 = visual.ImageStim(win, image = images[2])#create visual stimuli
img2.pos = (0.7, 0)
img2.size = (0.5)
#Picture 3
img3 = visual.ImageStim(win, image = i)#create visual stimuli
img3.pos = (-0.4, 0)
img3.size = (0.5)
#Picture 4
img4 = visual.ImageStim(win, image = images[2])#create visual stimuli
img4.pos = (-0.7, 0)
img4.size = (0.5)
#Drawing picures
img1.draw()#draw picture
img2.draw()#draw picture
img3.draw()#draw picture
img4.draw()#draw picture
win.flip()#flip screen
stopwatch.reset() #set clock
core.wait(1.0)
#Ratings
event.clearEvents()
# define window
winrating = visual.Window(size = (1280, 720), color = 'black', units='pix')
x, y = winrating.size # for converting norm units to pix
leftward = -0.35 * x / 2 # use pix units, because the drawing window's units are pix
rightward = -1 * leftward
# create a RatingScale object:
RatingLeft = visual.RatingScale(winrating, choices=map(str, range(1, 8)), mouseOnly=True, pos=(leftward, -y/6),
marker='circle', size=0.85, name='left')
RatingRight = visual.RatingScale(winrating, choices=map(str, range(1, 8)), low=0, high=8, markerStart=4,
leftKeys='left', rightKeys = 'right', acceptKeys='down', pos=(rightward, -y/6),
marker='circle', size=0.85, name='right')
while RatingLeft.noResponse or RatingRight.noResponse:
whichred_left.draw
whichred_right.draw
RatingLeft.draw()
RatingRight.draw()
winrating.flip()
if event.getKeys(['escape']):
core.quit()
There is no need to define a second window. Do all of your drawing into your originally defined window, win. This is created as a full screen window, so I'd assume that the second window, winrating is hidden behind it and any drawing wouldn't be visible.

How to rotate wxButton label?

I'm creating a Graphical User Interface with wxpython and I would like to insert one button with the label rotated vertically (see example below).
I have looked into docs and did some internet search but I can't find information how to do it.
Is it possible to do it? If yes any help would be very much appreciated.
Thank you.
Ivo
The only way that I can think of would be to use a BitmapButton that you have prepared.
You could do it programmatically e.g.
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, wx.ID_ANY, title, size=(400, 300))
panel = wx.Panel(self)
#Create an image
simg = wx.Image(150,25,True)
#Change from black to grey
simg.Replace(0,0,0,200,200,200)
bitmap = simg.ConvertToBitmap()
#Write required text
dc = wx.MemoryDC(bitmap)
dc.SetTextForeground(wx.BLACK)
dc.DrawText("Vertical Button", 10, 0)
del dc
img = bitmap.ConvertToImage()
img1 = img.Rotate90(False)
img2 = img.Rotate90()
bmp = img1.ConvertToBitmap()
bmp2 = img2.ConvertToBitmap()
btn1 = wx.BitmapButton(panel, -1, bmp, pos=(10,10))
btn2 = wx.BitmapButton(panel, -1, bmp2, pos=(350,10))
btn1.Bind(wx.EVT_BUTTON, self.BTN1)
btn2.Bind(wx.EVT_BUTTON, self.BTN2)
#Just for fun create a button with vertical text
simg = wx.Image(25,110,True)
#Change from black to grey
simg.Replace(0,0,0,200,200,200)
bitmap = simg.ConvertToBitmap()
#Write required text
dc = wx.MemoryDC(bitmap)
dc.SetTextForeground(wx.BLACK)
dc.DrawText("V", 7, 0)
dc.DrawText("e", 8, 15)
dc.DrawText("r", 8, 30)
dc.DrawText("t", 8, 45)
dc.DrawText("i", 8, 60)
dc.DrawText("c", 8, 75)
dc.DrawText("l", 8, 90)
del dc
img3 = bitmap.ConvertToImage()
bmp3 = img3.ConvertToBitmap()
btn3 = wx.BitmapButton(panel, -1, bmp3, pos=(175,10))
btn3.Bind(wx.EVT_BUTTON, self.BTN3)
def BTN1(self,event):
print("Left Button")
def BTN2(self,event):
print("Right Button")
def BTN3(self,event):
print("Middle Button")
app = wx.App()
frame = MyFrame(None, 'Vertical Buttons')
frame.Show()
app.MainLoop()

Resources