Pi GUI with an existing while loop - python

I am struggling to get a simple GUI to work with python (2.7) on Raspberry Pi (Buster).
I have tried Tkinter and PySimpleGUI but both of these effectively use while loops and I
already have such a loop in my program, which is working without issue.
Both Tkinter and PySimpleGUI block the main loop.
Attempts to run Tkinter and PySimpleGUI in a thread do not seem to work,
various elements are not thread compliant and hang with various error messages.
In any case it appears that once in a thread you can't interact with the GUI widgets
unless you create complicated queues and they are not thread safe.
All I am trying to do is write out the print 'Alert Door statement (last line of the while loop)
into a text field (something pretty / colourful)
and then have an alarm sound (GPIO) and a button which clears the alarm and text field.
Any thoughts apreciated, it appears the available Pi GUIs are just not suitable.
Be gentle, I am a newbie.
def vp_start_gui():
#'''Starting point when module is the main routine.'''
global val, w, root
root = tk.Tk()
top = Toplevel1 (root)
redalert_support.init(root, top)
root.mainloop()
w = None
def destroy_Toplevel1():
global w
w.destroy()
w = None
class Toplevel1:
def __init__(self, top=None):
'''This class configures and populates the toplevel window.
top is the toplevel containing window.'''
_bgcolor = '#d9d9d9' # X11 color: 'gray85'
_fgcolor = '#000000' # X11 color: 'black'
_compcolor = '#d9d9d9' # X11 color: 'gray85'
_ana1color = '#d9d9d9' # X11 color: 'gray85'
_ana2color = '#ececec' # Closest X11 color: 'gray92'
font13 = "-family {Segoe UI} -size 22"
font14 = "-family {Segoe UI} -size 21"
top.geometry("480x300+267+205")
top.minsize(120, 1)
top.maxsize(1028, 749)
top.resizable(1, 1)
top.title("SecuriCode RedAlert")
top.configure(background="#4339fb")
self.Button1 = tk.Button(top)
self.Button1.place(relx=0.333, rely=0.667, height=54, width=177)
self.Button1.configure(activebackground="#ececec")
self.Button1.configure(activeforeground="#000000")
self.Button1.configure(background="#ffff00")
self.Button1.configure(cursor="fleur")
self.Button1.configure(disabledforeground="#a3a3a3")
self.Button1.configure(font=font14)
self.Button1.configure(foreground="#000000")
self.Button1.configure(highlightbackground="#d9d9d9")
self.Button1.configure(highlightcolor="black")
self.Button1.configure(pady="0")
self.Button1.configure(text='''Clear Alarm''')
self.Text1 = tk.Text(top)
self.Text1.place(relx=0.125, rely=0.133, relheight=0.423, relwidth=0.756)
self.Text1.configure(background="white")
self.Text1.configure(font=font13)
self.Text1.configure(foreground="black")
self.Text1.configure(highlightbackground="#d9d9d9")
self.Text1.configure(highlightcolor="black")
self.Text1.configure(insertbackground="black")
self.Text1.configure(selectbackground="#c4c4c4")
self.Text1.configure(selectforeground="black")
self.Text1.configure(wrap="word")
vp_start_gui()
while 1:
#Receive data from LAN device
reply = s.recv(34)
#Receive replies from SMS Gateway
#smsreply = g.recv(34)
#Check for Lan device keep alive replies
if reply.find(alivereply) != -1:
#print 'Device alive'
print reply
#Check for valid Tag strings
if reply.find(tagstring) != -1:
print 'Tag string received'
print reply
#Send SMS alert message
doorcode = reply[5:6]
doornumber = int(doorcode, 16)
#print doornumber
tagcode = reply[8:9]
tagnumber = int(tagcode, 16)
#print tagnumber
print 'Alert Door ' +str(doornumber) + ' Tag ' +str(tagnumber)

