У даній статті ми напишемо простеньку малювалки на Python. На цьому прикладі ми потренуємося в створенні GUI. використанні макетів компонування в tkinter. передачі додаткових аргументів на функцію-обробник натискання кнопки і використанні lambda-функції в Python.
Для цього прикладу зручніше буде використовувати класовий підхід до створення GUI. Для початку визначимо клас Paint:
Запустивши цей код ви повинні отримати простеньке вікно, з яким ми будемо працювати далі.
Тепер напишемо для класу Paint метод setUI, в якому буде задаватися розташування всіх кнопок, міток і самого поля для малювання. У нас буде два ряди кнопок, перший ряд з кнопками встановлюють колір, другий ряд встановлює розмір кисті для малювання. Під ними буде йти поле для малювання.
Це досить об'ємний метод, однак багато рядки повторюються, так що наберіться терпіння:
Не забудьте додати виклик цього методу в __init__, щоб все працювало.
Якщо ви зробили все правильно, то при запуску всього коду ви побачите наступне вікно:
Тепер створимо метод малювання на полотні. Для початку створимо змінні класу встановлюють розмір і колір кисті, в метод __init__ допишіть:
Сам метод малювання буде виглядати наступним чином:
Малювання здійснюється шляхом створення кіл на полотні: користувач затискає ліву кнопку миші і при русі мишею, по шляху проходження курсору будуть отрісовиваться кола. Метод draw приймає аргумент event, на основі якого ми будемо формувати овали. Метод create_oval класу Canvas отримує чотири координати, на основі яких створюється квадрат, в який вписується коло. Як цих координат ми передаємо позицію курсора, тому перша координата по осі ікс буде позиція курсора мінус розмір кисті, друга координата по осі ікс - позиція курсора плюс розмір кисті, те ж саме для осі ігрек. Це може здатися складним, але скоро ви запустите наш додаток і побачите все своїми очима.
Залишилося тільки прив'язати до кинувся обробку щойно створеного методу. Додайте дотримуюся рядок після прикріплення кинувся (self.canvas.grid.)
Вже виглядає непогано. Додамо можливість змінювати колір кисті, змусимо кнопки верхнього ряду працювати. Для цього спочатку створимо метод зміни кольору кисті:
Після цього в кожній кнопці верхнього ряду слід додати код обробки натискання цієї кнопки за наступним шаблоном:
Код який ми додали - command = lambda: self.set_color ( "red"), прив'язує функцію з потрібним нам аргументом до кнопки. Ми використовуємо lambda-функцію тому-що, без lambda функція викликається відразу при створенні кнопки, а не тільки при її натисканні. (Можете спробувати такий рядок command = self.set_color ( "red") і колір відразу встановиться на червоний). Додавши цей код з потрібними аргументами (а це "green", "blue", "black", "white") до всіх кнопок отримаємо можливість змінювати колір кисті:
Тепер додамо метод зміни розміру кисті:
І модернізуємо код кожної кнопки нижнього ряду по наступним шаблоном:
Логіка роботи цих кнопок та ж, що і у кнопок зміни кольору кисті. Отримуємо наступний результат:
На цьому практично всі, залишилося додати функціонал очищення полотна. Ми залишили місце в верхньому ряду кнопок, його і заповнимо. Додайте наступний код в наш метод setUI:
Для очищення полотна ми використовуємо метод delete класу Canvas, щоб видалити всі з полотна як аргумент методу delete ми передаємо "all". Ось і все, у нас є примітивний Paint.
P.S. Запустивши програму, ви помітите, що якщо провести мишкою швидко, то лінії у нас виходять преривчастимі. Це викликано тим, що рух відбувається швидше, ніж завершується черговий цикл root.mainloop, відповідно все, що потрапляє "між" ітераціями циклу пропадає. Вирішення цієї проблеми саме по собі досить цікаве завдання, проте воно вимагає набагато більш складного коду.
P.P.S: Вихідний код проекту на GitHub