Меню
Видеоучебник
Видеоучебник  /  Информатика  /  Основы алгоритмизации и программирования на языке Python  /  Модель обработки данных в приложении с графическим интерфейсом

Модель обработки данных в приложении с графическим интерфейсом

Урок 33. Основы алгоритмизации и программирования на языке Python

Из этого видеоурока ученики узнают, для чего в приложениях с графическим пользовательским интерфейсом принято выделять в отдельные модули модель обработки данных и представление, как соотносятся эти части между собой и что они содержат. Также в уроке описано создание модели обработки данных для приложения «Калькулятор».

Конспект урока "Модель обработки данных в приложении с графическим интерфейсом"

Вопросы:

·     Декомпозиция приложения с графическим интерфейсом.

·     Модель обработки данных для приложения «Калькулятор».

Ранее при написании приложения с графическим интерфейсом, мы всё описывали в одном модуле. Но предположим, что данные в нашей программе нужно представить как-нибудь иначе. Тогда придётся полностью изменять её, несмотря на то, что сами данные остались прежними, а изменилась лишь форма их представления.

Чтобы сократить количество таких ситуаций, было предложено делить приложения с графическим интерфейсом на две части: модель обработки данных и представление. При этом модель обработки данных решает основную задачу. Она принимает на вход исходные данные задачи, обрабатывает их и возвращает выходные данные задачи. Для чего же тогда нужно представление? Оно отвечает за взаимодействие программы и пользователя. По сути это графический интерфейс программы. Представление принимает на вход данные, которые задаёт пользователь, преобразует эти данные в форму, в которой их принимает модель обработки. После чего получает выходные данные задачи от модели обработки и представляет их в форме, в которой их должен воспринять пользователь. При этом важно, что модель обработки данных не зависит от представления.

Рассмотрим пример. Предположим, что у нас есть программа, которая должна показать поведение математической функции. Выходные данные программы – это набор пар чисел (значений функции) при разных значениях аргумента. Их можно представить в текстовой форме, то есть в виде простого списка чисел, а можно на основании полученных данных построить график.

Если в приложении мы выделим модель обработки данных в отдельный модуль, то на основании одних и тех же вычислений можно будет написать несколько разных программ с разным представлением выходных данных. При этом модель обработки данных изменяться не будет, ведь она не зависит от представления. То есть программисту не нужно описывать процесс решения задачи снова, будет достаточно изменить лишь интерфейс.

Реализуем на практике описанное разделение данных. Напишем приложение «Калькулятор» для выполнения основных арифметических операций над целыми числами. Подумаем, как должен выглядеть и работать калькулятор. Мы сделаем его похожим по виду и принципу работы на обычный электронный калькулятор, который вы уже наверняка не раз использовали. У него будет дисплей и кнопки для управления. Прежде всего это кнопки с цифрами, а также кнопки для четырёх основных арифметических операций и «=». И, наконец, у калькулятора должна быть кнопка «Сброс». Обозначим её буквой «С». Так как калькулятор будет обрабатывать целые числа, то кнопка с запятой на нём не нужна.

Теперь подумаем, как должен работать калькулятор. Вначале у него на дисплее цифра 0. Нажимая на кнопки с цифрами, пользователь вводит первое число, после чего нажимает на кнопку с операцией. При нажатии на эту кнопку число на дисплее, а также выбранная операция сохраняются в память калькулятора. Далее пользователь, нажимая на кнопки с цифрами, вводит второе число. После этого при нажатии на кнопку с операцией или на кнопку «=», выполняется операция, сохранённая в памяти калькулятора. При этом результат операции, а также выбранное действие сохраняются в память калькулятора. При нажатии на «сброс» состояние калькулятора становится таким же, как в начальный момент времени. Также отдельно стоит рассмотреть случай деления на ноль. Условимся, что в этом случае будем обнулять число в памяти и выводить на экран сообщение о том, что на ноль делить нельзя.

