Python - Quiz Game with Tkinter

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
4
down vote

favorite












I have made a little Quiz Game in Python. This was my first experience in programming Gui's in Python with Tkinter. In general, I do not have much knowledge about graphic programming and have acquired the necessary knowledge through skimming internet articles and try and error. Accordingly, the code looks like sciolism and semi-professional structuring. That should be improved. I will not be able to avoid a good basic tutorial on graphic programming, I think. However, if you have tips for me how to improve the style I would be grateful to hear them.



from tkinter import Tk, Frame, Label, Button 
from time import sleep

class Question:
def __init__(self, question, answers, correctLetter):
self.question = question
self.answers = answers
self.correctLetter = correctLetter

def check(self, letter, view):
global right
if(letter == self.correctLetter):
label = Label(view, text="Right!")
right += 1
else:
label = Label(view, text="Wrong!")
label.pack()
view.after(1000, lambda *args: self.unpackView(view))


def getView(self, window):
view = Frame(window)
Label(view, text=self.question).pack()
Button(view, text=self.answers[0], command=lambda *args: self.check("A", view)).pack()
Button(view, text=self.answers[1], command=lambda *args: self.check("B", view)).pack()
Button(view, text=self.answers[2], command=lambda *args: self.check("C", view)).pack()
Button(view, text=self.answers[3], command=lambda *args: self.check("D", view)).pack()
return view

def unpackView(self, view):
view.pack_forget()
askQuestion()

def askQuestion():
global questions, window, index, button, right, number_of_questions
if(len(questions) == index + 1):
Label(window, text="Thank you for answering the questions. " + str(right) + " of " + str(number_of_questions) + " questions answered right").pack()
return
button.pack_forget()
index += 1
questions[index].getView(window).pack()

questions =
file = open("questions.txt", "r")
line = file.readline()
while(line != ""):
questionString = line
answers =
for i in range (4):
answers.append(file.readline())

correctLetter = file.readline()
correctLetter = correctLetter[:-1]
questions.append(Question(questionString, answers, correctLetter))
line = file.readline()
file.close()
index = -1
right = 0
number_of_questions = len(questions)

window = Tk()
button = Button(window, text="Start", command=askQuestion)
button.pack()
window.mainloop()


questions.txt (this file has to be in the same folder)



Where is Germany?
In Europe
In Great Britain
In Asia
In the USA
A
Where is England?
In Asia
On an island
In the USA
In China
B
What is the etymological meaning of antibiotics?
For Life
For Health
Against Live
Against Diseases
C
"Portability is for people who can not write new programs." From whom does the quote come from?
Bill Gates
Hillary Clinton
Richard Stallman
Linus Torvalds
D
Who is the richest man in the world?
Jeff Bezos
Bill Gates
Donald Trump
Me
AX






