Автор оригинала: Muhammad Junaid Khalid.
Вступление
В этом уроке мы узнаем, как использовать библиотеку wxPython для разработки графических пользовательских интерфейсов (GUI) для настольных приложений на Python. Графический интерфейс-это та часть вашего приложения, которая позволяет пользователю взаимодействовать с вашим приложением без необходимости вводить команды, они могут делать практически все одним щелчком мыши.
Некоторые из популярных альтернатив Python для разработки графического интерфейса включают Tkinter и pyqt . Однако в этом уроке мы узнаем о wxPython.
Прежде чем мы двинемся дальше, есть несколько предварительных условий для этого урока. Вы должны иметь базовое представление о синтаксисе Python и/или иметь хотя бы начальный уровень программирования на каком-то другом языке. Хотя вы можете следовать ему, даже если вы не соответствуете этим критериям, но вы можете найти некоторые части немного сложными. Если вы это сделаете, не стесняйтесь обращаться за разъяснениями в комментариях.
Установка
Процесс установки wxPython довольно прост, хотя и немного отличается в зависимости от используемой системы.
Mac и Windows
wxPython довольно легко установить на Mac и Windows с помощью pip package manager. Если в вашей системе установлен pip, выполните следующую команду для загрузки и установки wxPython:
$ pip install wxpython
Линукс
Для Linux эта процедура может быть немного болезненной, так как в ней есть много необходимых библиотек, которые необходимо установить. Я бы рекомендовал попробовать выполнить следующие две команды в последовательности:
# Command 1 $ sudo apt-get install dpkg-dev build-essential python2.7-dev python3.5-dev python3.6-dev libgstreamer-plugins-base1.0-dev libnotify-dev libwebkitgtk-3.0-dev libwebkit-dev libwebkitgtk-dev libjpeg-dev libtiff-dev libgtk2.0-dev libsdl1.2-dev libgstreamer-plugins-base0.10-dev freeglut3 freeglut3-dev # Command 2 $ pip install --upgrade --pre -f https://wxpython.org/Phoenix/snapshot-builds/ wxPython
Однако если они не работают, то вам придется вручную установить эти библиотеки, список которых упоминается в разделе “Предварительные условия” репо wxPython Github .
Примеры создания графических интерфейсов с помощью wxPython
В этом разделе мы запачкаем руки wxPython и создадим базовое приложение для манипулирования строками с некоторыми базовыми функциями, такими как подсчет количества слов, отображение частоты каждого слова, наиболее часто повторяющегося слова и т. Д.
Прежде чем двигаться дальше, мы создадим очень простое скелетное приложение, которое мы будем использовать в качестве отправной точки в следующих примерах для реализации более продвинутых функций графического интерфейса.
Без лишних слов, давайте начнем. Ниже приведен базовый скелет или структура графического приложения, построенного с использованием wxPython. Мы изменим его далее в следующем разделе, чтобы сделать его объектно-ориентированным для дополнительной функциональности.
import wx # Creates an App object which runs a loop to display the # GUI on the screen myapp = wx.App() # Initialises a frame that the user would be able to # interact with init_frame = wx.Frame(parent=None, title='Word Play') # Display the initialised frame on screen init_frame.Show() # Run a loop on the app object myapp.MainLoop()
Если цикл не запущен (т. е. вызов app.MainLoop ()
), то кадр появится на экране на долю секунды, и даже прежде, чем вы его увидите, он исчезнет. Эта функция гарантирует, что кадр остается видимым на экране до тех пор, пока пользователь не выйдет из программы, и делает это, запустив кадр в цикле.
Примечание : При запуске этой программы на Mac я получил следующую ошибку, когда запустил свой код с помощью python filename.py
команда в терминале:
This program needs access to the screen. Please run with a Framework build of python, and only when you are logged in on the main display of your Mac.
Чтобы избавиться от этого, просто используйте python
вместо python
в приведенной выше команде.
После запуска программы на экране должно появиться следующее пустое окно:
Объектно-ориентированный код
Прежде чем мы добавим функциональность в наш код, давайте сначала модулируем его, создавая классы и функции, чтобы он выглядел чище и его было легче расширить. Функциональность следующего кода такая же, как и раньше, однако он был переработан для реализации концепций объектно-ориентированного программирования.
import wx import operator # We make a class for frame, so that each time we # create a new frame, we can simply create a new # object for it class WordPlay(wx.Frame): def __init__(self, parent, title): super(WordPlay, self).__init__(parent, title=title) self.Show() def main(): myapp = wx.App() WordPlay(None, title='Word Play') myapp.MainLoop() main()
В приведенном выше сценарии мы создаем класс WordPlay
, который наследует класс wxFrame
. Конструктор класса WordPlay
принимает два параметра: parent
и title
. Внутри дочернего конструктора вызывается конструктор родительского класса для класса wxPython
и ему передаются атрибуты parent
и title
. Наконец, для отображения кадра вызывается метод show
. В методе main()
создается объект класса WordPlay
.
В приведенном выше сценарии мы создаем класс || WordPlay||, который наследует класс || wxFrame||. Конструктор класса || WordPlay || принимает два параметра: || parent || и || title || . Внутри дочернего конструктора вызывается конструктор родительского класса для класса || wxPython || и ему передаются атрибуты || parent || и || title||. Наконец, для отображения кадра вызывается метод || show||. В методе || main() || создается объект класса || WordPlay||.
Добавление функциональных возможностей
Мы будем добавлять функциональные возможности по одной, чтобы избежать путаницы относительно того, какая часть кода добавляется для какой конкретной функциональности. То, что нам нужно в нашем базовом приложении, – это текстовое поле, в которое мы можем добавить текст, а затем несколько кнопок для выполнения различных функций над этим текстом, таких как вычисление количества слов в нем, частоты каждого слова и т. Д.
Давайте начнем с добавления текстового поля в наше приложение, в которое мы можем добавить наш текст.
# Some of the code will be the same as the one above, # so make sure that you understand that before moving # to this part import wx import operator # We make a class for frame, so that each time we create a new frame, # we can simply create a new object for it class WordPlay(wx.Frame): def __init__(self, parent, title): super(WordPlay, self).__init__(parent, title=title) self.widgets() self.Show() # Declare a function to add new buttons, icons, etc. to our app def widgets(self): text_box = wx.BoxSizer(wx.VERTICAL) # Vertical orientation self.textbox = wx.TextCtrl(self, style=wx.TE_RIGHT) text_box.Add(self.textbox, flag=wx.EXPAND | wx.TOP | wx.BOTTOM, border=5) grid = wx.GridSizer(5, 5, 10, 10) # Rows, columns, vertical gap, horizontal gap text_box.Add(grid, proportion=2, flag=wx.EXPAND) self.SetSizer(text_box) def main(): myapp = wx.App() WordPlay(None, title='Word Play') myapp.MainLoop() main()
Как вы можете видеть, мы добавили новую функцию с именем widgets()
выше, и она была вызвана в конструкторе класса WordPlay
. Его цель-добавить новые виджеты на наш экран, однако в нашем случае нас интересует только один виджет, то есть текстовое поле, в которое мы можем добавить какой-то текст.
Давайте теперь разберемся в некоторых важных вещах, которые происходят внутри этой функции widgets ()
. Метод BoxSizer ()
, как следует из названия, управляет размером виджетов, а также их положением (относительным или абсолютным). Параметр wx.VERTICAL
указывает, что мы хотим иметь вертикальную ориентацию для этого виджета. TextCtrl
в основном добавляет небольшое текстовое поле в наш текущий from, где пользователь может ввести текстовый ввод. Метод Grid size()
помогает нам создать табличную структуру для нашего окна.
Хорошо, давайте посмотрим, как теперь выглядит наше приложение.
Теперь в окне нашего приложения можно увидеть текстовое поле.
Давайте перейдем дальше и добавим в наше приложение две кнопки: одну для подсчета количества слов в тексте, а вторую для отображения самого повторяющегося слова. Мы сделаем это в два этапа: сначала добавим две новые кнопки, а затем добавим обработчики событий в нашу программу, которые сообщат нам, на какую кнопку нажал пользователь, а также текст, введенный в текстовое поле, чтобы можно было выполнить определенное действие над вводом.
Добавление кнопок довольно просто, для этого требуется только добавить некоторый дополнительный код в нашу функцию “виджеты”. В приведенном ниже блоке кода мы будем отображать только обновленную функцию виджетов; остальная часть кода останется прежней.
# Adding buttons to our main window def widgets(self): text_box = wx.BoxSizer(wx.VERTICAL) self.textbox = wx.TextCtrl(self, style=wx.TE_RIGHT) text_box.Add(self.textbox, flag=wx.EXPAND | wx.TOP | wx.BOTTOM, border=5) grid = wx.GridSizer(2, 5, 5) # Values have changed to make adjustments to button positions button_list = ['Count Words', 'Most Repeated Word'] # List of button labels for lab in button_list: button = wx.Button(self, -1, lab) # Initialise a button object grid.Add(button, 0, wx.EXPAND) # Add a new button to the grid with the label from button_list text_box.Add(grid, proportion=2, flag=wx.EXPAND) self.SetSizer(text_box)
Как вы можете видеть, теперь в наше главное окно также добавлены две новые кнопки.
Добавление обработчика событий
Интерфейс нашего приложения теперь готов, все, что нам нужно сделать сейчас, это добавить обработчики событий для выполнения определенных действий при нажатии кнопок. Для этого нам придется создать новую функцию и добавить дополнительную строку кода в функцию виджетов. Давайте начнем с написания нашей функции.
# Declare an event handler function def event_handler(self, event): # Get label of the button clicked btn_label = event.GetEventObject().GetLabel() # Get the text entered by user text_entered = self.textbox.GetValue() # Split the sentence into words words_list = text_entered.split() # Perform different actions based on different button clicks if btn_label == "Count Words": result = len(words_list) elif btn_label == "Most Repeated Word": # Declare an empty dictionary to store all words and # the number of times they occur in the text word_dict = {} for word in words_list: # Track count of each word in our dict if word in word_dict: word_dict[word] += 1 else: word_dict[word] = 1 # Sort the dict in descending order so that the # most repeated word is at the top sorted_dict = sorted(word_dict.items(), key=operator.itemgetter(1), reverse=True) # First value in the dict would be the most repeated word result = sorted_dict[0] # Set the value of the text box as the result of our computation self.textbox.SetValue(str(result))
Логика, лежащая в основе функции “Самое повторяющееся слово”, заключается в том, что мы сначала запускаем цикл, который повторяет слово из списка всех слов. Затем он проверяет, существует ли это конкретное слово уже в словаре или нет; если это так, то это означает, что оно повторяется, и его значение увеличивается на единицу каждый раз, когда слово появляется снова. В противном случае, если он не существует в словаре, это означает, что он появился в предложении впервые, и его значение “вхождение” должно быть установлено равным 1. Наконец, мы сортируем словарь (аналогично сортировке списка Python ) в порядке убывания, так что слово с наибольшим значением (частотой) выходит на первое место, которое мы затем можем отобразить.
Итак, теперь, когда мы написали вычисление/действие, которое должно быть выполнено при нажатии определенной кнопки, давайте “свяжем” это действие с этой конкретной кнопкой. Для этого нам придется немного изменить нашу функцию виджеты
.
# Only one line needs to be added in the "for loop" of # our widgets function, so that's all we're showing for lab in button_list: button = wx.Button(self, -1, lab) self.Bind(wx.EVT_BUTTON, self.event_handler, button) grid.Add(button, 0, wx.EXPAND)
В приведенном выше коде self.Bind
call-это место, где происходит привязка. Он связывает определенное действие с определенной кнопкой, так что при нажатии на эту кнопку будет выполнено определенное действие, связанное с ней. В нашем конкретном случае у нас есть только одна функция обработчика событий, которая обрабатывает оба действия, проверяя во время выполнения, какая кнопка была нажата через свойство ‘label’, а затем выполняя связанное действие. Так и в самости.Bind
вызов мы связываем все наши кнопки с одной функцией ‘event_handler’.
Итак, наш код завершен. Давайте попробуем обе наши функции и посмотрим, работает ли все это так, как ожидалось.
На первом шаге, как показано ниже, мы вводим строку в текстовое поле:
Далее, если мы нажмем кнопку “Подсчитать слова”, вы увидите “7” в текстовом поле, так как в строке было 7 слов.
Пока все так хорошо!
Теперь давайте запишем еще одну строку в текстовое поле, как показано на следующем рисунке:
Теперь, если мы нажмем кнопку “Самое повторяющееся слово”, вы увидите наиболее повторяющиеся слова в текстовом поле вместе с частотой их появления, как показано ниже:
Работает отлично!
Мы добавили только две функции, но цель состояла в том, чтобы показать вам, как все эти компоненты связаны, вы можете добавить столько функций, сколько захотите, просто написав для них дополнительные функции. Кроме того, этот учебник не был слишком сосредоточен на эстетике. Есть много виджетов, доступных в wxPython, чтобы украсить вашу программу теперь, когда вы овладели базовыми знаниями инструментария.
Вывод
Подводя итог, мы узнали, что wxPython широко используется для разработки настольных приложений на основе графического интерфейса на Python, и что у Python также есть некоторые другие интересные альтернативы для него. Мы прошли через команды, чтобы загрузить и установить его на все популярные операционные системы. Наконец, мы узнали, как сделать модульное приложение с помощью wxPython, которое можно легко расширить, как это видно из этого урока, где мы построили базовое скелетное приложение и шаг за шагом добавили дополнительные функции.