Both Tkinter and PySimpleGUI block the main loop.
This is not true always.In my experience the best solution to stop tkinter from blocking the main program's loop is using root_window.update() instead of root_window.mainloop().
Using this will allow you to keep iterating through your while loop and also update your tkinter window.
Hope this helps.
UPDATE
Following your edit I had a look at your code myself.
I changed the function vp_start_gui() and created the root window outside the loop.The main goal of this code is to give you an idea about how to go about implementing your tkinter window correctly.Also about the buttons changing the active background when hovering over it; tkinter.tk Buttons don't have this feature by default.What they really mean by active backgroud is the background color when you click the button.Though there are ways to get this done using tkinter.tk I have showed an easy way to get what you want using tkinter.ttk.
import tkinter as tk
from tkinter import ttk
def vp_update_gui():
#'''Starting point when module is the main routine.'''
global val, w, root
#redalert_support.init(root, top)
root.update()
w = None
def destroy_Toplevel1():
global w
w.destroy()
w = None
class Toplevel1:
def __init__(self, top=None):
'''This class configures and populates the toplevel window.
top is the toplevel containing window.'''
_bgcolor = '#d9d9d9' # X11 color: 'gray85'
_fgcolor = '#000000' # X11 color: 'black'
_compcolor = '#d9d9d9' # X11 color: 'gray85'
_ana1color = '#d9d9d9' # X11 color: 'gray85'
_ana2color = '#ececec' # Closest X11 color: 'gray92'
font13 = "-family {Segoe UI} -size 22"
font14 = "-family {Segoe UI} -size 21"
top.geometry("480x300+267+205")
top.minsize(120, 1)
top.maxsize(1028, 749)
top.resizable(1, 1)
top.title("SecuriCode RedAlert")
top.configure(background="#4339fb")
s = ttk.Style()
s.configure('Kim.TButton', foreground='maroon',activeforeground="yellow")
self.Button1 = ttk.Button(top,style='Kim.TButton',text='''Clear Alarm''')
self.Button1.place(relx=0.333, rely=0.667, height=54, width=177)
self.Text1 = tk.Text(top)
self.Text1.place(relx=0.125, rely=0.133, relheight=0.423, relwidth=0.756)
self.Text1.configure(background="white")
self.Text1.configure(font=font13)
self.Text1.configure(foreground="black")
self.Text1.configure(highlightbackground="#d9d9d9")
self.Text1.configure(highlightcolor="black")
self.Text1.configure(insertbackground="black")
self.Text1.configure(selectbackground="#c4c4c4")
self.Text1.configure(selectforeground="black")
self.Text1.configure(wrap="word")
root = tk.Tk()
top = Toplevel1(root)
while 1:
vp_update_gui()
#Receive data from LAN device
reply = 's.recv(34)'
#Receive replies from SMS Gateway
#smsreply = g.recv(34)
#Check for Lan device keep alive replies
if reply == '-1':
#print 'Device alive'
print (reply)
#Check for valid Tag strings
if reply == '+1':
print ('Tag string received')
print (reply)
#Send SMS alert message
doorcode = reply[5:6]
doornumber = int(doorcode, 16)
#print doornumber
tagcode = reply[8:9]
tagnumber = int(tagcode, 16)
#print tagnumber
print( 'Alert Door ' +str(doornumber) + ' Tag ' +str(tagnumber) )

Your "blocking" problem is easily solving by running your PySimpleGUI program in "async mode". The docs have quite a bit of info about using timeouts on your read call and you'll find tons of demo programs that demonstrate this technique.
Here's a sample bit of code that loops, updating a counter every 100 milliseconds. You could add polling for a hardware condition or some set of conditions instead of updating the text. This is where you would add code to poll something.
import PySimpleGUI as sg
layout = [ [sg.Text('My Window')],
[sg.Text('Will output here', key='-OUT-')],
[sg.Button('Exit')] ]
window = sg.Window('A non-blocking window', layout)
count = 0
while True:
event, values = window.read(timeout=100) # returns every 100 milliseconds
if event == sg.WIN_CLOSED or event == 'Exit':
break
window['-OUT-'].update(f'Count={count}')
count += 1
window.close()

Related

Pygame & Tkinter Musikplayer

