3
\$\begingroup\$

I am currently working on a python program with appJar. This program is made for Raspberry, as I wanted to create a program that is portable. I wanted to insert a virtual keyboard into it, by using buttons, and I currently succeeded by building one. This because it is much more useful for a little touch-screen. Here is the code of the full program:

import csv
import RPi.GPIO as GPIO
import time
from appJar import gui
#all the names of the buttons are in italian
l=[]
class misure: #class where I manage all the measures and the functions of the entries
    global l
    def nome_file(self):
        nome_file=app.getEntry("e1") +'.csv'
        return nome_file
    def verticale(self):
        verticale=float(app.getEntry("e2"))
        return verticale
    def prof_tot(self):
        prof_tot=float(app.getEntry("e3"))
        return prof_tot
    def dist_riv(self):
        mis=float(app.getEntry("e2"))
        return mis
    def dist_fond(self):
        dist_fond=float(app.getEntry("e4"))
        return dist_fond
    def cambia_mis(self):
        app.clearEntry("e2")
        app.clearEntry("e3")
        app.clearEntry("e4")
        app.clearLabel("e5")
        app.showButton("Inizia misura")
        app.setFocus("e2")
    def cambia_prof(self):
        prof=float(app.getEntry("e4"))
        v=app.getLabel("e5")
        l.append(prof)
        l.append(v)
        print(l)
        app.clearEntry("e4")
        app.showButton("Inizia misura")
    def cambia_staz(self):
        app.clearEntry("e1")
        app.clearEntry("e2")
        app.clearEntry("e3")
        app.clearEntry("e4")
        app.clearLabel("e5")
        app.showButton("Inizia misura")
        app.setFocus("e1")
    def mulinello(self):
        mulinello=app.getOptionBox("Mulinello")
        return mulinello
    def tempo_mis(self):
        tempo_mis=app.getOptionBox("Secondi misurazione")
        return float(tempo_mis)

class calcoli: #here are all of the calculation to transform rotation of an hydrometer reel to speed
    def velocita(self,mulinello,giri):
        v=0
        giri_1s=0
        if giri=='':
            v=''
            return v
        giri=float(giri)
        giri_1s=giri/30
        if giri_1s==0:
            v=0
            return v
        if mulinello=='125':
            if giri_1s<1.98:
                v=(1.93+(31.17*giri_1s))/100
                return v
            elif giri_1s<10.27:
                v=(0.19+(32.05*giri_1s))/100
                return v
            else:
                v=(-14.09+(33,44*giri_1s))/100
                return v
        elif mulinello=='80':
            if giri_1s<1:
                v=(2.8+(31.34*giri_1s))/100
                return v
            else:
                v=(0.82+(33.32*giri_1s))/100
                return v
        elif mulinello=='50':
            if giri_1s<1.74:
                v=(1.23+(24.73*giri_1s))/100
                return v
            else:
                v=(-0.42+(25.68*giri_1s))/100
                return v
        elif mulinello=='30':
            if giri_1s<1.16:
                v=(1.90+(10.57*giri_1s))/100
                return v
            else:
                v=(2.26+(10.26*giri_1s))/100
                return v
    def conta_giri(self,temp_mis):
        """print(temp_mis)
        giri=input('Inserire numero di giri') # use this if from computer so you don't have to use raspberry function
        t_fine = time.time()+temp_mis
        print(t_fine)
        return giri"""
        GPIO.setmode(GPIO.BOARD) #input from raspberry of the rotations
        GPIO.setup(32,GPIO.IN)

        #set up a counter
        giri = 0

        #set up a variable for reed activation
        reed_state = 0
        print("Misurazione in corso...")
        t_fine = time.time()+temp_mis
        #while loop until t_fine
        while time.time()<t_fine:
        #check if reed newly activated(the hydrometric reel works like an on and off circuit)
            if GPIO.input(32) == 1 and reed_state == 0:
                #turn on LED. Set reed_state to 1. Add to counter .
                reed_state = 1
                giri = giri + 1
            #pause to debounce
            time.sleep(.01)
            #check if reed released
            if GPIO.input(32) == 0 and reed_state == 1:
                # set reed_state to 0
                reed_state = 0

            #now that loop has finished, print the final count
        return giri
def funz(self): #function to start the measure of speed
        c=calcoli()
        m=misure()
        v=c.velocita(m.mulinello(),c.conta_giri(m.temp_mis()))
        v=round(v,4)
        l=[m.dist_fond(),v]
        app.setLabel("e5",v)
        app.hideButton("Inizia misura")