Создание приложения начинается с модели обработки данных. Подумаем, как она должна работать. Вся модель приложения будет описана в отдельном классе, назовём его calc. По сути, это и будет наш калькулятор, только управление им будет осуществляться через текстовый интерфейс. Пользователь видит лишь то, что изображено на дисплее калькулятора, но не в состоянии как-то воздействовать на дисплей напрямую. Поэтому в классе будет одно открытое текстовое поле. Назовём его display. Оно будет доступно только для чтения, но не для изменения. Пользователь управляет калькулятором, нажимая на его кнопки. Поэтому определим в описываемом классе один открытый метод. Назовём его pressButton.

Начнём программирование модели. Создадим класс calc. У него не будет предков, поэтому после его имени сразу запишем двоеточие. Опишем конструктор класса. Создадим в нём поля, необходимые для работы калькулятора. Пока все они будут внутренними, так как пользователь не должен иметь возможности воздействовать на них напрямую. Прежде всего нам нужно поле для хранения текста, отображаемого на дисплее. Назовём его __display, и сначала в нём будет цифра 0. Также нам нужно поле для хранения информации о последней нажатой кнопке. Назовём его __lastBtn. Вначале оно будет содержать пустую строку. Ещё создадим поле для хранения числа в памяти калькулятора – __num. Сначала в нём будет 0. И, наконец, нам нужно поле с информацией об операции, которую нужно выполнить. Назовём его __oper. Вначале в нём будет пустая строка. Описание конструктора класса завершено.

class calc:

    def __init__ (self):

        self.__display = '0'

        self.__lastBtn = ''

        self.__num = 0

        self.__oper = ''

Мы помним, что поле «Дисплей» должно быть доступно для чтения. Чтобы открыть к нему доступ, опишем внутренний метод-гетер getDisplay, который будет возвращать значение этого поля. Чтобы получить поле, доступное только для чтения, объявим в классе открытое свойство display, в котором для чтения укажем метод getDisplay, описанный нами ранее. Так мы организовали доступ для чтения к полю __display.

def __getDisplay (self):

    return self.__display

 

display = property (__getDisplay)

Опишем единственный открытый метод для управления калькулятором pressButton. У него, кроме параметра self, должен быть ещё один: текст, который изображён на нажатой кнопке калькулятора. Назовём его btn. В начале работы метода мы должны определить, какая кнопка калькулятора была нажата: кнопка с цифрой, «cброс» или кнопка с операцией. Для этого опишем ветвление с условием, что в строке btn хранится цифра. Для этого у строки вызовем метод isdigit. Если это условие выполняется, то была нажата кнопка с цифрой. Действия для этого случая мы опишем позже. Далее запишем ветвь elif, которая проверяет, является ли нажатая кнопка кнопкой сброса. Для этого строка btn должна содержать единственный символ – «C». Мы также опишем действия для этого случая позже. И, наконец, запишем у нашего ветвления ветвь else. Она сработает, если была нажата не кнопка с цифрой и не кнопка «Сброс», то есть кнопка с операцией. Действия и для этого случая опишем позже. В конце мы в любом случае сохраним в поле __lastBtn текст из строки btn.

def pressButton (self, btn):

    if btn.isdigit ():

        pass

    elif btn == 'C':

        pass

    else:

        pass

    self.__lastBtn = btn

Теперь опишем действия для каждого случая. Если была нажата кнопка с цифрой, то мы должны проверить, какая кнопка была нажата до этого. И если это была кнопка не с цифрой, необходимо очистить дисплей. Для этого запишем ветвление с условием, что в поле __lastBtn записана не цифра. Если это условие выполняется, присвоим полю display пустую строку. Далее, так как мы нажали кнопу с цифрой, добавим эту цифру в конец строки, которая отображается на дисплее.

if btn.isdigit ():

    if not self.__lastBtn.isdigit ():

        self.__display = ''

    self.__display = self.__display + btn

Теперь опишем действия при нажатии кнопки «cброс». В данном случае калькулятор должен вернуться к своему начальному состоянию. Для этого вызовем у него метод-конструктор. В результате все поля примут свои начальные значения.

self.__init__ ()