Please can you help me I don't know what´s the problem.
This is the Error:
[Running] python -u "c:\Users\Leon\Desktop\Page Guis\Music Player Pro ++\unknown.py"
File "c:\Users\Leon\Desktop\Page Guis\Music Player Pro ++\unknown.py", line 49
mixer.music.play()
^
TabError: inconsistent use of tabs and spaces in indentation
[Done] exited with code=1 in 0.651 seconds
My code:
# -*- coding: utf-8 -*-
from pygame import mixer
import tkinter.filedialog
import sys
try:
import tkinter as tk
except ImportError:
import tkinter as tk
try:
import tkinter.ttk
py3 = False
except ImportError:
import tkinter.ttk as ttk
py3 = True
import unknown_support
mixer.init()
def vp_start_gui():
'''Starting point when module is the main routine.'''
global val, w, root
root = tk.Tk()
top = Toplevel1 (root)
unknown_support.init(root, top)
root.mainloop()
w = None
def create_Toplevel1(rt, *args, **kwargs):
'''Starting point when module is imported by another module.
Correct form of call: 'create_Toplevel1(root, *args, **kwargs)' .'''
global w, w_win, root
#rt = root
root = rt
w = tk.Toplevel (root)
top = Toplevel1 (w)
unknown_support.init(w, top, *args, **kwargs)
return (w, top)
def destroy_Toplevel1():
global w
w.destroy()
w = None
def load_song():
mixer.music.load(tk.filedialog.askopenfile())
mixer.music.play()
def pause_song():
mixer.music.pause()
def resume():
mixer.music.unpause()
class Toplevel1:
def __init__(self, top=None):
'''This class configures and populates the toplevel window.
top is the toplevel containing window.'''
_bgcolor = '#d9d9d9' # X11 color: 'gray85'
_fgcolor = '#000000' # X11 color: 'black'
_compcolor = '#d9d9d9' # X11 color: 'gray85'
_ana1color = '#d9d9d9' # X11 color: 'gray85'
_ana2color = '#ececec' # Closest X11 color: 'gray92'
top.geometry("600x430+314+157")
top.minsize(120, 1)
top.maxsize(1370, 729)
top.resizable(1, 1)
top.title("Musik Player Pro ++")
top.configure(relief="groove")
top.configure(background="#000000")
top.configure(highlightbackground="#d9d9d9")
top.configure(highlightcolor="black")
self.menubar = tk.Menu(top,font="TkMenuFont",bg=_bgcolor,fg=_fgcolor)
top.configure(menu = self.menubar)
self.Canvas1 = tk.Canvas(top)
self.Canvas1.place(relx=0.867, rely=0.116, relheight=0.658
, relwidth=0.122)
self.Canvas1.configure(background="#000000")
self.Canvas1.configure(borderwidth="2")
self.Canvas1.configure(highlightbackground="#d9d9d9")
self.Canvas1.configure(highlightcolor="black")
self.Canvas1.configure(insertbackground="#4fff53")
self.Canvas1.configure(relief="ridge")
self.Canvas1.configure(selectbackground="#48ffff")
self.Canvas1.configure(selectforeground="white")
self.Label1 = tk.Label(top)
self.Label1.place(relx=0.667, rely=0.023, height=41, width=194)
self.Label1.configure(activebackground="#f9f9f9")
self.Label1.configure(activeforeground="black")
self.Label1.configure(background="#000000")
self.Label1.configure(disabledforeground="#a3a3a3")
self.Label1.configure(font="-family {Tw Cen MT Condensed} -size 14 -weight bold -slant italic -underline 1")
self.Label1.configure(foreground="#ffffff")
self.Label1.configure(highlightbackground="#d9d9d9")
self.Label1.configure(highlightcolor="black")
self.Label1.configure(text='''Volume''')
self.Scale1 = tk.Scale(top, from_=0.0, to=100.0)
self.Scale1.place(relx=0.767, rely=0.116, relwidth=0.0, relheight=0.665
, width=45, bordermode='ignore')
self.Scale1.configure(activebackground="#ececec")
self.Scale1.configure(background="#000000")
self.Scale1.configure(font="-family {Tw Cen MT Condensed} -size 14 -weight bold -underline 1")
self.Scale1.configure(foreground="#ffffff")
self.Scale1.configure(highlightbackground="#d9d9d9")
self.Scale1.configure(highlightcolor="black")
self.Scale1.configure(label="Volume")
self.Scale1.configure(relief="groove")
self.Scale1.configure(troughcolor="#d9d9d9")
self.tooltip_font = "TkDefaultFont"
self.Scale1_tooltip = \
ToolTip(self.Scale1, self.tooltip_font, '''Volume + / -''')
self.Label1_2 = tk.Label(top)
self.Label1_2.place(relx=0.017, rely=0.023, height=41, width=194)
self.Label1_2.configure(activebackground="#f9f9f9")
self.Label1_2.configure(activeforeground="black")
self.Label1_2.configure(anchor='w')
self.Label1_2.configure(background="#000000")
self.Label1_2.configure(compound='left')
self.Label1_2.configure(disabledforeground="#a3a3a3")
self.Label1_2.configure(font="-family {Tw Cen MT Condensed} -size 14 -weight bold -slant italic -underline 1")
self.Label1_2.configure(foreground="#ffffff")
self.Label1_2.configure(highlightbackground="#d9d9d9")
self.Label1_2.configure(highlightcolor="black")
self.Label1_2.configure(text='''Now playing:''')
self.Label2 = tk.Label(top)
self.Label2.place(relx=0.267, rely=0.279, height=101, width=164)
self.Label2.configure(activebackground="#f9f9f9")
self.Label2.configure(activeforeground="black")
self.Label2.configure(background="#000000")
self.Label2.configure(disabledforeground="#a3a3a3")
self.Label2.configure(font="-family {Segoe UI Black} -size 15 -weight bold -slant italic -underline 1")
self.Label2.configure(foreground="#ffffff")
self.Label2.configure(highlightbackground="#d9d9d9")
self.Label2.configure(highlightcolor="black")
self.Label2.configure(text='''Track Name''')
self.Button1 = tk.Button(top)
self.Button1.place(relx=0.017, rely=0.837, height=64, width=187)
self.Button1.configure(activebackground="#ffffff")
self.Button1.configure(activeforeground="#000000")
self.Button1.configure(background="#000000")
self.Button1.configure(cursor="fleur")
self.Button1.configure(disabledforeground="#a3a3a3")
self.Button1.configure(foreground="#ffffff")
self.Button1.configure(highlightbackground="#d9d9d9")
self.Button1.configure(highlightcolor="black")
self.Button1.configure(pady="0")
self.Button1.configure(relief="groove")
self.Button1.configure(text='''Resume''')
self.Button1.configure(command=resume)
self.Button1_1 = tk.Button(top)
self.Button1_1.place(relx=0.35, rely=0.837, height=64, width=187)
self.Button1_1.configure(activebackground="#ffffff")
self.Button1_1.configure(activeforeground="#000000")
self.Button1_1.configure(background="#000000")
self.Button1_1.configure(disabledforeground="#a3a3a3")
self.Button1_1.configure(foreground="#ffffff")
self.Button1_1.configure(highlightbackground="#d9d9d9")
self.Button1_1.configure(highlightcolor="black")
self.Button1_1.configure(pady="0")
self.Button1_1.configure(relief="groove")
self.Button1_1.configure(text='''Pause''')
self.Button1_1.configure(command=pause_song)
self.Button1_1_1 = tk.Button(top)
self.Button1_1_1.place(relx=0.683, rely=0.837, height=64, width=187)
self.Button1_1_1.configure(activebackground="#ffffff")
self.Button1_1_1.configure(activeforeground="#000000")
self.Button1_1_1.configure(background="#000000")
self.Button1_1_1.configure(disabledforeground="#a3a3a3")
self.Button1_1_1.configure(foreground="#ffffff")
self.Button1_1_1.configure(highlightbackground="#d9d9d9")
self.Button1_1_1.configure(highlightcolor="black")
self.Button1_1_1.configure(pady="0")
self.Button1_1_1.configure(relief="groove")
self.Button1_1_1.configure(text='''Load Song''')
self.Button1_1_1.configure(command=load_song)
from time import time, localtime, strftime
class ToolTip(tk.Toplevel):
"""
Provides a ToolTip widget for Tkinter.
To apply a ToolTip to any Tkinter widget, simply pass the widget to the
ToolTip constructor
"""
def __init__(self, wdgt, tooltip_font, msg=None, msgFunc=None,
delay=0.5, follow=True):
"""
Initialize the ToolTip
Arguments:
wdgt: The widget this ToolTip is assigned to
tooltip_font: Font to be used
msg: A static string message assigned to the ToolTip
msgFunc: A function that retrieves a string to use as the ToolTip text
delay: The delay in seconds before the ToolTip appears(may be float)
follow: If True, the ToolTip follows motion, otherwise hides
"""
self.wdgt = wdgt
# The parent of the ToolTip is the parent of the ToolTips widget
self.parent = self.wdgt.master
# Initalise the Toplevel
tk.Toplevel.__init__(self, self.parent, bg='black', padx=1, pady=1)
# Hide initially
self.withdraw()
# The ToolTip Toplevel should have no frame or title bar
self.overrideredirect(True)
# The msgVar will contain the text displayed by the ToolTip
self.msgVar = tk.StringVar()
if msg is None:
self.msgVar.set('No message provided')
else:
self.msgVar.set(msg)
self.msgFunc = msgFunc
self.delay = delay
self.follow = follow
self.visible = 0
self.lastMotion = 0
# The text of the ToolTip is displayed in a Message widget
tk.Message(self, textvariable=self.msgVar, bg='#FFFFDD',
font=tooltip_font,
aspect=1000).grid()
# Add bindings to the widget. This will NOT override
# bindings that the widget already has
self.wdgt.bind('<Enter>', self.spawn, '+')
self.wdgt.bind('<Leave>', self.hide, '+')
self.wdgt.bind('<Motion>', self.move, '+')
def spawn(self, event=None):
"""
Spawn the ToolTip. This simply makes the ToolTip eligible for display.
Usually this is caused by entering the widget
Arguments:
event: The event that called this funciton
"""
self.visible = 1
# The after function takes a time argument in milliseconds
self.after(int(self.delay * 1000), self.show)
def show(self):
"""
Displays the ToolTip if the time delay has been long enough
"""
if self.visible == 1 and time() - self.lastMotion > self.delay:
self.visible = 2
if self.visible == 2:
self.deiconify()
def move(self, event):
"""
Processes motion within the widget.
Arguments:
event: The event that called this function
"""
self.lastMotion = time()
# If the follow flag is not set, motion within the
# widget will make the ToolTip disappear
#
if self.follow is False:
self.withdraw()
self.visible = 1
# Offset the ToolTip 10x10 pixes southwest of the pointer
self.geometry('+%i+%i' % (event.x_root+20, event.y_root-10))
try:
# Try to call the message function. Will not change
# the message if the message function is None or
# the message function fails
self.msgVar.set(self.msgFunc())
except:
pass
self.after(int(self.delay * 1000), self.show)
def hide(self, event=None):
"""
Hides the ToolTip. Usually this is caused by leaving the widget
Arguments:
event: The event that called this function
"""
self.visible = 0
self.withdraw()
def update(self, msg):
"""
Updates the Tooltip with a new message. Added by Rozen
"""
self.msgVar.set(msg)
# ===========================================================
# End of Class ToolTip
# ===========================================================
if __name__ == '__main__':
vp_start_gui()
HERE IS THE ERROR PICTURE:
https://i.stack.imgur.com/eAs6q.png
https://i.stack.imgur.com/7qwDf.png
Thanks
Don't use a mix of tabs and space for indentation, it's not considered a good practice (python specific).
Now to fix it:
Go to terminal and type pip install autopep8
Once it's installed type the following command :
autopep8 -i yourfilename.py
3)You're good to go now!