file1=''
def inserisci_mis(self): #insert measure into csv file
    global file1,mis_0,l
    m=misure()
    myFile = open(m.nome_file(),'a')
    with myFile:
        writer = csv.writer(myFile,lineterminator='\n')
        if file1!=m.nome_file():
            primaLinea = ["Distanza dalla verticale", "Distanza dalla riva", "Profondità"]+["Dist dal Fondo","Velocità"]*5
            writer.writerow(primaLinea)
            file1=m.nome_file()
            mis_0=float(m.dist_riv())
        prof=float(app.getEntry("e4"))
        v=app.getLabel("e5")
        l.append(prof)
        l.append(v)
        writer.writerow([m.verticale(),(m.verticale()-mis_0),m.prof_tot()]+l)
        l=[]
app=gui() #appJar gui
app.setTitle("Water app")
app.setFont(size=12, family="Calibri")

app.addLabel("l1", "Misure",0,0)
app.addLabel("l2", "Velocità",5,0)


app.addEntry("e1",1,0)
app.addEntry("e2",2,0)
app.addEntry("e3",3,0)
app.addEntry("e4",4,0)
app.addLabel("e5","",6,0)

app.addButton("Inizia misura",funz,6,0)

app.addButton("Inserisci misura",inserisci_mis,4,1)
app.addButton("Altra profondità",misure.cambia_prof,3,1)
app.addButton("Cambia misura",misure.cambia_mis,2,1)
app.addButton("Cambia stazione",misure.cambia_staz,1,1)

app.setEntryDefault("e1", "Nome stazione")
app.setEntryDefault("e2", "Verticale n°")
app.setEntryDefault("e3", "Profondità totale")
app.setEntryDefault("e4", "Distanza dal fondo")
app.setGuiPadding(15, 5)
app.addLabelOptionBox("Mulinello", ['125', '80', '50','30'],5,1)
app.addLabelOptionBox("Secondi misurazione", ['15', '30', '60','120','180'],6,1,2)

app.setLabelFont(size=13,weight="bold")
app.setEntryWidths(["e1","e2","e3","e4"], 20)
app.setEntryRelief("e1", "raised")
app.setEntryRelief("e2", "raised")
app.setEntryRelief("e3", "raised")
app.setEntryRelief("e4", "raised")
#keyboard and number pad
app.addButtons([["1","2","3"],["4","5","4","6"],["7","8","9"],["0",".","O"]],press,1, 2, 3,4)
app.addButtons([["A","B","C","D"],["E","F","G","H"],["I","L","M","N"],["P","Q","R","S"],["T","U","V","Z"]],press,1,5,4,5)

app.go()

Function recalled when you press the letters and numbers buttons:

def press(Button): #function to write into entries with buttons of the program
    if Button=="A":
        entry=''
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"A"
        app.setEntry(focus,entry)
    elif Button=="B":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"B"
        app.setEntry(focus,entry)
    elif Button=="C":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"C"
        app.setEntry(focus,entry)
    elif Button=="D":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"D"
        app.setEntry(focus,entry)
    elif Button=="E":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"E"
        app.setEntry(focus,entry)
    elif Button=="F":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"F"
        app.setEntry(focus,entry)
    elif Button=="G":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"G"
        app.setEntry(focus,entry)
    elif Button=="H":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"H"
        app.setEntry(focus,entry)
    elif Button=="I":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"I"
        app.setEntry(focus,entry)
    elif Button=="L":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"L"
        app.setEntry(focus,entry)
    elif Button=="M":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"M"
        app.setEntry(focus,entry)
    elif Button=="N":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"N"
        app.setEntry(focus,entry)
    elif Button=="O":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"O"
        app.setEntry(focus,entry)
    elif Button=="P":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"P"
        app.setEntry(focus,entry)
    elif Button=="Q":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"Q"
        app.setEntry(focus,entry)
    elif Button=="R":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"R"
        app.setEntry(focus,entry)
    elif Button=="S":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"S"
        app.setEntry(focus,entry)
    elif Button=="T":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"T"
        app.setEntry(focus,entry)
    elif Button=="U":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"U"
        app.setEntry(focus,entry)
    elif Button=="V":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"V"
        app.setEntry(focus,entry)
    elif Button=="Z":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"Z"
        app.setEntry(focus,entry)
    elif Button=="0":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"0"
        app.setEntry(focus,entry)
    elif Button=="1":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"1"
        app.setEntry(focus,entry)
    elif Button=="2":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"2"
        app.setEntry(focus,entry)
    elif Button=="3":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"3"
        app.setEntry(focus,entry)
    elif Button=="4":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"4"
        app.setEntry(focus,entry)
    elif Button=="5":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"5"
        app.setEntry(focus,entry)
    elif Button=="6":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"6"
        app.setEntry(focus,entry)
    elif Button=="7":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"7"
        app.setEntry(focus,entry)
    elif Button=="8":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"8"
        app.setEntry(focus,entry)
    elif Button=="9":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"9"
        app.setEntry(focus,entry)
    elif Button==".":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"."
        app.setEntry(focus,entry)

