Benutzer-Werkzeuge

Webseiten-Werkzeuge


en:examples

Inhaltsverzeichnis

Examples

EAN check

Tkinter/TTK

The EAN check is an example of a simple GUI application. It has an entry widget for entering an EAN and a text widget for the multi-line output of results.

This event method is programmed for the „Check“ button:

def bCheck_Command(self):
    # Input
    EAN = self.eEANCV.get()
    # Processing
    if not EAN.isdigit():
        self.output('An EAN must not contain any characters other than digits!')
    if len(EAN) == 13:
        self.output('Length of EAN: 13 ')
        self.output('Entered check digit: ' + EAN[12])
        sum = 0
        index = 0
        factor = 1
        while index < 12:
            sum = sum + int(EAN[index])*factor
            index = index + 1
            if factor == 1:
                factor = 3
            else:
                factor = 1
        if sum % 10 == 0:
            calculatedCheckDigit = 0
        else:
            calculatedCheckDigit = 10 - sum % 10
        if int(EAN[12]) == calculatedCheckDigit:
            self.output('The check digit ' + EAN[12] + ' is correct!')
        else:
            self.output('The entered check digit ' + EAN[12] + ' is incorrect!')
            self.output('The correct check digit is ' + str(calculatedCheckDigit))
    else:
        self.output('The entered EAN has ' + str(len(EAN)) + ' digits!')
        self.output('It must consist of 13 digits.')

According to the IPO principle, the input from the entry widget is read in first. The control variable eEANCV assigned to the entry widget is used for input or output. Its value can be read with eENACV.get() for input and with eEANCV.set(value) for output. With

    EAN = self.eEANCV.get()

the EAN entered in the Entry widget is read into the local variable EAN of type str(ing) and can then be processed.

The processing part checks whether 13 digits have been entered and then performs the check digit calculation.

Outputs are made to the text widget Output. It has very powerful methods, so even just outputting a single line isn't quite easy. A separate method output() is therefore used in order to simplify programming.

def output(self, line):
    self.Output.insert('end', line + '\n')

This inserts a line at the end of the text widget Output and ends it with the control character '\n' (NewLine). If an output line consists of several substrings, these must be put together with „+“. Numbers must first be converted into a string using str().

Download:

Qt variant of EAN check

In Qt we have a LineEdit widget for input and a PlainTextWidget for output. To read the EAN we use the text() method of LineEdit widget.

    EAN = self.leEAN.text()

The output is easier in Qt than in Tkinter/TTK:

    def output(self, line):
        self.Output.appendPlainText(line)

Download:

Car

This example is suitable for the introduction to object-oriented programming. Fuel gauge and mileage of a car are modeled. The actual modeling takes place with the class modeler. The license plate is not absolutely necessary, it is used to make it easier to distinguish between cars and to use another data type.

The result can be tested interactively in the UML window. The students understand the difference between the concepts class and object.

In the next step, the car class is used as a functional specification in a GUI program.

The GUI program uses the car class. To do this, it must be imported. A car is created and provided as attribute car1 of the GUI class for further use.

    from car import *
      ...
      self.car1 = car('DA RR 1013', 47, 7.3)

Tkinter/TKK

When refueling, the quantity entered in the entry widget is read in via the get() method of the control variable eAmountCV belonging to the widget and converted into the required data type using float.

    def bRefuel_Command(self):
        # Input from the GUI
        amount = float(self.eAmountCV.get())
        # Processing
        self.car1.refuel(amount)
        # Output
        self.show()

Then, according to the IPO principle, the entered amount is processed in the refuel() method.

Finally, the result is output with a separate method show(). The values for license plate, tank contents and mileage are retrieved via the get() methods of the class car and passed to the set() methods of the control variables eLicenseplateCV, eTankcontentCV and eMileageCV:

    def show(self):
        self.eLicenseplateCV.set(self.car1.get_licenseplate())
        self.eTankcontentCV.set(self.car1.get_tankcontent())
        self.eMileageCV.set(self.car1.get_mileage())
        self.lCar.place(x = self.car1.get_mileage(), y = 160)