Getting weird indentation error on python tkinter - unindent does not match any outer indentation level

I'm just adding 1 def with 2 lines of code before it gets indentation error. I'm trying to modify the code that generated from PAGE Tkinter GUI editor for login message box. I really don't know why this happens.
I did the exact same code as this guy on youtube and I tried to move the def into the far-most left neither right.
So what I'm trying to add is. def cancelLogin() inside the login page class. It shows me indentation error on def init(). Please help me to figure this out.
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# GUI module generated by PAGE version 4.20
# in conjunction with Tcl version 8.6
# Feb 07, 2019 05:38:55 AM EST platform: Linux
import sys
import tkMessageBox
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
try:
import ttk
py3 = False
except ImportError:
import tkinter.ttk as ttk
py3 = True
import jta_support
def vp_start_gui():
'''Starting point when module is the main routine.'''
global val, w, root
root = tk.Tk()
top = Login_page (root)
jta_support.init(root, top)
root.mainloop()
w = None
def create_Login_page(root, *args, **kwargs):
'''Starting point when module is imported by another program.'''
global w, w_win, rt
rt = root
w = tk.Toplevel (root)
top = Login_page (w)
jta_support.init(w, top, *args, **kwargs)
return (w, top)
def destroy_Login_page():
global w
w.destroy()
w = None
class Login_page:
def cancelLogin(self):
msg=tkMessageBox.askyesno("Login page","Are you sure , you want to cancel login?")
def __init__(self, top=None):
'''This class configures and populates the toplevel window.
top is the toplevel containing window.'''
_bgcolor = '#d9d9d9' # X11 color: 'gray85'
_fgcolor = '#000000' # X11 color: 'black'
_compcolor = '#d9d9d9' # X11 color: 'gray85'
_ana1color = '#d9d9d9' # X11 color: 'gray85'
_ana2color = '#ececec' # Closest X11 color: 'gray92'
font11 = "-family {DejaVu Sans} -size 10 -weight bold -slant " \
"roman -underline 0 -overstrike 0"
font17 = "-family {DejaVu Sans} -size 13 -weight bold -slant " \
"roman -underline 0 -overstrike 0"
self.style = ttk.Style()
if sys.platform == "win32":
self.style.theme_use('winnative')
self.style.configure('.',background=_bgcolor)
self.style.configure('.',foreground=_fgcolor)
self.style.configure('.',font="TkDefaultFont")
self.style.map('.',background=
[('selected', _compcolor), ('active',_ana2color)])
top.geometry("584x457+1039+55")
top.title("JTA Login")
top.configure(relief="ridge")
top.configure(background="#201856")
top.configure(highlightbackground="#000000")
self.btnLogin = tk.Button(top)
self.btnLogin.place(relx=0.634, rely=0.744, height=54, width=101)
self.btnLogin.configure(background="#201856")
self.btnLogin.configure(borderwidth="0")
self.btnLogin.configure(font=font11)
self.btnLogin.configure(highlightbackground="#201856")
self._img1 = tk.PhotoImage(file="../../Downloads/button.png")
self.btnLogin.configure(image=self._img1)
self.btnLogin.configure(padx="6m")
self.btnLogin.configure(pady="3m")
self.btnLogin.configure(text='''Login''')
self.btnLogin.configure(width=101)
self.btnExit = tk.Button(top)
self.btnExit.place(relx=0.223, rely=0.744, height=55, width=97)
self.btnExit.configure(activebackground="#ffffff")
self.btnExit.configure(background="#201856")
self.btnExit.configure(borderwidth="0")
self.btnExit.configure(font=font11)
self.btnExit.configure(highlightbackground="#201856")
self._img2 = tk.PhotoImage(file="../../Downloads/button(1).png")
self.btnExit.configure(image=self._img2)
self.btnExit.configure(padx="6m")
self.btnExit.configure(pady="3m")
self.btnExit.configure(text='''Exit''')
self.btnExit.configure(width=97)
self.txtUsername = tk.Entry(top)
self.txtUsername.place(relx=0.462, rely=0.372, height=40, relwidth=0.342)
self.txtUsername.configure(background="white")
self.txtUsername.configure(font="TkFixedFont")
self.txtPassword = tk.Entry(top)
self.txtPassword.place(relx=0.462, rely=0.547, height=40, relwidth=0.342)
self.txtPassword.configure(background="white")
self.txtPassword.configure(font="TkFixedFont")
self.txtPassword.configure(selectbackground="#c4c4c4")
self.Label1 = tk.Label(top)
self.Label1.place(relx=0.205, rely=0.372, height=40, width=100)
self.Label1.configure(background="#201856")
self.Label1.configure(font=font17)
self.Label1.configure(foreground="#ffffff")
self.Label1.configure(text='''Username''')
self.Label1_3 = tk.Label(top)
self.Label1_3.place(relx=0.205, rely=0.547, height=40, width=100)
self.Label1_3.configure(activebackground="#f9f9f9")
self.Label1_3.configure(background="#201856")
self.Label1_3.configure(font=font17)
self.Label1_3.configure(foreground="#ffffff")
self.Label1_3.configure(text='''Password''')
self.menubar = tk.Menu(top,font="TkMenuFont",bg=_bgcolor,fg=_fgcolor)
top.configure(menu = self.menubar)
self.TLabel1 = ttk.Label(top)
self.TLabel1.place(relx=0.154, rely=0.022, height=131, width=423)
self.TLabel1.configure(background="#201856")
self.TLabel1.configure(foreground="#000000")
self.TLabel1.configure(font="TkDefaultFont")
self.TLabel1.configure(relief='flat')
self.TLabel1.configure(text='''Tlabel''')
self.TLabel1.configure(width=423)
self._img3 = tk.PhotoImage(file="./jtalogo.png")
self.TLabel1.configure(image=self._img3)
if __name__ == '__main__':
vp_start_gui()
without the "def cancelLogin()" it works fine as usual
actual result :
File "./jta.py", line 52
def init(self, top=None):
^
IndentationError: unindent does not match any outer indentation level
You can try:
grep -C 7 "__init" YOUR_FILE.py | tr ' \t' '.*'
This will translate spaces into dots, and tabs into stars. Then you can check if there is a mismatch there.
This is the output when I tried it on the code you posted (from the question source):
$ grep -C 7 "__init" test.py | tr ' \t' '.*'
........w.=.None
....
....class.Login_page:
....
....*def.cancelLogin(self):
....**msg=tkMessageBox.askyesno("Login.page","Are.you.sure.,.you.want.to.cancel.login?")
....
........def.__init__(self,.top=None):
............'''This.class.configures.and.populates.the.toplevel.window.
...............top.is.the.toplevel.containing.window.'''
............_bgcolor.=.'#d9d9d9'..#.X11.color:.'gray85'
............_fgcolor.=.'#000000'..#.X11.color:.'black'
............_compcolor.=.'#d9d9d9'.#.X11.color:.'gray85'
............_ana1color.=.'#d9d9d9'.#.X11.color:.'gray85'.
............_ana2color.=.'#ececec'.#.Closest.X11.color:.'gray92'.
As stated by #tobias_k, there are tabs and spaces mixed in the lines you added.