This is my program. I modified appJar.py into the appJar directory module to not have the focus on the buttons (lines 488-489-490 are all commented):

#self.topLevel.bind('<Button-1>', lambda e: _setFocus(e))
#self.topLevel.bind('<Button-2>', lambda e: _setFocus(e))
#self.topLevel.bind('<Button-3>', lambda e: _setFocus(e))

I wanted to ask if there is a more efficient way to do a keyboard and numeric pad, because I think that there is a better way to do it. Or even something that I could change in my program to be more efficient.

\$\endgroup\$
6
\$\begingroup\$

Python has an official style guide, PEP8. It won't hurt getting familiar with it, since it helps keeping your code readable, consistent and ready for others to mess with.

Combining Italian and English gets confusing fast. It's also unhelpful for those of us that don't read Italian. There's also a distinct lack of whitespace between blocks of code and one-letter variable names are not helpful.

Your class uses a global l where l=[]. I don't like globals, especially in a class. Consider the following:

class misure:
    def __init__(self):
        self.l = []
    def nome_file(self):

my_misure = misure()
print(my_misure.l)

And all of a sudden you can have 20 instances of misure because they all have their own list. A class should hold it's own data as much as possible.

The following can be improved a lot:

def press(Button): #function to write into entries with buttons of the program
    if Button=="A":
        entry=''
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"A"
        app.setEntry(focus,entry)
    elif Button=="B":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"B"
        app.setEntry(focus,entry)
    elif Button=="C":
        focus=app.getFocus()
        entry=app.getEntry(focus)
        entry=entry+"C"
        app.setEntry(focus,entry)

If that entry should do what you want it to do, create it before the first if. But since you overwrite it anyway, why not toss it? Which leaves the following:

    focus=app.getFocus()
    entry=app.getEntry(focus)
    entry=entry+"character"
    app.setEntry(focus,entry)

That's what all those blocks look like, right? So why not put it in a function?

def we_put_it_in_a_function(character):
    focus=app.getFocus()
    entry=app.getEntry(focus)
    entry=entry+"character"
    app.setEntry(focus,entry)

All of a sudden, your massive if block looks like this:

def press(Button): #function to write into entries with buttons of the program
    if Button=="A":
        we_put_it_in_a_function("A"):
    elif Button=="B":
        we_put_it_in_a_function("B"):
    elif Button=="C":
        we_put_it_in_a_function("C"):
    elif Button=="D":
        we_put_it_in_a_function("D"):
    elif Button=="E":
        we_put_it_in_a_function("E"):
    elif Button=="F":
        we_put_it_in_a_function("F"):

And here comes the real kicker, it can be done even shorter:

def press(Button): #function to write into entries with buttons of the program
    we_put_it_in_a_function(Button):
\$\endgroup\$
  • \$\begingroup\$ we_put_it_in_a_function needs to validate that the value of Button is allowed. Put all the allowed values of Button in a set and check that it exists in the set before doing stuff with it. \$\endgroup\$ – Simon Forsberg Apr 8 '18 at 11:14
  • \$\begingroup\$ @SimonForsberg Definitely. But the current code didn't appear to do any of that either although I wasn't sure, with half of it in Italian. Perhaps the app already handles invalid input. Validation could be a whole review by itself. \$\endgroup\$ – Mast Apr 8 '18 at 12:14
  • \$\begingroup\$ I need to revise my python knolwedge XD. Could you explain me in simple words what self means? Cause I looked up in various part of the internet an I couldn't understand. Anyway I will upload the code all in english, so that you can understand. \$\endgroup\$ – Lorenz Bonat Apr 8 '18 at 12:17
  • \$\begingroup\$ @Mast The problem of having the list as into the _init_ is that every time I call that class it removes the values that are into it. What I need is a list where I append different values from different funcrions, so I think that is better to use global \$\endgroup\$ – Lorenz Bonat Apr 8 '18 at 12:35
  • \$\begingroup\$ @LorenzBonat If you decide to upload new (translated) code, do so in a new question (linking back to this one). I think your problems with init are due to how you're calling your code, but I can't be certain without seeing how you do it. Don't create a new class on every action. If that's what you're doing, you might need to restructure a couple of things. Honestly a good explanation of what your code does (and more importantly, why) would go a long way in helping you clear things up. \$\endgroup\$ – Mast Apr 8 '18 at 12:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.