0
\$\begingroup\$

I have been tasked to create a GUI that asks the user questions about a mobile device.the GUI I have created asks the user a sequence of questions to try and come to a solution.However, I feel that my inexperience with GUI has made me repeat myself a lot with this. Therefore, is there anything i can do to make this more efficient? I want to make this code as efficient as possible while still retaining its functionality.

from tkinter import *
import sys
screen = Tk()

def sftwr_or_hrdwr():
    label6=Label(screen, text = "is your phone a software or hardware        problem?",font=("Helvetica",15))
label6.pack()
software=Button(screen,fg="black",bg="white",text="SOFTWARE", command = question1_s)
software.pack()
hardware=Button(screen,fg="black",bg="white",text="HARDWARE",command = question1_h)
hardware.pack()
IDK=Button(screen, fg = "black", bg= "white", text ="I DONT KNOW THE DIFFERENCE",command=IDK_)
IDK.pack()
def IDK_():
  label27=Label(screen,text="hardware are the physical components of the phone(camera, internal parts ect) \n the software is the oporating system. eg, apple phones yous OSX, samsung phones use android. \n common faults for this are, phone freezing/shutting down)",font=("Helvetica",15))
label27.pack()
label28=Label(screen,text="now go back and click either software or hardwre",font=("Helvetica",15))
label28.pack()    
#software questions
def question1_s():
 label5 = Label( screen, text = "Has your phone been randomly shuttting down ? ",font=("Helvetica",15))
 label5.pack()
 Yes2 = Button(screen, fg = "black", bg= "white", text = "YES",command =solution1_s)
 Yes2.pack()
No2 = Button(screen, fg = "black", bg = "white", text = "NO", command= question2_s)
No2.pack()
def question2_s():
 label21=Label(screen, text="has your phone been getting pop ups blocking your screen constantly, and applications being randomly deleted (even with storage available)?",font=("Helvetica",15))
 label21.pack()
Yes_all=Button(screen, fg = "black", bg= "white", text ="YES, all of these are happening", command= solution2_s)
Yes_all.pack()
Yes_app=Button(screen, fg = "black", bg= "white", text ="YES, but only applications being deleted",command=solution_app)
Yes_app.pack()
Yes_pop=Button(screen, fg = "black", bg= "white", text ="YES, but only the pop up ads",command=solution_pop)
Yes_pop.pack()
No8=Button(screen, fg = "black", bg= "white", text ="NO none of these",command= question3_s)
No8.pack()
def question3_s():
label25=Label(screen,text="has your phone been freezing randomly?",font=("Helvetica",15))
label25.pack()
Yes9=Button(screen, fg = "black", bg= "white", text ="YES",command=solution3_s)
Yes9.pack()
No9=Button(screen, fg = "black", bg= "white", text ="NO",command=no_solution)
No9.pack()                   
#hardware questions   
def question1_h():
 label3 = Label(screen, text = " Has your phone got a crack in it ? ",font=("Helvetica",15))
label3.pack()
Yes1 = Button(screen, fg = "black", bg= "white",  text = "YES",command=hardware_crack2)
Yes1.pack()
No1 = Button(screen, fg = "black", bg = "white", text = "NO", command =question2_h )
No1.pack()

def hardware_crack1():
 label9=Label(screen,text="is the crack showing any internal parts of thr system?",font=("Helvetica",15))
label9.pack()
Yes3=Button(screen, fg = "black", bg= "white", text ="YES", command= solution_crack1)
No3=Button(screen, fg = "black", bg= "white", text ="NO",command=   hardware_crack2)
def hardware_crack2():
 label8=Label(screen,text= "where is the crack on your phone?",font=("Helvetica",15))
label8.pack()
crack=Button(screen, fg = "black", bg= "white", text ="on the main screen",  command=solution_crack2)
 crack.pack()
 back=Button(screen, fg = "black", bg= "white", text ="on the back of the  phone",command=solution_crack3)
 back.pack()
 on_c=Button(screen, fg = "black", bg= "white", text ="on a component (eg, crack on the camera)", command=solution_crack4)
 on_c.pack()
 sides=Button(screen, fg = "black", bg= "white", text ="on the side of the phone/around but not on the screen", command=solution_crack3)
sides.pack()
def question2_h():
 label12=Label(screen,text="has your phone come in contact with liquid?",font=("Helvetica",15))
  label12.pack()              
 Yes4=Button(screen, fg = "black", bg= "white", text ="YES", command=solution2_h)
 Yes4.pack()
 No4=Button(screen, fg = "black", bg= "white", text ="NO",command=question3_h)
 No4.pack()
 def question3_h():
  label15=Label(screen,text="is your phone not charging correctly, or loosing battery very fast or jumping from battery percentages?",font=("Helvetica",15))
 label15.pack()
