I've been searching for an answer for two hours now. What I am trying to accomplish in kivy is this:
import time
clear = "\033[2J\033[1;1f"
print("""
################################
##this should display an image##
################################""")
time.sleep(1)
print(clear)
print("""
#####################################
##this should display another image##
#####################################""")
It is the beginning of a program I already got ready, but not as a real Desktop Application as if it would be with kivy.
The program begins with showing an image, pausing for a second, then not showing an image before initiating the main menu with buttons and so on (not important).
This is what I have so far (not working) :
class Intro(FloatLayout):
connection = Image(source='connection.png')
noconnection = Image(source='noconnection.png')
checkloop = True
def check_connection(self, dt):
url='http://www.google.com/'
timeout=5
connected.stop()
noconnection.stop()
try:
server = smtplib.SMTP('smtp.gmail.com', 587)
_ = requests.get(url, timeout=timeout)
connected.play()
self.add_widget(self.connection)
Clock.schedule_once(self.remove_widget(self.connection), 1)
checkloop = False
except requests.ConnectionError:
noconnection.play()
self.add_widget(self.noconnection)
self.remove_widget(self.noconnection)
txtinput = TextInput(text='ConnectionError. Enter to try again...')
except smtplib.SMTPConnectError:
noconnection.play()
img = Image(source='noconnection.png')
self.add_widget(self.noconnection)
self.remove_widget(self.noconnection)
txtinput = TextInput(text='SMTPConnectError. Enter to try again...')
class I41(App):
def build(self):
self.icon = 'riseicon.png'
self.title = '41'
intro = Intro()
Clock.schedule_once(intro.check_connection)
print("DONE")
What am I doing wrong still?
I hope you guys can help me! First questions asked on stackoverflow!
In your check_connection() method you have many return statements. Note that the documentation. says:
return leaves the current function
So anything after a return is encountered will not be executed, and any other code in the method will be stopped (like a while loop).
A fix is to call the code that you want executed after return using a call to Clock.schedle_once() .
Here is a simple example of how to do that:
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
class MyFloatLayout(FloatLayout):
img = Image(source='connection.png')
checkloop = True
def showImage(self, dt):
self.add_widget(self.img)
# other code here, like connecting to Google
if self.checkloop:
# continue loop
Clock.schedule_once(self.deleteImage, 1)
def deleteImage(self, dt):
self.remove_widget(self.img)
if self.checkloop:
# continue loop
Clock.schedule_once(self.showImage, 1)
class I41(App):
def build(self):
self.icon = 'riseicon.png'
self.title = '41'
root = MyFloatLayout()
# start image loop
Clock.schedule_once(root.showImage)
return root
I41().run()
The loop is stopped by setting checkloop to False in MyFloatLayout.
Related
I have designed an application which have two buttons i.e CAL and SAV.
Accordingly that I have two functions but the issue is sometimes production line Operator by mistake presses SAV button. So that attribute error arises and program stuck.
How to overcome this issue? Please guide me.
Here is my code:
class ADS1x15:
"""Base functionality for ADS1x15 analog to digital converters."""
class ADS1115(ADS1x15):
"""Class for the ADS1115 16 bit ADC."""
class AnalogIn:
"""AnalogIn Mock Implementation for ADC Reads."""
import RPi.GPIO as GPIO
import tkinter as tk
GPIO.setmode(GPIO.BCM)
GPIO.setup(12,GPIO.IN) #Save Button
GPIO.setup(5,GPIO.IN) #Cal Button
root=tk.Tk()
root.geometry("1000x600")
file = open("/home/pi/data_log.txt", "r")
f = file.read().split(',')
rangeh = int(f[3])
offset = int(f[4])
fullScale = int(f[5])
chan=AnalogIn(ads,P0,P1)
def cal(channel):
global Dsel,cal_c,rangeh,offset,fullScale,chan
cal_c = cal_c + 1
if cal_c == 1:
root.L1 = tk.Label(root,text="Put Zero Weight and Press CAL btn",fg="brown",font="bold")
root.L1.pack()
root.L1.place(x=1,y=1)
elif cal_c == 2:
root.L1.destroy()
offset = chan.value
file = open("/home/pi/data_log.txt", "w")
if os.stat("/home/pi/data_log.txt").st_size == 0:
file.write("rangeh,offset,Full_Scale,\n")
file.write(str(rangeh)+","+str(offset)+","+str(fullScale))
file.flush()
root.L2 = tk.Label(root,text="Put Full Weight and Press SAV btn",fg="brown",font="bold")
root.L2.pack()
root.L2.place(x=1,y=1)
def sav(channel):
global rangeh,offset,fullScale
file = open("/home/pi/data_log.txt", "w")
if os.stat("/home/pi/data_log.txt").st_size == 0:
file.write("rangeh,offset,Full_Scale,\n")
file.write(str(rangeh)+","+str(offset)+","+str(fullScale))
file.flush()
root.L2.destroy()
def update():
""" function for continuous show value in every 500ms in tkinter window"""
GPIO.add_event_detect(5,GPIO.RISING,callback=cal,bouncetime=1000)
GPIO.add_event_detect(12,GPIO.RISING,callback=sav,bouncetime=1000)
root.after(500,update)
root.mainloop()
This error generated due to root.L2.destroy() this line.
Can I block or disable this sav function, so that without call of cal function, it shouldn't execute?
A brute force solution would be to check whether root has an L2 attribute or not
from tkinter import messagebox
def sav(channel):
if hasattr(root, 'L2'):
global rangeh, offset, fullScale
file = open("/home/pi/data_log.txt", "w")
if os.stat("/home/pi/data_log.txt").st_size == 0:
file.write("rangeh,offset,Full_Scale,\n")
file.write(str(rangeh) + "," + str(offset) + "," + str(fullScale))
file.flush()
root.L2.destroy()
else:
messagebox.showinfo('Unable to save', 'No data was generated yet')
A more elegant approach would be to disable the save button on startup and only enable it after the cal function has been executed.
I am not very familiar with Raspberry Pi implementations, so this is only a rough sketch on how to achieve the button disabling:
By the looks of it, the buttons are "wired in" via the GPIO.add_event_detect functions.
So i would remove the sav-callback from the main script and dynamically add it after the cal script, something like that:
# [...] beginning of your script [...]
def cal(channel):
# [...] original body of cal function [...]
activate_save_button()
def activate_save_button():
GPIO.add_event_detect(12, GPIO.RISING, callback=sav, bouncetime=1000)
def deactivate_save_button():
GPIO.remove_event_detect(12)
def sav(channel):
# [...] original body of sav function [...]
# remove save button functionality after saving
deactivate_save_button()
def update():
""" function for continuous show value in every 500ms in tkinter window"""
GPIO.add_event_detect(5, GPIO.RISING, callback=cal, bouncetime=1000)
# line with callback=sav is deleted here
root.after(500, update)
root.mainloop()
I'm building a large, complicated program, one half of which involves a GUI, which I'm building using Tkinter.
Previous iterations of this GUI seemed to work as intended. However, in the latest version, when I try to run a demonstration (see the demo() function in the code below), my whole computer freezes, and my only option is to carry out a hard reset.
Does anyone have any ideas as to why this might be happening? Some points which might be useful:
If I run the code below with the line self.gui.mainloop() commented out, the desired window appears on the screen for long enough for the toaster message to be displayed, and then closes without any freezing.
The ArrivalsManagerDaughter and DeparturesManagerDaughter objects transmit data wirelessly to another device, but they shouldn't be doing anything, other than being initialised, in the code which is causing the freezing. I don't believe that these are the cause of the problem, although I could well be wrong.
Here's the whole Python file which I'm trying to run. I'm happy to post more code if requested.
"""
This code holds a class which manages transitions between the
"recommendations" and "custom placement" windows, and also oversees their
interactions with Erebus.
"""
# GUI imports.
from tkinter import *
# Non-standard imports.
import ptoaster
# Custom imports.
from erebus.arrivals_manager_daughter import ArrivalsManagerDaughter
from erebus.departures_manager_daughter import DeparturesManagerDaughter
# Local imports.
from charon.custom_placement_window import Custom_Placement_Window
from charon.recommendations_window import Recommendations_Window
# Local constants.
REFRESH_INTERVAL = 1000
# ^^^ in miliseconds ^^^
##############
# MAIN CLASS #
##############
class Comptroller:
""" The class in question. """
def __init__(self, welcome=False, delete_existing_ledger=False,
internal=False, diagnostics=False, path_to_icon=None):
self.close_requested = False
self.path_to_icon = path_to_icon
self.recommendations = dict()
self.arrivals_manager = ArrivalsManagerDaughter(self,
diagnostics=diagnostics)
self.departures_manager = DeparturesManagerDaughter(
delete_existing=delete_existing_ledger, internal=internal,
diagnostics=diagnostics)
self.gui = Tk()
self.top = Frame(self.gui)
self.window = Recommendations_Window(self)
self.is_on_recommendations_window = True
self.arrange()
if welcome:
print_welcome()
def add_recommendation(self, ticket, epc, column, row):
""" Add a recommendation to the dictionary. """
recommendation = dict()
recommendation["ticket"] = ticket
recommendation["epc"] = epc
recommendation["column"] = column
recommendation["row"] = row
self.recommendations[ticket] = recommendation
def remove_recommendation(self, ticket):
""" Delete a recommendation from the dictionary. """
del self.recommendations[ticket]
def get_top(self):
""" Return the top-level GUI object. """
return self.top
def arrange(self):
""" Arrange the widgets. """
self.window.get_top().pack()
self.top.pack()
def switch_to_custom_placement(self, ticket, epc):
""" Switch window from "Recommendations" to "Custom Placement". """
columns = self.arrivals_manager.columns
rows = self.arrivals_manager.rows
self.window.get_top().pack_forget()
self.window = Custom_Placement_Window(self, ticket, epc, columns,
rows)
self.window.get_top().pack()
self.is_on_recommendations_window = False
def switch_to_recommendations(self):
""" Switch window from "Custom Placement" to "Recommendations". """
self.window.get_top().pack_forget()
self.window = Recommendations_Window(self)
self.window.get_top().pack()
self.is_on_recommendations_window = True
def refresh(self):
""" Refresh the "recommendations" window, as necessary. """
if (self.is_on_recommendations_window and
self.arrivals_manager.clear_quanta()):
self.window.refresh_rec_table()
self.departures_manager.clear_backlog()
if self.close_requested:
self.kill_me()
else:
self.gui.after(REFRESH_INTERVAL, self.refresh)
def simulate_recommendation(self, ticket, epc, column, row):
""" Simulate receiving a transmission from the Pi. """
self.add_recommendation(ticket, epc, column, row)
self.window.refresh_rec_table()
def request_close(self):
self.close_requested = True
def run_me(self):
""" Run the "mainloop" method on the GUI object. """
self.gui.after(REFRESH_INTERVAL, self.refresh)
self.gui.title("Charon")
if self.path_to_icon:
self.gui.iconphoto(True, PhotoImage(file=self.path_to_icon))
self.gui.protocol("WM_DELETE_WINDOW", self.request_close)
self.gui.mainloop()
def kill_me(self):
""" Kill the mainloop process, and shut the window. """
self.gui.destroy()
####################
# HELPER FUNCTIONS #
####################
def print_welcome():
""" Print a welcome "toaster" message. """
message = ("Notifications about boxes leaving the coldstore will be "+
"posted here.")
ptoaster.notify("Welcome to Charon", message,
display_duration_in_ms=REFRESH_INTERVAL)
def print_exit(epc):
""" Print an exit "toaster" message. """
message = "Box with EPC "+epc+" has left the coldstore."
ptoaster.notify("Exit", message)
###########
# TESTING #
###########
def demo():
""" Run a demonstration. """
comptroller = Comptroller(welcome=True, delete_existing_ledger=True,
internal=True, diagnostics=True)
comptroller.simulate_recommendation(1, "rumpelstiltskin", 0, 0)
comptroller.simulate_recommendation(2, "beetlejuice", 0, 0)
comptroller.run_me()
###################
# RUN AND WRAP UP #
###################
def run():
demo()
if __name__ == "__main__":
run()
FOUND THE PROBLEM: the culprit was actually calling a ptoaster function from within a Tkinter GUI. Which leads me on to my next question: Is it possible to combine ptoaster and Tkinter in an elegant fashion, and, if so, how?
The problem ocurred when calling print_welcome(), which in turn calls one of the ptoaster functions. It seems that Tkinter and ptoaster do not play together nicely. Removing the reference to print_welcome() from the Comptroller class put a stop to any freezing.
(On a side note: I'd be very grateful to anyone who could suggest an elegant method of combing ptoaster with Tkinter.)
Try changing
def demo():
""" Run a demonstration. """
comptroller = Comptroller(welcome=True, delete_existing_ledger=True,
internal=True, diagnostics=True)
comptroller.simulate_recommendation(1, "rumpelstiltskin", 0, 0)
comptroller.simulate_recommendation(2, "beetlejuice", 0, 0)
comptroller.run_me()
###################
# RUN AND WRAP UP #
###################
def run():
demo()
if __name__ == "__main__":
run()
To simply
if __name__ == "__main__":
""" Run a demonstration. """
comptroller = Comptroller(welcome=True, delete_existing_ledger=True,
internal=True, diagnostics=True)
comptroller.simulate_recommendation(1, "rumpelstiltskin", 0, 0)
comptroller.simulate_recommendation(2, "beetlejuice", 0, 0)
comptroller.run_me()
As to why this might happening, since you're creating an object by instantiating Comptroller inside a regular function demo, the object is not being "retained" after the demo exits.
EDIT
If you would like to still maintain demo and run you could create a class Demo and store the instance globally.
Or maybe a simple global variable inside demo to retain a "reference" to the instance Comptroller.
I want to use the bot_create function with a button but I keep getting (on line 20) the problem "bots not defined" so I moved the function down below the button but got the problem "bot_create not defined".
I didn't get this problem using C++ and I'm new to Python. How should I arrange the functions?
import tkinter as tk
import numpy as np
import multiprocessing as mp
bots_max = 1000 # Maximum number of bots
bot = []
bot_count = 0
# Menu functions
def save_field():
pass
# Field functions
def field_clear():
pass
# Bots functions
def bots_create():
bot[bot_count] = bots
bot_count += 1
main = tk.Tk()
field_sides = 600
ctrls_width = 200
main.geometry("800x600")
main.resizable(0, 0)
main.title("Swarm Simulator v1.0")
# Controls menu on left side
button1 = tk.Button(main, text = "Button 1").pack(side = "left", command = bots_create())
class environment:
def __init__():
pass
class wall:
def __init__():
pass
# Bots
class bots:
alive = True
def __init__():
alive = True
# Field where bots live
field = tk.Canvas(main, width = field_sides, height = field_sides, bg = "white").pack(side = "right")
for particle in bots:
print("|")
main.mainloop()
Here's a version of your code that fixes all the syntactic problems, and so compiles (what I really mean is that my IDE now thinks its ok). It also runs, but I don't know if it does what you intended. See my comments in the code:
import tkinter as tk
import numpy as np
import multiprocessing as mp
# moved your class defs up to fix problems with accessing them before they are defined
class environment:
def __init__(self): # need a self param here
pass
class wall:
def __init__(self): # need a self param here
pass
# Bots
class bots:
alive = True
def __init__(self): # need a self param here
alive = True
bots_max = 1000 # Maximum number of bots
bot = []
# bot_count = 0 # this no longer does anything. use `len(bot)` to get the number of objects in the 'bot' list
# Menu functions
def save_field():
pass
# Field functions
def field_clear():
pass
# Bots functions
def bots_create():
# bot[bot_count] = bots # this will crash as it is referring to a non-existent location in the list
# also, your use of "bots" here makes no sense
# bot_count += 1 # this makes 'bot_count' a local variable, which is not what you want
bot.append(bots()) # not sure this is what you want, but this creates a new 'bots' object and adds it to the 'bot' list
main = tk.Tk()
field_sides = 600
ctrls_width = 200
main.geometry("800x600")
main.resizable(0, 0)
main.title("Swarm Simulator v1.0")
# Controls menu on left side
button1 = tk.Button(main, text = "Button 1").pack(side = "left", command = bots_create())
# Field where bots live
field = tk.Canvas(main, width = field_sides, height = field_sides, bg = "white").pack(side = "right")
for particle in bot: # maybe you want to iterate over the 'bot' list instead of the 'bots' type?
print("|")
main.mainloop()
As #khelwood says, it seems that you should swap the use of the names bot and bots per the way you are using them
I am using PyViz / Panel in a notebook. Now I want to use a toggle button inside a class, and bind a callback to it.
This code - outside a class - is working:
import panel as pn
import panel.widgets as pnw
pn.extension()
toggle = pn.widgets.Toggle(name='Toggle')
def callback(*events):
if toggle.active is True: toggle.name = 'Active'
else: toggle.name = 'Toggle'
watcher = toggle.param.watch(callback, 'active')
toggle.param.set_param(active=False)
toggle.param.trigger('active')
pn.Row(toggle)
It produces a toggle button, and when clicked, the text changes.
No I tried to put everything inside a class definition:
class ToggleInClass():
def __init__(self):
self.toggle = pn.widgets.Toggle(name='Toggle')
self.watcher = self.toggle.param.watch(callback, 'active')
self.toggle.param.set_param(active=False)
self.toggle.param.trigger('active')
def callback(self, *events):
if toggle.active is True: toggle.name = 'Active'
else: toggle.name = 'Toggle'
toggle_in_class = ToggleInClass()
pn.Row(toggle_in_class.toggle)
Again a button is produced, but this time the callback does not seem to work: The text never changes.
The watcher seems to be ok:
toggle_in_class.watcher gives Watcher(inst=Toggle(), cls=<class 'panel.widgets.Toggle'>, fn=<function callback at 0x000001EC8419E510>, mode='args', onlychanged=True, parameter_names=('active',)).
The output of toggle_in_class.toggle.active alternates according the toggle state.
What is wrong with my callback / class definition?
After correcting some stupid typos this code is working for me:
class ToggleInClass():
def __init__(self):
self.toggle = pn.widgets.Toggle(name='Toggle')
self.watcher = self.toggle.param.watch(self.callback, 'active')
self.toggle.param.set_param(active=False)
def callback(self, *events):
if self.toggle.active is True: self.toggle.name = 'Active'
else: self.toggle.name = 'Toggle'
toggle_in_class = ToggleInClass()
pn.Row(toggle_in_class.toggle)
I am currently working on a projet similar to tic tac toe (with an AI)
And I did a GUI to allow the user to play with the bot
But the program doesn't wait for the player to choose and instead it crash because it doesn't have value
So I searcher about threads, tried for a long time can't achieve to figure out how it works
I did some tests (bellow) that my archly resemble what I need to do with my code
But it doesn't work neither
Do someone have an answer ?
import threading
import tkinter as tk
windo = tk.Tk()
windo.title("Morpion")
windo.resizable(width=tk.FALSE, height=tk.FALSE)
class Player:
def __init__(self,name):
self.name = name
self.choice = None
def Change_Var(x):
print(P.choice)
P.choice = x
print(P.choice)
play_event.set()
def boucle():
i = 0
while not play_event.isSet() and i < 3000:
print(i)
i += 1
P = Player("Deltix")
start = tk.Button(height=2,width=8, text = "Start",command = lambda x = 0 : Change_Var(x))
start.grid(column = 2, row = 3,pady = 5)
play_event = threading.Event()
threading.Thread(target = windo.mainloop()).start
threading.Thread(target = boucle()).start```
You don't need to use threads, just use events.
Say you wanted to bind a function to the enter key.
This would be your code:
canvas = Canvas(master)
def clicked(event):
print("Enter was pressed")
canvas.bind("<Return>", clicked)
You can read more about tkinter events here.
Hopefully this helps!