share|improve this question



























    up vote
    4
    down vote

    favorite












    I have made a little Quiz Game in Python. This was my first experience in programming Gui's in Python with Tkinter. In general, I do not have much knowledge about graphic programming and have acquired the necessary knowledge through skimming internet articles and try and error. Accordingly, the code looks like sciolism and semi-professional structuring. That should be improved. I will not be able to avoid a good basic tutorial on graphic programming, I think. However, if you have tips for me how to improve the style I would be grateful to hear them.



    from tkinter import Tk, Frame, Label, Button 
    from time import sleep

    class Question:
    def __init__(self, question, answers, correctLetter):
    self.question = question
    self.answers = answers
    self.correctLetter = correctLetter

    def check(self, letter, view):
    global right
    if(letter == self.correctLetter):
    label = Label(view, text="Right!")
    right += 1
    else:
    label = Label(view, text="Wrong!")
    label.pack()
    view.after(1000, lambda *args: self.unpackView(view))


    def getView(self, window):
    view = Frame(window)
    Label(view, text=self.question).pack()
    Button(view, text=self.answers[0], command=lambda *args: self.check("A", view)).pack()
    Button(view, text=self.answers[1], command=lambda *args: self.check("B", view)).pack()
    Button(view, text=self.answers[2], command=lambda *args: self.check("C", view)).pack()
    Button(view, text=self.answers[3], command=lambda *args: self.check("D", view)).pack()
    return view

    def unpackView(self, view):
    view.pack_forget()
    askQuestion()

    def askQuestion():
    global questions, window, index, button, right, number_of_questions
    if(len(questions) == index + 1):
    Label(window, text="Thank you for answering the questions. " + str(right) + " of " + str(number_of_questions) + " questions answered right").pack()
    return
    button.pack_forget()
    index += 1
    questions[index].getView(window).pack()

    questions =
    file = open("questions.txt", "r")
    line = file.readline()
    while(line != ""):
    questionString = line
    answers =
    for i in range (4):
    answers.append(file.readline())

    correctLetter = file.readline()
    correctLetter = correctLetter[:-1]
    questions.append(Question(questionString, answers, correctLetter))
    line = file.readline()
    file.close()
    index = -1
    right = 0
    number_of_questions = len(questions)

    window = Tk()
    button = Button(window, text="Start", command=askQuestion)
    button.pack()
    window.mainloop()


    questions.txt (this file has to be in the same folder)



    Where is Germany?
    In Europe
    In Great Britain
    In Asia
    In the USA
    A
    Where is England?
    In Asia
    On an island
    In the USA
    In China
    B
    What is the etymological meaning of antibiotics?
    For Life
    For Health
    Against Live
    Against Diseases
    C
    "Portability is for people who can not write new programs." From whom does the quote come from?
    Bill Gates
    Hillary Clinton
    Richard Stallman
    Linus Torvalds
    D
    Who is the richest man in the world?
    Jeff Bezos
    Bill Gates
    Donald Trump
    Me
    AX






    share|improve this question























      up vote
      4
      down vote

      favorite









      up vote
      4
      down vote

      favorite











      I have made a little Quiz Game in Python. This was my first experience in programming Gui's in Python with Tkinter. In general, I do not have much knowledge about graphic programming and have acquired the necessary knowledge through skimming internet articles and try and error. Accordingly, the code looks like sciolism and semi-professional structuring. That should be improved. I will not be able to avoid a good basic tutorial on graphic programming, I think. However, if you have tips for me how to improve the style I would be grateful to hear them.



      from tkinter import Tk, Frame, Label, Button 
      from time import sleep

      class Question:
      def __init__(self, question, answers, correctLetter):
      self.question = question
      self.answers = answers
      self.correctLetter = correctLetter

      def check(self, letter, view):
      global right
      if(letter == self.correctLetter):
      label = Label(view, text="Right!")
      right += 1
      else:
      label = Label(view, text="Wrong!")
      label.pack()
      view.after(1000, lambda *args: self.unpackView(view))


      def getView(self, window):
      view = Frame(window)
      Label(view, text=self.question).pack()
      Button(view, text=self.answers[0], command=lambda *args: self.check("A", view)).pack()
      Button(view, text=self.answers[1], command=lambda *args: self.check("B", view)).pack()
      Button(view, text=self.answers[2], command=lambda *args: self.check("C", view)).pack()
      Button(view, text=self.answers[3], command=lambda *args: self.check("D", view)).pack()
      return view

      def unpackView(self, view):
      view.pack_forget()
      askQuestion()

      def askQuestion():
      global questions, window, index, button, right, number_of_questions
      if(len(questions) == index + 1):
      Label(window, text="Thank you for answering the questions. " + str(right) + " of " + str(number_of_questions) + " questions answered right").pack()
      return
      button.pack_forget()
      index += 1
      questions[index].getView(window).pack()

      questions =
      file = open("questions.txt", "r")
      line = file.readline()
      while(line != ""):
      questionString = line
      answers =
      for i in range (4):
      answers.append(file.readline())

      correctLetter = file.readline()
      correctLetter = correctLetter[:-1]
      questions.append(Question(questionString, answers, correctLetter))
      line = file.readline()
      file.close()
      index = -1
      right = 0
      number_of_questions = len(questions)

      window = Tk()
      button = Button(window, text="Start", command=askQuestion)
      button.pack()
      window.mainloop()


      questions.txt (this file has to be in the same folder)



      Where is Germany?
      In Europe
      In Great Britain
      In Asia
      In the USA
      A
      Where is England?
      In Asia
      On an island
      In the USA
      In China
      B
      What is the etymological meaning of antibiotics?
      For Life
      For Health
      Against Live
      Against Diseases
      C
      "Portability is for people who can not write new programs." From whom does the quote come from?
      Bill Gates
      Hillary Clinton
      Richard Stallman
      Linus Torvalds
      D
      Who is the richest man in the world?
      Jeff Bezos
      Bill Gates
      Donald Trump
      Me
      AX






      share|improve this question













      I have made a little Quiz Game in Python. This was my first experience in programming Gui's in Python with Tkinter. In general, I do not have much knowledge about graphic programming and have acquired the necessary knowledge through skimming internet articles and try and error. Accordingly, the code looks like sciolism and semi-professional structuring. That should be improved. I will not be able to avoid a good basic tutorial on graphic programming, I think. However, if you have tips for me how to improve the style I would be grateful to hear them.



      from tkinter import Tk, Frame, Label, Button 
      from time import sleep

      class Question:
      def __init__(self, question, answers, correctLetter):
      self.question = question
      self.answers = answers
      self.correctLetter = correctLetter

      def check(self, letter, view):
      global right
      if(letter == self.correctLetter):
      label = Label(view, text="Right!")
      right += 1
      else:
      label = Label(view, text="Wrong!")
      label.pack()
      view.after(1000, lambda *args: self.unpackView(view))


      def getView(self, window):
      view = Frame(window)
      Label(view, text=self.question).pack()
      Button(view, text=self.answers[0], command=lambda *args: self.check("A", view)).pack()
      Button(view, text=self.answers[1], command=lambda *args: self.check("B", view)).pack()
      Button(view, text=self.answers[2], command=lambda *args: self.check("C", view)).pack()
      Button(view, text=self.answers[3], command=lambda *args: self.check("D", view)).pack()
      return view

      def unpackView(self, view):
      view.pack_forget()
      askQuestion()

      def askQuestion():
      global questions, window, index, button, right, number_of_questions
      if(len(questions) == index + 1):
      Label(window, text="Thank you for answering the questions. " + str(right) + " of " + str(number_of_questions) + " questions answered right").pack()
      return
      button.pack_forget()
      index += 1
      questions[index].getView(window).pack()

      questions =
      file = open("questions.txt", "r")
      line = file.readline()
      while(line != ""):
      questionString = line
      answers =
      for i in range (4):
      answers.append(file.readline())

      correctLetter = file.readline()
      correctLetter = correctLetter[:-1]
      questions.append(Question(questionString, answers, correctLetter))
      line = file.readline()
      file.close()
      index = -1
      right = 0
      number_of_questions = len(questions)

      window = Tk()
      button = Button(window, text="Start", command=askQuestion)
      button.pack()
      window.mainloop()


      questions.txt (this file has to be in the same folder)



      Where is Germany?
      In Europe
      In Great Britain
      In Asia
      In the USA
      A
      Where is England?
      In Asia
      On an island
      In the USA
      In China
      B
      What is the etymological meaning of antibiotics?
      For Life
      For Health
      Against Live
      Against Diseases
      C
      "Portability is for people who can not write new programs." From whom does the quote come from?
      Bill Gates
      Hillary Clinton
      Richard Stallman
      Linus Torvalds
      D
      Who is the richest man in the world?
      Jeff Bezos
      Bill Gates
      Donald Trump
      Me
      AX








      share|improve this question












      share|improve this question




      share|improve this question








      edited Feb 7 at 17:17
























      asked Feb 7 at 16:25









      Dexter Thorn

      657521




      657521




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          4
          down vote



          accepted










          Use a single import



          Instead of importing each individual class, I recommend importing the whole module with a short name. You can then use the short name as a prefix for all of your commands. It makes your code a bit more self-documenting, especially if you mix both tkinter and ttk in the same application.



          For example:



          import tkinter as tk
          ...
          window = tk.Tk()
          button = tk.Button(window, text="Start", command=askQuestion)


          Separate widget creation from layout



          In my experience, the layout of a GUI changes a lot more than the actual widgets, especially early in development. By separating widget creation from widget layout, it makes debugging much easier. It also makes it much easier to visualize the layout just by looking at the code.



          Instead of this:



          Label(view, text=self.question).pack()
          Button(view, text=self.answers[0], command=lambda *args: self.check("A", view)).pack()
          Button(view, text=self.answers[1], command=lambda *args: self.check("B", view)).pack()
          Button(view, text=self.answers[2], command=lambda *args: self.check("C", view)).pack()
          Button(view, text=self.answers[3], command=lambda *args: self.check("D", view)).pack()


          ... I recommend this:



          label = Label(view, text=self.question)
          button_a = Button(view, text=self.answers[0], command=lambda *args: self.check("A", view))
          button_b = Button(view, text=self.answers[1], command=lambda *args: self.check("B", view))
          button_c = Button(view, text=self.answers[2], command=lambda *args: self.check("C", view))
          button_d = Button(view, text=self.answers[3], command=lambda *args: self.check("D", view))

          label.pack()
          button_a.pack()
          button_b.pack()
          button_c.pack()
          button_d.pack()


          Explicitly set side for pack



          I recommend always explicitly setting the side for pack. Even though the default will likely never change, explicitly setting the side makes the code less ambiguous:



          label.pack(side="top")
          button_a.pack(side="top")
          button_b.pack(side="top")
          button_c.pack(side="top")
          button_d.pack(side="top")





          share|improve this answer





















            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187024%2fpython-quiz-game-with-tkinter%23new-answer', 'question_page');

            );

            Post as a guest






























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            4
            down vote



            accepted










            Use a single import



            Instead of importing each individual class, I recommend importing the whole module with a short name. You can then use the short name as a prefix for all of your commands. It makes your code a bit more self-documenting, especially if you mix both tkinter and ttk in the same application.



            For example:



            import tkinter as tk
            ...
            window = tk.Tk()
            button = tk.Button(window, text="Start", command=askQuestion)


            Separate widget creation from layout



            In my experience, the layout of a GUI changes a lot more than the actual widgets, especially early in development. By separating widget creation from widget layout, it makes debugging much easier. It also makes it much easier to visualize the layout just by looking at the code.



            Instead of this:



            Label(view, text=self.question).pack()
            Button(view, text=self.answers[0], command=lambda *args: self.check("A", view)).pack()
            Button(view, text=self.answers[1], command=lambda *args: self.check("B", view)).pack()
            Button(view, text=self.answers[2], command=lambda *args: self.check("C", view)).pack()
            Button(view, text=self.answers[3], command=lambda *args: self.check("D", view)).pack()


            ... I recommend this:



            label = Label(view, text=self.question)
            button_a = Button(view, text=self.answers[0], command=lambda *args: self.check("A", view))
            button_b = Button(view, text=self.answers[1], command=lambda *args: self.check("B", view))
            button_c = Button(view, text=self.answers[2], command=lambda *args: self.check("C", view))
            button_d = Button(view, text=self.answers[3], command=lambda *args: self.check("D", view))

            label.pack()
            button_a.pack()
            button_b.pack()
            button_c.pack()
            button_d.pack()


            Explicitly set side for pack



            I recommend always explicitly setting the side for pack. Even though the default will likely never change, explicitly setting the side makes the code less ambiguous:



            label.pack(side="top")
            button_a.pack(side="top")
            button_b.pack(side="top")
            button_c.pack(side="top")
            button_d.pack(side="top")





            share|improve this answer

























              up vote
              4
              down vote



              accepted










              Use a single import



              Instead of importing each individual class, I recommend importing the whole module with a short name. You can then use the short name as a prefix for all of your commands. It makes your code a bit more self-documenting, especially if you mix both tkinter and ttk in the same application.



              For example:



              import tkinter as tk
              ...
              window = tk.Tk()
              button = tk.Button(window, text="Start", command=askQuestion)


              Separate widget creation from layout



              In my experience, the layout of a GUI changes a lot more than the actual widgets, especially early in development. By separating widget creation from widget layout, it makes debugging much easier. It also makes it much easier to visualize the layout just by looking at the code.



              Instead of this:



              Label(view, text=self.question).pack()
              Button(view, text=self.answers[0], command=lambda *args: self.check("A", view)).pack()
              Button(view, text=self.answers[1], command=lambda *args: self.check("B", view)).pack()
              Button(view, text=self.answers[2], command=lambda *args: self.check("C", view)).pack()
              Button(view, text=self.answers[3], command=lambda *args: self.check("D", view)).pack()


              ... I recommend this:



              label = Label(view, text=self.question)
              button_a = Button(view, text=self.answers[0], command=lambda *args: self.check("A", view))
              button_b = Button(view, text=self.answers[1], command=lambda *args: self.check("B", view))
              button_c = Button(view, text=self.answers[2], command=lambda *args: self.check("C", view))
              button_d = Button(view, text=self.answers[3], command=lambda *args: self.check("D", view))

              label.pack()
              button_a.pack()
              button_b.pack()
              button_c.pack()
              button_d.pack()


              Explicitly set side for pack



              I recommend always explicitly setting the side for pack. Even though the default will likely never change, explicitly setting the side makes the code less ambiguous:



              label.pack(side="top")
              button_a.pack(side="top")
              button_b.pack(side="top")
              button_c.pack(side="top")
              button_d.pack(side="top")





              share|improve this answer























                up vote
                4
                down vote



                accepted







                up vote
                4
                down vote



                accepted






                Use a single import



                Instead of importing each individual class, I recommend importing the whole module with a short name. You can then use the short name as a prefix for all of your commands. It makes your code a bit more self-documenting, especially if you mix both tkinter and ttk in the same application.



                For example:



                import tkinter as tk
                ...
                window = tk.Tk()
                button = tk.Button(window, text="Start", command=askQuestion)


                Separate widget creation from layout



                In my experience, the layout of a GUI changes a lot more than the actual widgets, especially early in development. By separating widget creation from widget layout, it makes debugging much easier. It also makes it much easier to visualize the layout just by looking at the code.



                Instead of this:



                Label(view, text=self.question).pack()
                Button(view, text=self.answers[0], command=lambda *args: self.check("A", view)).pack()
                Button(view, text=self.answers[1], command=lambda *args: self.check("B", view)).pack()
                Button(view, text=self.answers[2], command=lambda *args: self.check("C", view)).pack()
                Button(view, text=self.answers[3], command=lambda *args: self.check("D", view)).pack()


                ... I recommend this:



                label = Label(view, text=self.question)
                button_a = Button(view, text=self.answers[0], command=lambda *args: self.check("A", view))
                button_b = Button(view, text=self.answers[1], command=lambda *args: self.check("B", view))
                button_c = Button(view, text=self.answers[2], command=lambda *args: self.check("C", view))
                button_d = Button(view, text=self.answers[3], command=lambda *args: self.check("D", view))

                label.pack()
                button_a.pack()
                button_b.pack()
                button_c.pack()
                button_d.pack()


                Explicitly set side for pack



                I recommend always explicitly setting the side for pack. Even though the default will likely never change, explicitly setting the side makes the code less ambiguous:



                label.pack(side="top")
                button_a.pack(side="top")
                button_b.pack(side="top")
                button_c.pack(side="top")
                button_d.pack(side="top")





                share|improve this answer













                Use a single import



                Instead of importing each individual class, I recommend importing the whole module with a short name. You can then use the short name as a prefix for all of your commands. It makes your code a bit more self-documenting, especially if you mix both tkinter and ttk in the same application.



                For example:



                import tkinter as tk
                ...
                window = tk.Tk()
                button = tk.Button(window, text="Start", command=askQuestion)


                Separate widget creation from layout



                In my experience, the layout of a GUI changes a lot more than the actual widgets, especially early in development. By separating widget creation from widget layout, it makes debugging much easier. It also makes it much easier to visualize the layout just by looking at the code.



                Instead of this:



                Label(view, text=self.question).pack()
                Button(view, text=self.answers[0], command=lambda *args: self.check("A", view)).pack()
                Button(view, text=self.answers[1], command=lambda *args: self.check("B", view)).pack()
                Button(view, text=self.answers[2], command=lambda *args: self.check("C", view)).pack()
                Button(view, text=self.answers[3], command=lambda *args: self.check("D", view)).pack()


                ... I recommend this:



                label = Label(view, text=self.question)
                button_a = Button(view, text=self.answers[0], command=lambda *args: self.check("A", view))
                button_b = Button(view, text=self.answers[1], command=lambda *args: self.check("B", view))
                button_c = Button(view, text=self.answers[2], command=lambda *args: self.check("C", view))
                button_d = Button(view, text=self.answers[3], command=lambda *args: self.check("D", view))

                label.pack()
                button_a.pack()
                button_b.pack()
                button_c.pack()
                button_d.pack()


                Explicitly set side for pack



                I recommend always explicitly setting the side for pack. Even though the default will likely never change, explicitly setting the side makes the code less ambiguous:



                label.pack(side="top")
                button_a.pack(side="top")
                button_b.pack(side="top")
                button_c.pack(side="top")
                button_d.pack(side="top")






                share|improve this answer













                share|improve this answer



                share|improve this answer











                answered Feb 7 at 17:51









                Bryan Oakley

                1,494712




                1,494712






















                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187024%2fpython-quiz-game-with-tkinter%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Greedy Best First Search implementation in Rust

                    Function to Return a JSON Like Objects Using VBA Collections and Arrays

                    C++11 CLH Lock Implementation