Tkinter modify root window from TopLevel() widget

I am new to Tkinter/OOP and would like some help, I am currently stuck making a gui for a application. The functionality i want is that when a new window using the TopLevel() widget is spawned the button used for it to become disabled, which i have achieved. However the problem is enabling it after the spawned window is closed.
And in general how does one go about modifying the main tkinter root window from a TopLevel() widget using an OOP based approach. As i would like to do more stuff later on
The code is as follows:
from tkinter import *
from tkinter import ttk
class MainWindow:
def __init__(self, top):
_bgcolor = '#d9d9d9' # X11 color: 'gray85'
_fgcolor = '#000000' # X11 color: 'black'
_compcolor = '#d9d9d9' # X11 color: 'gray85'
_ana1color = '#d9d9d9' # X11 color: 'gray85'
_ana2color = '#d9d9d9' # X11 color: 'gray85'
font10 = "-family {Segoe UI} -size 10 -weight normal -slant " \
"roman -underline 0 -overstrike 0"
self.style = ttk.Style()
if sys.platform == "win32":
self.style.theme_use('winnative')
self.style.configure('.', background=_bgcolor)
self.style.configure('.', foreground=_fgcolor)
self.style.configure('.', font="TkDefaultFont")
self.style.map('.', background=
[('selected', _compcolor), ('active', _ana2color)])
self.top=top
self.top.geometry("214x96+462+349")
self.top.title("Test")
self.top.configure(background="#d9d9d9")
self.top.configure(highlightbackground="#d9d9d9")
self.top.configure(highlightcolor="black")
self.top.resizable(0, 0)
self.Btn_UI = Button(self.top)
self.Btn_UI.place(relx=0.50, rely=0.21, height=24, width=100)
self.Btn_UI.configure(activebackground="#d9d9d9")
self.Btn_UI.configure(activeforeground="#000000")
self.Btn_UI.configure(background="#d9d9d9")
self.Btn_UI.configure(command=self.Btn_UI_fun)
self.Btn_UI.configure(disabledforeground="#a3a3a3")
self.Btn_UI.configure(foreground="#000000")
self.Btn_UI.configure(highlightbackground="#d9d9d9")
self.Btn_UI.configure(highlightcolor="black")
self.Btn_UI.configure(pady="0")
self.Btn_UI.configure(text='''New Window''')
def Btn_UI_fun(self):
print('button')
root2 = Toplevel(self.top)
second = SettingsWindow(root2)
self.Btn_UI.configure(state="disabled")
return
class SettingsWindow():
def __init__(self, master):
self.master=master
self.master.geometry("214x96+462+349")
self.master.title("New")
self.master.configure(background="#d9d9d9")
self.master.configure(highlightbackground="#d9d9d9")
self.master.configure(highlightcolor="black")
self.master.resizable(0, 0)
self.Btn = Button(self.master)
self.Btn.place(relx=0.50, rely=0.21, height=24, width=51)
self.Btn.configure(text='''Quite''')
self.Btn.configure(command=self.quite)
def quite(self):
p = MainWindow.__init__
p.self.Btn_UI.configure(state="normal")
self.master.destroy()
def main():
root = Tk()
Main = MainWindow(root)
root.mainloop()
main()
Thanks in Advance!! :D