Yes5=Button(screen, fg = "black", bg= "white", text ="YES",command=solution3_h)
Yes5.pack()
No5=Button(screen, fg = "black", bg= "white", text ="NO", command=question4_h)
No5.pack()
def question4_h():
 label17=Label(screen,text="is your phone overheating or unable to open many applications at once?",font=("Helvetica",15))
label17.pack()
Yes_o=Button(screen, fg = "black", bg= "white", text ="YES, it has been overheating but it can open applcations fine",command=solution_heat)
 Yes_o.pack()
 Yes_a=Button(screen, fg = "black", bg= "white", text ="YES, there are no overheating problems, but i am struggling to open many applications at once",command=solution_RAM)
 Yes_a.pack()
 Yes7=Button(screen, fg = "black", bg= "white", text ="YES, both of these are happening to me", command =solution4_h)
 Yes7.pack()
 No7=Button(screen, fg = "black", bg= "white", text ="NO", command=no_solution)
 No7.pack()
 #software solutions
 def solution1_s():
  label20=Label(screen,text="if this is happeing to you, there is a bug in the software. call up your supplier and they will try and troubleshoot the phone. make sure you have all the latest updates installed",font=("Helvetica",15))
    label20.pack()
    sys.exit()
 def solution2_s():
label22=Label(screen,text="these are all signs of a virus. the deleting of applications is virus munching on your data, and pop ups on your scren is also a virus symptom. immiditely use your antivirus to look for the problem or take it to a repair shop where they can delete the virus",font=("Helvetica",15))
label22.pack()
sys.exit()
def solution_app():
 label23=Label(screen,text="check if you have enogh storage on your device, if you dont and that was the problem, then see if you can get a storage upgrade. However, if it isnt there is a good chance you have a virus on your phone. scan your phone with an antivirus, or let your local repair shop do it",font=("Helvetica",15))
label23.pack()
sys.exit()
def solution_pop():
 label24=Label(screen,text="f the pop ups are on a web browser, this is normal. try getting an ad blocker if it is bothering you, but do not click on them. however, if it is happening on the main screen, you have contracted a virus. use your antivirus orget it fixed at a repair shop",font=("Helvetica",15))
   label24.pack()
   sys.exit()
  def solution3_s():
  label26=Label(screen,text="this is another sign of a software fault. the only one who can fix this is your supplier. contact them as soon as possible",font=("Helvetica",15))
label26.pack()
sys.exit()
#hardware solutions
def solution_crack1():
 label10=Label(screen,text="take it to a repair shop as soon as possible as if interior parts are exposed then it can damage your phone",font=("Helvetica",15))
 label10.pack()
 sys.exit()
def solution_crack2():
 label11=Label(screen,text=" get your screen repaired at a local repair shop, as parts of the screen glass may fall off",font=("Helvetica",15))
 label11.pack()
 sys.exit()
def solution_crack3():                 
 label12=Label(screen,text="Try and get a protective cover that can protect the back/sides of your phone. you can also get a screen protector if you are worred about moe dents. or get it repaired at a repair shop",font=("Helvetica",15))
label12.pack()
sys.exit()
def solution_crack4():
 label13=Label(screen,text="if your hardware is getting distrupted due to cracks and dents, you should go and get it repaired at a shop, as it is limiting what your phone can do",font=("Helvetica",15))
 label13.pack()
 sys.exit()
def solution2_h():
 label2 = Label(screen, text = " Please take off your cover and try to dry the inner components.",font=("Helvetica",15))
label2.pack()
sys.exit()
def solution3_h():
label16=Label(screen,text= "you should get your battery changed. try and find a battery that is compatible with your phone by asking your supplier, and get a technitian to replace it if need be.",font=("Helvetica",15))
label16.pack()
sys.exit
def solution4_h():
label18=Label(screen,text="this means there is a problem with the internal parts. this could be that the parts are becoming old. The struggle to open applications is the ram. this could be that it is getting old and is loosing performance or it is damaged. The overheating is the other components in your phone are not functioning properly. you should contant your supplier and get it repaired at a repair shop.",font=("Helvetica",15))
label18.pack()
sys.exit()
def solution_RAM():
label19=Label(screen,text="the fact you cant open multiple applications at once means your RAM is not functioning properly. get it upgraded or replaced at a repair shop",font=("Helvetica",15))
label19.pack()
sys.exit()
def solution_heat():
label20=Label(screen,text="if your phone is overheating that means the internal parts are not performing how they should be. ask your local repair shop to see what is wrong with the internal parts",font=("Helvetica",15))
label20.pack()
#no solution
def show_entry_fields():
print("Email: %s\nProblem with phone: %s" % (e1.get(), e2.get()))
def no_solution():
label21=Label(screen,text="sorry, we cannot find a solution to your problem. try to see if your problem is in hardware/software as you may have picked the wrong one. do ths by scrolling up and clicking the other option. your data will be sent to a technitian and we will get back to you as soon as possible. in the box submit our email and problem, then press Enter and close down troubleshooter",font=("Helvetica",15))
label21.pack()