The label widget lCar has been assigned a car image via the Image attribute in the object inspector. The place() method sets the x position of the car to the mileage.

Download

Qt

When refueling, the quantity is read in via the text() method of the LineEdit widget and converted into the required data type using float.

    def bRefuel_Command(self):
        # Input from the GUI
        amount = float(self.leAmount.text())
        # Processing
        self.car1.refuel(amount)
        # Output
        self.show()

Then, according to the IPO principle, the entered amount is processed in the refuel() method.

Finally, the result is output with a separate method show(). The values for license plate, tank contents and mileage are retrieved via the get() methods of the class car and passed to the setText() methods of the widgets leLicenseplate, leTankcontent and leMileage:

    def show(self):
        self.leLicenseplate.setText(self.car1.get_licenseplate())
        self.leTankcontent.setText(self.car1.get_tankcontent())
        self.leMileage.setText(self.car1.get_mileage())
        self.lCar.move(x = self.car1.get_mileage(), y = 160)

The label widget lCar has been assigned a car image via the Pixmap attribute in the object inspector. The move() method sets the x position of the car to the mileage.

Download

Linked List

Programming dynamic data structures is a significant challenge, as one must understand the concept of linking using references and perform complex operations on references. New are variables that have values that are references to objects or addresses.

In this example we consider a singly linked linear list. The list itself is modeled as a class LinkedList with nodes as list elements. As an attribute it has a reference to the head of the list.

The Node class can store data in the first attribute and a reference to a next node of the linked list in the next attribute. If a node has no next node, this attribute has the value None.

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

The implementation of an insert operation is difficult because four cases must be distinguished:

  1. The list is empty.
  2. It should be inserted at the beginning.
  3. It should be inserted at the end.
  4. It is intended to be inserted between two nodes.

The first two cases can be implemented with the method insert_first():

    def insert_first(self, node):
        node.next = self.head
        self.head = node

The implementation can be tested in the UML window. To do this, you create a linked list and a node, call the insert_first() method via the linkedlist1 object and enter the value node1 for the node parameter.

To insert at the end of the list, you must use a loop and a cursor variable to navigate to the last element. The new node is added there.

    def insert_last(self, node):
        if self.head is None:
            self.head = node
        else:
            cursor = self.head
            while cursor.next is not None:
                cursor = cursor.next
            cursor.next = node

Inserting before a node is the most difficult case because the new node must then be inserted after the previous node. In addition to the cursor, you need another reference to the previous node. The node before which to insert is determined by its data.

    def insert_before(self, data, new_node):
        if self.head.data == data:
            self.insert_first(new_node)
            return
 
        prev_node = self.head
        cursor = prev_node.next
        while cursor is not None and cursor.data != data:
            prev_node = cursor
            cursor = cursor.next
        if cursor is not None:
            new_node.next = cursor
            prev_node.next = new_node
        else:
            raise Exception("Node with data '%s' not found" % data)

Deleting a node is just as difficult because the previous node must be connected to the following one in order to delete it.

    def remove(self, data):
        if self.head.data == data:
            self.head = self.head.next
        else:
            prev_node = self.head
            cursor = prev_node.next
            while cursor is not None and cursor.data != data:
                prev_node = cursor
                cursor = cursor.next
            if cursor is not None:
                prev_node.next = cursor.next

The functionality of the implemented methods can be checked very well by interactive testing in the UML window, because the result is visualized in the object diagram. You can see immediately whether a method worked as expected. In the picture the list with the elements 'a, 'b' and 3 was created and then the node with data = 'b' was deleted. That worked, because the list consists only of the two elements 'a' and 3. The deleted node is just deleted from the list. Python's garbage collection takes care of it.

Important NOTE

In the UML window, objects are identified by their addresses. In the example, the address 0x01CFA688 for the node1 object.

>>> node1 = Node('a')
>>> print(node1)
<__main__.Node object at 0x01CFA688>

Therefore, do not implement a __repr__ function for your classes, because then these addresses will no longer be available.

Download:

en/examples.txt · Zuletzt geändert: 2022/08/25 21:28 von roehner