Open executable file from graphics button without closing parent window

I've created a game "dice poker" using Zelle's graphing package, and have a button on the main screen which opens a text file. The text file opens when the button is clicked, but the main window closes. How can I keep the parent window open?
The button class is below:
from graphics import *
from tkinter import Button as tkButton
class Button():
"""A button is a labeled rectangle in a window.
It is activated or deactivated with the activate()
and deactivate() methods. The clicked(p) method
returns true if the button is active and p is inside it."""
def __init__(self, win, center, width, height, label):
""" Creates a rectangular button, eg:
qb = Button(myWin, centerPoint, width, height, 'Quit') """
w,h = width/2.0, height/2.0
x,y = center.getX(), center.getY()
self.xmax, self.xmin = x+w, x-w
self.ymax, self.ymin = y+h, y-h
p1 = Point(self.xmin, self.ymin)
p2 = Point(self.xmax, self.ymax)
self.rect = Rectangle(p1,p2)
self.rect.setFill('lightgray')
self.rect.draw(win)
self.label = Text(center, label)
self.label.draw(win)
self.deactivate()
def clicked(self, p):
"Returns true if button active and p is inside"
return (self.active and
self.xmin <= p.getX() <= self.xmax and
self.ymin <= p.getY() <= self.ymax)
def getLabel(self):
"Returns the label string of this button."
return self.label.getText()
def activate(self):
"Sets this button to 'active'."
self.label.setFill('black')
self.rect.setWidth(2)
self.active = True
def deactivate(self):
"Sets this button to 'inactive'."
self.label.setFill('darkgrey')
self.rect.setWidth(1)
self.active = False
How can I include a command argument that can open an executable in a fashion similar to this tkinter implementation:
import Tkinter as tk
def create_window():
window = tk.Toplevel(root)
root = tk.Tk()
b = tk.Button(root, text="Create new window", command=create_window)
b.pack()
root.mainloop()
Where the command can be subprocess.run(['open', '-t', 'poker_help.txt']) and still keep the original window open?
I have to make some assumptions since you didn't include top level code (e.g. you're on a Mac):
Zelle graphics, unlike tkinter and turtle, which is also built on tkinter, doesn't have an explicit win.mainloop() call to turn control over to the Tk event handler to idle awaiting events to happen. Instead, you have to patch one together yourself, otherwise once you get the mouse click that fires off your button, the program falls through the end of the file and the main window closes:
import subprocess
from graphics import *
from button import Button
win = GraphWin()
help_button = Button(win, Point(150, 150), 50, 50, "Help")
help_button.activate()
quit_button = Button(win, Point(50, 50), 50, 50, "Quit")
quit_button.activate()
while True:
point = win.getMouse()
if help_button.clicked(point):
subprocess.call(['open', '-t', 'poker_help.txt'])
elif quit_button.clicked(point):
win.close()
Where from button import Button brings in your button code above. Another thing to check is your window is actually closing, and not simply being obscured by the new window opened atop it.