master = Tk()
Label(master, text="Email").grid(row=0)
Label(master, text="Problem with phone").grid(row=1)

e1 = Entry(master)
e2 = Entry(master)

e1.grid(row=0, column=1)
e2.grid(row=1, column=1)
Button(master, text='Quit', command=master.quit).grid(row=3, column=0, sticky=W, pady=4)
Button(master, text='Enter', command=show_entry_fields).grid(row=3, column=1, sticky=W, pady=4)

start

def start_program():
label = Label(screen, text = "Hello and welcome to the troubleshooting program ",font=("Helvetica",15))
label.pack()
label1 = Label(screen, text = "")
label.pack()
sftwr_or_hrdwr()

screen.title("Troubleshooter")
screen.configure(background="#a1dbcd")
screen.geometry("1920x1080")

start = Button(screen, fg = "black", bg = "white", text = "Lets get started with troubleshooter ",font= ("Helvetica",16), command = start_program)
start.pack()

of course, as this is a project, i dont actually expect the email to be sent to the user. and i am fairly new to python, however i need to make this as efficient as possible, any help is appreciated.. thank you!

\$\endgroup\$
2
  • 5
    \$\begingroup\$ Could you fix the indentation from copy&pasting here please? And update the title to what the program does, not what you want people to help you with. \$\endgroup\$ – ferada Jan 11 '17 at 11:35
  • 2
    \$\begingroup\$ Easiest way is to paste your code, highlight it, and press Ctrl-K to mark it as a code block. \$\endgroup\$ – 200_success Jan 11 '17 at 15:59
3
\$\begingroup\$

Data structures

The first thing you should do when creating a program is to think about your data structures. In your case you don't have any data structures; instead, you just have a bunch of code.

For example, a whole lot of code follows this pattern:

def solution2_h():
    label2 = Label(screen, text = " Please take off your cover and try to dry the inner components.",font=("Helvetica",15))
    label2.pack()
    sys.exit()

Since the only difference between all of those solutions is the text, you can remove the text from the function and make the text a parameter. In this case, I suggest making a dictionary of the solution text:

solutions = {
    "2_h": "Please take off your cover and try to dry the inner components"
    "2_s": "these are all signs of a virus. ..."
    ...
}

You can then create a function that displays a solution:

def show_solution(name):
    label = Label(screen, text=solutions[name])
    label2.pack()
    sys.exit()

Code structure

Your code seems to mirror the way you typed the code. "I need a label", "I need to pack the label", "I need another label", "I need to pack the label". Instead, thing about the code more logically.

A GUI is made up of several logical parts. One part is the actual widgets required to create the GUI. Another part is how those widgets are organized on the screen and presented to the user.

My recommendation is to gather all of your layout code together, organized by the widget hierarchy. For example:

label6=Label(screen, ...)
software=Button(screen,...)
hardware=Button(screen,...)
IDK=Button(screen, ...)

label6.pack()
software.pack()
hardware.pack()
IDK.pack()

Don't repeat yourself

You define a custom font for every widget, but you're using the same custom font. If you decided at a later date to change the font, you're going to have to change it in dozens of places.

Instead, use a variable for the font. Also, in the specific case of fonts you can leverage tkinter's extremely powerful named fonts feature. You can create a font as an object, and later if you change that object then all widgets will automatically update.

For example

from tkinter import font
...
defaut_font = font.Font(family='Helvetica', size=15)
...
label6=Label(..., font=default_font)
software=Button(..., font=default_font)
hardware=Button(..., font=default_font)
...

Use the object-oriented features of python

Creating GUIs requires a lot of objects that must be referred to from many places. There are a couple solutions to this problem: use lots of global variables, or use a class to encapsulate those objects in one place.

This post is already too long to fully describe how to use object-oriented techniques. You can read more about it in this stackoverflow answer: https://stackoverflow.com/a/17470842/7432

The example from that answer is here:

import tkinter as tk

class MainApplication(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent

        <create the rest of your GUI here>

if __name__ == "__main__":
    root = tk.Tk()
    MainApplication(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

Don't use wildcard imports

Although many tkinter tutorials do it this way, they go against PEP8 and good coding practices. I recommend importing it and giving it a shorthand of "tk". You then need to prefix every widget with tk. which IMHO makes the code easier to understand (the Zen of Python (PEP20) says "explicit is better than implicit")

For example:

import tkinter as tk
...
root = tk.TK()
button = tk.Button(...)
...

Consider a different UI design altogether

If you are creating a troubleshooting guide, you might want to consider a wizard-like design which has a series of screens tied together with buttons (eg: next, back)

For an example of how to do that, start with this stackoverflow question: Creating a wizard in Tkinter

\$\endgroup\$

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