И, наконец, рассмотрим случай, когда была нажата кнопка операции или «=». Ещё раз подумаем, как в этом случае должен работать калькулятор. Он будет по-разному вести себя, в зависимости от того, какая кнопка была нажата до этого. Если ранее была нажата кнопка с цифрой, то при нажатии на кнопку с операцией сначала должна быть выполнена операция, которая содержится в памяти калькулятора. После чего полученное число и операция, указанная на нажатой кнопке, будут сохранены в памяти калькулятора. Если же ранее была нажата кнопка с операцией или кнопка «=», то эта операция была внесена в память калькулятора. Соответственно, новая операция просто заменит уже содержащуюся в памяти калькулятора.

Запрограммируем описанное поведение калькулятора. Вначале запишем ветвление с условием, что в поле __lastBtn содержится цифра, а именно то, что ранее была нажата кнопка с цифрой. Если это условие истинно, то должна выполниться арифметическая операция, содержащаяся в памяти калькулятора. Однако прежде чем её выполнить, мы должны узнать, что это за операция. Запишем ветвление с условием, что в поле __oper символ «+». Если это условие выполняется, то мы должны вычислить сумму числа, которое было задано ранее, а также числа, которое записано на дисплее в данный момент. После чего вывести её на дисплей калькулятора. Для этого запишем инструкцию присваивания полю __display значения выражения, преобразованного в текстовый формат, так как в этом поле должны содержаться текстовые данные. Выражение – это сумма числа из поля num, а также числа из поля __display, преобразованного в целочисленный тип данных из текстового. Также в ветвях elif запрограммируем выполнение операций умножения и разности.

Теперь опишем операцию деления. При этом мы должны отдельно рассмотреть случай, когда делитель равен нулю. Проверим это. Запишем ветвление с условием, что в поле__display содержится только символ «0». Если данное условие выполняется, то делитель равен нулю. В этом случае мы выведем на экран сообщение о том, что делить на ноль нельзя, в противном случае – результат деления чисел, округлённый до целых, так как наш калькулятор предназначен для обработки целых чисел. Далее мы попробуем внести число, которое выведено на дисплее в память, присвоив соответствующее значение полю __num. Это не сработает, если на дисплей было выведено сообщение о том, что на ноль делить нельзя. Для этого мы опишем обработчик исключения ValueError. Если возникло это исключение, то обнулим число в памяти. И, наконец, мы обновим данные о последней заданной операции, присвоив полю __oper значение переменной btn.

if self.__lastBtn.isdigit ():

    if self.__oper == '+':

        self.__display = str (self.__num + int (self.__display))

    elif self.__oper == '*':

        self.__display = str (self.__num * int (self.__display))

    elif self.__oper == '-':

        self.__display = str (self.__num - int (self.__display))

    elif self.__oper == '/':

        if self.__display == '0':

            self.__display = 'Делить на ноль нельзя'

        else:

            self.__display = str (round (self.__num / int (self.__display)))

     try:

         self.__num = int (self.__display)

     except ValueError:

         self.__num = 0

     self.__oper = btn

Мы описали модель. Протестируем её. Чтобы облегчить тестирование, сделаем так, чтобы после нажатия любой кнопки калькулятора, на экран выводились данные сего дисплея. Для этого в конце метода pressButton запишем соответствующую инструкцию. Сохраним код в модуле с именем calcModel.py. И запустим его на выполнение. Создадим в переменной clc объект класса calc. Проверим доступ к полю display, вызвав его значение. Как видим, вначале в нём записан ноль. Теперь, вызывая метод pressButton, мы будем имитировать нажатие на кнопки калькулятора.  Вычислим таким образом произведение чисел 25 и 6. Мы получили число 150. Вычтем из него число 30 и полученное число разделим на 60. Мы получили число 2. Прибавим к нему 3. Мы получили 5. Попробуем разделить это число на ноль. Мы получили сообщение о том, что на ноль делить нельзя. При нажатии на кнопку с цифрой оно исчезает с дисплея и появляется выбранная цифра. Модель работает правильно. Уберём из метода инструкцию вывода данных дисплея на экран и сохраним модуль.

Мы узнали:

·     В приложениях с графическим интерфейсом часто в отдельные модули выделяют модель обработки данных и представление.

·     Модель обработки данных отвечает за получение выходных данных из входных и не зависит от представления.

0
1091

Комментарии 0

Чтобы добавить комментарий зарегистрируйтесь или на сайт