How to make a window fullscreen in a secondary display with tkinter?

I know how to make a window fullscreen in the "main" display, but even when moving my app's window to a secondary display connected to my PC, when I call:
self.master.attributes('-fullscreen', True)
to fullscreen that window, it does so in the "main" display and not in the secondary one (the app's window disappears from the secondary display and instantly appears in the "main" one, in fullscreen).
How can I make it fullscreen in the secondary display?
This works on Windows 7: If the second screen width and height are the same as the first one, you can use win1 or win2 geometry of the following code depending its relative position(leftof or rightof) to have a fullscreen in a secondary display:
from Tkinter import *
def create_win():
def close(): win1.destroy();win2.destroy()
win1 = Toplevel()
win1.geometry('%dx%d%+d+%d'%(sw,sh,-sw,0))
Button(win1,text="Exit1",command=close).pack()
win2 = Toplevel()
win2.geometry('%dx%d%+d+%d'%(sw,sh,sw,0))
Button(win2,text="Exit2",command=close).pack()
root=Tk()
sw,sh = root.winfo_screenwidth(),root.winfo_screenheight()
print "screen1:",sw,sh
w,h = 800,600
a,b = (sw-w)/2,(sh-h)/2
Button(root,text="Exit",command=lambda r=root:r.destroy()).pack()
Button(root,text="Create win2",command=create_win).pack()
root.geometry('%sx%s+%s+%s'%(w,h,a,b))
root.mainloop()
Try:
from Tkinter import *
rot = Tk()
wth,hgh = rot.winfo_screenwidth(),rot.winfo_screenheight()
#take desktop width and hight (pixel)
_w,_h = 800,600 #root width and hight
a,b = (wth-_w)/2,(hgh-_h)/2 #Put root to center of display(Margin_left,Margin_top)
def spann():
def _exit():
da.destroy()
da = Toplevel()
da.geometry('%dx%d+%d+%d' % (wth, hgh,0, 0))
Button(da,text="Exit",command=_exit).pack()
da.overrideredirect(1)
da.focus_set()#Restricted access main menu
Button(rot,text="Exit",command=lambda rot=rot : rot.destroy()).pack()
but = Button(rot,text="Show SUB",command=spann)
but.pack()
rot.geometry('%sx%s+%s+%s'%(_w,_h,a,b))
rot.mainloop()
""" Geometry pattern 'WxH+a+b'
W = Width
H = Height
a = Margin_left+Margin_Top"""
Super simple method working in 2021
This works even if both displays are different resolutions. Use geometry to offset the second display by the width of the first display. The format of the geometry string is <width>x<height>+xoffset+yoffset:
root = tkinter.Tk()
# specify resolutions of both windows
w0, h0 = 3840, 2160
w1, h1 = 1920, 1080
# set up a window for first display, if wanted
win0 = tkinter.Toplevel()
win0.geometry(f"{w0}x{h0}+0+0")
# set up window for second display with fullscreen
win1 = tkinter.Toplevel()
win1.geometry(f"{w1}x{h1}+{w0}+0") # <- this is the key, offset to the right by w0
win1.attributes("-fullscreen", True)
As long as you know the width of the first display, this will work fine. The X system TK runs on puts the second monitor to the right of the first one by default.
Windows, Python 3.8
In this solution, pressing F11 will make the window fullscreen on the current screen.
Note that self.root.state("zoomed") is Windows specific according to doc.
self.root.overrideredirect(True) is weird in Windows and may have unwanted side effects. For instance I've had issues related to changing screen configuration with this option active.
#!/usr/bin/env python3
import tkinter as tk
class Gui:
fullScreen = False
def __init__(self):
self.root = tk.Tk()
self.root.bind("<F11>", self.toggleFullScreen)
self.root.bind("<Alt-Return>", self.toggleFullScreen)
self.root.bind("<Control-w>", self.quit)
self.root.mainloop()
def toggleFullScreen(self, event):
if self.fullScreen:
self.deactivateFullscreen()
else:
self.activateFullscreen()
def activateFullscreen(self):
self.fullScreen = True
# Store geometry for reset
self.geometry = self.root.geometry()
# Hides borders and make truly fullscreen
self.root.overrideredirect(True)
# Maximize window (Windows only). Optionally set screen geometry if you have it
self.root.state("zoomed")
def deactivateFullscreen(self):
self.fullScreen = False
self.root.state("normal")
self.root.geometry(self.geometry)
self.root.overrideredirect(False)
def quit(self, event=None):
print("quiting...", event)
self.root.quit()
if __name__ == '__main__':
Gui()

Categories