<?xml version="1.0" encoding="UTF-8"?>
<quiz>
<!-- question: 46347  -->
  <question type="coderunner">
    <name>
      <text>Counter GUI in Objects</text>
    </name>
    <questiontext format="html">
      <text><![CDATA[<h3>Exercise: Advanced counting with objects</h3>
<p>Recreate the program from Question 4 but encapsulate the GUI code in a class <code>CounterGui</code>. This program should have all the same functionality as the program in Question 4: The program has two buttons and a label that displays the current value of a counter. One button, bearing the text <code>+1</code>, should add one to the counter, while the other button, labelled <code>-1</code>, should subtract one from it. The counter should start at zero.</p>
<p><img class="img-responsive" style="vertical-align: text-bottom; margin: 0 .5em;" src="@@PLUGINFILE@@/counter.png" alt="" width="168" height="82" /></p>
<pre>from tkinter import *
from tkinter.ttk import *

# Write your code here

def main():
    """Set up the GUI and run it"""
    window = Tk()
    counter_gui = CounterGui(window)
    window.mainloop()

main()
</pre>]]></text>
<file name="counter.png" path="/" encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAKgAAABSCAYAAADAQp/LAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAwKSURBVHhe7Z1bbxTJFcc732DzCfINwrLIKAEiXjZPeSARBhsQi5VFSIkiBYUgJFurKMpi88ICihDBAiEhbgYhDKyxrF2tsQ1C3GxsbG42PICNMPebuUPF/7KPfeb49PRlembas1XST/TUOVXVfepHz3hmwN6DBw/M0NCQ5eLFi6a5udmsWrXK4Sg4u3fvNhcuXDDnz583PT095vr168YbHBw0AwMD5uDBgxOJbW1t5uPHjyXDp0+fzP79++3xhw8fpsQlyMkFzHHq1KlE5gqikGslDc6Z9gXOkX+7du0yZ86cMZcuXTLerVu3rJwVFRU2CZsJMCjNaBfsB/L37dtnj9+/fz8lLkFOWN69ezcF9Le3t0+J83HZiJKL8+3o6Mg4b75mmsG5yn2Bg3CRJPXwt4/umiRnGgTFyWr9BOJhQT7+puKYChEW2vSwUOFzERTwcdnG4hxLQVDeR3dTvNz0jh07ZpYtW5YhZ1okDQvJ5Ady+FM8oM3keX5QbhRyFZSTbTzOr1CCvn37Vu2PC85VCgrwGIJu3brVeDhobW1VBeVwIdIKLkwDMT9BAc/V4Llh0QTl/K9+t1m4eFUokIsxcg2A85OCcuS6QcjzorX9+nMB56cJin44CTetoJqQGlyGNEJCSRCTggK+kbxfg+cGgXyShheeg00O25BL47KtJWMEXzcIeV4ko9avjY8Czk0TFMC3DEGpcSElXAbO8ePHzZ8WLjR/+/s/1HihwIVqIKYJmgtSAg7iXBpZfCA3PFtDLp+f5tDW0uDrBuEnI294nM87KEDflDsoNS6lBgmB91BXrlxp5sz7jdl55oWZP3/+RCwM2txAy40DLhLgOIygfFO1OIfnShCPIiiONajhWK5B88i1ssHXz4YmKTX0a3LGeX2Kc8qLoERVVZUVE/y+rt8sWLAgQ5BsaPNxtDFxwIXizzQK+vTpUwuOqZ/mkHHqJyhfrhUWGu8HSUrnQOeRxJ2TwHlEElQTRIsBLuevl/7XClpeXm7u3bs3MVZDm+vjxyHTtMgzi5ruKjF9nihgngMHDthjXLgf//r3RrsJYUAujZObj74gaTAHagVwzDdHi8vxgHLpB7Io8PU0SFA6BzqP1AhKUON9IyMjZt6831o5f/W7r62cXy75p6msrLRxKQiH5uj67hfG29g1nl84QQEuXgMbELYhV46nzcdxGEHv3LljwbEGj2tzAL4Wba6WJ+EySEhOWp+D/qQkxXnkRdDly5dP3D09z7OCzpo1ywwPD9s4l0NCc4wJ2jnePyZoedNQRk7QXGHBPGEFffz4cSiQK8fT5uM4jKD4FC8MyNXmANpafKN5bjYon+SU68vHSUiKdXMWlKDN7e/vN59/PiNDToCPp2SuhOJWztGxY5Sb74fumqbFY4La+Eb0LzJNd7PPFxbMwQXloBAECo/vJoQBuXwsgaLjzzCC3rhxIxTI1eYAQWvRhmsxCfLkeeExSSv7ae64YM3EBCXWrFkz5e45549/tT8gafmAZOB9nT5P8Z2Qs7zJ3GW5XKgw4OL4Y8zhJyhAPvjP+k228GFALo2TYE58hIxjKQFBmx4G5GpzAKyRpKDyvOhO6defC1gztKDyadwP/CDE5fxy/XVTVlZmJ9TyCWwafzwmaOd4bExQe0cdlXNI5HKZ4oA5Dh8+bN8K0eIA5x8W2lAtBjAf/4YR5UeFb5gWB5g/KUEBXzNp5FtReIwbB86d9wP0xRIUT+Vc0LI//MVUV1eruRxsFn9MPySN9Y89xY895U8+tRPIyQXM0dTUZJ49e6bGAQqSFJjP7ytwmhTZkBsHeBxzBr2c4Ghz+MHXzAfYj8bGRnvuMoa+WIIuXbrU5pKgc+fOtf1oMleCDaNjvx+ShprKR+feaLrYmFyx63V1WbS4BgoUBdpUHGN8tu9ocgmCkBvHQRzzRREU0NiwyHWTAPP29vbaL8nj3GUcfbEEnTNnjln256+toJ999kv7nT30hx0/wd0ms3j8jvn9YObbTGM/JHlmY1cygoLnz5/b772ePXvWPHr0yK6j5cUFBSXwmATV4LlBSFk08D6oNtYPjNH6wyDXjgM+gezs7DQNDQ32AwD0BQpKyMZjoLu728yYMcMKVFtbO9FPjeeGhTYuWyxXcNF4zdPX12daWlrsax8/8KlTHPCCH2gxDcr/uXHixAlz+fJl8/r1a/PmzZspcgJfQQlqWuzJkydWUN7n13hOFDTJkkBbi9DyCwG/Q/2cePXqlSonQDy2oDBfCiqhpsWC0DYx38ji5Qp/StPiHJ4bBm1DOdqYbMQdB/i6SYK6ZBUUaI1ie/fuzciVUNNifmjiFAIpTFLwjdTiHJ4bBW1zOdoYjaj5HL5eUqAmgYJyeNPiEq1peRxNnnwjRckH2ESt3w8pQBDaBhNafjbijOVjkgJ1iCQooKbFwkBNixGaRPlASlEI+KZqcQ7PDULbYELLD0PU8XzNJEANUimoRJMrCaQQhYBvqBbn8NwgtA32QxuvETVfwteMA2qQIWgUcWTTcoIgUbSYBpcrCaQQhYI2UItp8E2PgrbphJavEWcMwcfGAdc+RVDepCB+UNNiYYgzVhMuCLnx0xFNBD+0TSe0/DBEGc/XiwOuN6ug1KQcaUATcLrCBdTiHJ5bSsQW9OjRo6ampsbhyBtHjhxRJQ0UFH2YgP+jKYcjaeCYE9SRWpygjlTjBHWkGieoI9WQoPLtqekt6KEq43mzTV2nEnNMK6SgJOk0FrTT1FXNNrOdoCVB6Qk6evecXVdnqpygJYEmKJimgo7ePWdXmUNPDzlBS4TSEhSvPasOjR47QUuFEhIUd0+S0glaKpSQoJCS/nMHwkk63SkhQTnuDloqOEEdqYYEpTfoS0RQR6kg76AkqhPUkQqkoIQT1JEKnKCOVOMEdaQaJ6gj1SQm6ObNm826devM6tWrHQzUBLXhRXf18kfWKxFB6zZsMFu2bLG/zAkDHZOgJqgNakRFd/XyR9aLBOXvgUYWdO3ateb+/ft2EvxPxY5JUBPUBjUiQV29/JH1SkRQ3JoxQFvQ8dzWBjUiQV29ssPrxQXlkqIvkqAYhN/K4JgKaiMFdfXyh9dLCkrEEpQ2wJGJn6A8xzFJ3gTF/03vmIqfoFquI7NeiQmKQfj1LamjYYXxvDKz/oISKxCojRQ0dfVKQZ0IXq8SFvSCWV/mGW/FCrPCCZqF9NSJ4PUiQXFXJWIL+vDhwxRywHw1Wvhvz2mxwuAnqJZbPIpfJyJIUBBLUPyGsOJw1nxb9pU5oMbGC39WixUGP0G13OJR/DoReREUv3Tp5s2bReIn880XS8xONbbTLPG+MN/8pMUKA2ojBS1uvTSKXyeC1ytRQfv7+wvLjzVm5pR/KOeZyh08b4ep9Gaamh95X2HxE1TLzTsZNas0OyZixa8TkTdBb9y4USR+MDUzK8wONbbDVKDwP2ixwuAnqJZbPIpfJyIvgo6MjJhr164ViRZTPSpovRqrt4WvbtFihQG1kYIWt14axa8TwesFx+j/35/GgmpA2synfm9mtWlRc/NLugVNT50IP0GJ2IJeuXLFoeAnqJbryKxXYoK+fPnS9Pb2OhRQGymoq5c/vF6aoERkQXt6ehwKfoJquY7MevkJir5Igr548cJ0d3c7FFAbKairlz+8XokIim8/3759235M1dXV5WCgJqiN/Ea9q5eOrBcck3JGFnTDhg1m06ZNZnBw0NrvmAQ1QW1QIxLU1csfWa9EBAW1tbXWetyaHZOgJqgN1cnVKzuyXnAs56d4hyNfcEH5G/WBgqK5XybryDeNjY3xBUVDzDF9wMZOR/jTO8C1TAh68uTJcR1di9KkHH5oTcvToKbF/NAE0JBScILi+QZOWkEbGhrsgWu5N00WCTUtpkFNi/khRcyGJgcIm5cPsB6c3LZtm/Gam5vtg7a2tvFSuBa3abJoRMkluCxaXMLzs6EJQkTJTQqsAxfhZEdHh/GuXr1qtm/fbioqKpykOTZNFI0ouRpRx0vROJokxQLnAwfhYn19vX2a9wYGBkxfX5+VFNbS3VS7UMf0RYqZNlpbWyf8g5x4fPr0aeMNDw/bd/chKcTcs2fPRKLDUUjwmrO9vX1CznPnzpn/A877R+M+NxRqAAAAAElFTkSuQmCC</file>
    </questiontext>
    <generalfeedback format="html">
      <text></text>
    </generalfeedback>
    <defaultgrade>2</defaultgrade>
    <penalty>0</penalty>
    <hidden>0</hidden>
    <idnumber></idnumber>
    <coderunnertype>python3_tkinter</coderunnertype>
    <prototypetype>0</prototypetype>
    <allornothing>1</allornothing>
    <penaltyregime>0</penaltyregime>
    <precheck>0</precheck>
    <showsource>0</showsource>
    <answerboxlines>18</answerboxlines>
    <answerboxcolumns>100</answerboxcolumns>
    <answerpreload></answerpreload>
    <globalextra></globalextra>
    <useace></useace>
    <resultcolumns></resultcolumns>
    <template></template>
    <iscombinatortemplate></iscombinatortemplate>
    <allowmultiplestdins></allowmultiplestdins>
    <answer><![CDATA[from tkinter import *
from tkinter.ttk import *

class CounterGui:
    """GUI for a counter"""
    
    def __init__(self, window):
        """Create the GUI object"""
        self.window = window
        self.count = 0
        self.result_label = Label(self.window, text=str(self.count))
        self.result_label.grid(row=0, column=0, columnspan=2)
        self.up_button = Button(self.window, text="+1", command=lambda : self.adjust(1))
        self.up_button.grid(row=1, column=0)
        self.down_button = Button(self.window, text="-1", command=lambda : self.adjust(-1))
        self.down_button.grid(row=1, column=1)

    def adjust(self, delta):
        """Increment/decrement the counter when a button is clicked"""
        self.count += delta
        self.result_label['text'] = str(self.count)
        

def main():
    """Set up the GUI and run it"""
    window = Tk()
    counter_gui = CounterGui(window)
    window.mainloop()

main()]]></answer>
    <validateonsave>0</validateonsave>
    <testsplitterre></testsplitterre>
    <language></language>
    <acelang></acelang>
    <sandbox></sandbox>
    <grader></grader>
    <cputimelimitsecs></cputimelimitsecs>
    <memlimitmb></memlimitmb>
    <sandboxparams></sandboxparams>
    <templateparams><![CDATA[{"requiredconstructs":["class"]}]]></templateparams>
    <hoisttemplateparams>0</hoisttemplateparams>
    <twigall>0</twigall>
    <uiplugin></uiplugin>
    <attachments>0</attachments>
    <attachmentsrequired>0</attachmentsrequired>
    <maxfilesize>0</maxfilesize>
    <filenamesregex></filenamesregex>
    <filenamesexplain></filenamesexplain>
    <displayfeedback>1</displayfeedback>
    <testcases>
      <testcase testtype="0" useasexample="0" hiderestiffail="1" mark="1.0000000" >
      <testcode>
                <text><![CDATA[The label should 
initally display "0".]]></text>
      </testcode>
      <stdin>
                <text></text>
      </stdin>
      <expected>
                <text><![CDATA[Label\((textvariable=<<0>>)|(text='0')\)]]></text>
      </expected>
      <extra>
                <text>getTk().display()</text>
      </extra>
      <display>
                <text>SHOW</text>
      </display>
    </testcase>
      <testcase testtype="0" useasexample="0" hiderestiffail="1" mark="1.0000000" >
      <testcode>
                <text><![CDATA[There is a button that
has the text "+1".]]></text>
      </testcode>
      <stdin>
                <text></text>
      </stdin>
      <expected>
                <text>Button\([^)]*text='\+1'\)</text>
      </expected>
      <extra>
                <text>getTk().display()</text>
      </extra>
      <display>
                <text>SHOW</text>
      </display>
    </testcase>
      <testcase testtype="0" useasexample="0" hiderestiffail="1" mark="1.0000000" >
      <testcode>
                <text><![CDATA[There is a button that
has the text "-1".]]></text>
      </testcode>
      <stdin>
                <text></text>
      </stdin>
      <expected>
                <text>Button\([^)]*text='-1'\)</text>
      </expected>
      <extra>
                <text>getTk().display()</text>
      </extra>
      <display>
                <text>SHOW</text>
      </display>
    </testcase>
      <testcase testtype="0" useasexample="0" hiderestiffail="1" mark="1.0000000" >
      <testcode>
                <text><![CDATA[When "+1" button is clicked twice
the label displays "2".]]></text>
      </testcode>
      <stdin>
                <text></text>
      </stdin>
      <expected>
                <text><![CDATA[Label\((textvariable=<<2>>)|(text='2')\)]]></text>
      </expected>
      <extra>
                <text><![CDATA[getTk().click(Selector(text="+1"))
getTk().click(Selector(text="+1"))
getTk().display()]]></text>
      </extra>
      <display>
                <text>SHOW</text>
      </display>
    </testcase>
      <testcase testtype="0" useasexample="0" hiderestiffail="1" mark="1.0000000" >
      <testcode>
                <text><![CDATA[When "-1" button is clicked twice
the label displays "-2".]]></text>
      </testcode>
      <stdin>
                <text></text>
      </stdin>
      <expected>
                <text><![CDATA[Label\((textvariable=<<-2>>)|(text='-2')\)]]></text>
      </expected>
      <extra>
                <text><![CDATA[getTk().click(Selector(text="-1", widget_type='Button'))
getTk().click(Selector(text="-1", widget_type='Button'))
getTk().display()]]></text>
      </extra>
      <display>
                <text>SHOW</text>
      </display>
    </testcase>
    </testcases>
    <tags>
      <tag><text>lab11</text>
</tag>
    </tags>
  </question>

</quiz>