Python GUI là gì

GUI with Kivy Python

  • Báo cáo
  • Thêm vào series của tôi

Kivy

Đối với mọi ngôn ngữ lập trình đi kèm với nó là một framework hỗ trợ cho việc xây dựng GUI [Graphic User Interface] - Lập trình giao diện đồ họa. Với Python thì cũng có một số framework như: Qt, Thinker, WxWidgets, Kivy,.....bài viết này mình sẽ sử dụng Kivy. Điểm nổi bật của Kivy này là có thể run trên Linux, Windows, OS X, Android, iOS, and Raspberry Pi hay nói cách khác là đa nền tảng [nhạc nào cũng chơi được ], với cùng code thì có thể run trên các nền tảng khác. Có thể hiện tại mọi người thường chủ yếu tập trung vào Web, App và tập trung vào hai thứ đó, nhưng với app trên Desktop không hẳn là nó biến mất mà vẫn có những ứng dụng cần làm việc trên Desktop. Và mình cũng chỉ hướng dẫn sơ qua, đơn giản thôi, còn chi tiết thì mn nghiên cứu thêm.

Khi mình lướt qua Gallery của Kivy thì thấy một vài app được xây dựng trông cũng xịn, và có cả Game trên Desktop và một số Game được đưa lên hẳn trên Google Play. Mọi người cũng có thể xem thêm Docummentation của nó.

Dưới đây là một vài video về ứng dụng của Kivy :

Và cả làm Game nữa :

Dạo này thời tiết có chút thay đổi đâm ra câu cú có vẻ không được mượt mà, mong mn cảm thông :

Cài đặt

Hiện mình đang sử dụng HĐH Linux có sử dụng Anaconda để create env cho từng project nên mình sẽ install Kivy theo Anaconda và làm một số demo nho nhỏ. Mọi người cũng có thể tuỳ chọn theo platform phù hợp với mục đích sử dụng như dưới đây.

Platform Installation Packaging
Windows pip PyInstaller
OS X pip, Kivy.app Kivy.app, PyInstaller
Linux pip, PPA ---
Ras-Pi pip ----
Android python-for-android python-for-android
iOS kivy-ios kivy-ios
Anaconda conda ---

Với Anaconda thì có thể install một trong các lệnh sau:

conda install -c conda-forge kivy conda install -c conda-forge/label/cf201901 kivy conda install -c conda-forge/label/cf202003 kivy

Check version Kivy đã install:

import kivy print[kivy.__version__] # 2.0.0rc4

Ok như thế đã install xong môi trường, bây giờ là một vài demo nho nhỏ.

Cấu trúc

Về cơ bản để tạo một Appicaltion thì sẽ gồm 3 phần :

  • Tạo một class kế thừa class App
  • implement phương thức build[]
  • tạo instance class và gọi phương thức run[]
import kivy from kivy.app import App from kivy.uix.label import Label class MyApp[App]: def build[self]: return Label[text='Hello world'] if __name__ == '__main__': MyApp[].run[]

Save file và run thử python name_file.py.

Nguồn ảnh

API Graphic của Kivy được base trên lib OpenGL. Lib OpenGL thì được viết bằng C và nó hỗ trợ cho việc xây dựng giao diện như Canvas, Rectangle,...

Về Widgets & Layouts, trong bất cứ một ứng dụng nào thì ta sẽ luôn thao tác với Widgets & Layouts [như các button, list, action touch,...], tùy thuộc vào mục đích sử dụng mà ta sẽ xây dựng Layout hợp lý.

Một số widget cơ bản

Trong demo đầu tiên này mình sex làm quen đơn giản với UI trước. Việc đàu tiên là ta sẽ phải import các Interface của Kivy.

from kivy.app import App from kivy.uix.label import Label #from kivy.uix.button import Button class FirstKivy[App]: def build[self]: return Label[text="Hello Kivy!"] FirstKivy[].run[]

Button

from kivy.app import App from kivy.uix.button import Button class SimpleApp[App]: def build[self]: def a[instance,value]: print["welcome to edureka"] btn = Button[text="Kivy-Clicked!",font_size=150] btn.bind[state=a] return btn if __name__ == "__main__": SimpleApp[].run[]

Slider

from kivy.app import App from kivy.uix.slider import Slider class SimpleApp[App]: def build[self]: slide = Slider[orientation='vertical', value_track=True, value_track_color=[1,0,0,1]] return slide if __name__ == "__main__": SimpleApp[].run[]

Progress Bar

from kivy.app import App from kivy.uix.progressbar import ProgressBar class SimpleApp[App]: def build[self]: Progress = ProgressBar[max=1000] Progress.value = 650 return Progress if __name__ == "__main__": SimpleApp[].run[]

Image sau kết quả :

Relative Layout

from kivy.app import App from kivy.uix.relativelayout import RelativeLayout from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button from kivy.uix.label import Label from kivy.lang import Builder res = Builder.load_string['''BoxLayout: Label: text: 'Left' Button: text: 'Middle' on_touch_down: print['Middle: {}'.format[args[1].pos]] RelativeLayout: on_touch_down: print['Relative: {}'.format[args[1].pos]] Button: text: 'Right' on_touch_down: print['Right: {}'.format[args[1].pos]]'''] class SimpleApp[App]: def build[self]: return res if __name__ == "__main__": SimpleApp[].run[]

Image kết quả :

Các bạn run và xem thử kết quả. Và còn vô vàn những thứ khác nữa, các bạn có thể search thêm.

Demo App

Trong demo này mình sẽ làm một app nhận diện giới tính đơn giản. Sẽ có 2 cách để nhận diện, một là dùng hình ảnh để predict, hai là sẽ dùng camera real-time để dự đoán. Về dữ liệu thì ta sẽ sử dụng tập data UTKFace, tập data này với hơn 20k ảnh đã được annotation với labels là độ tuổi [từ 0-116], giới tính [male, female], màu da. Để đơn giản mình sẽ sử dụng opencv để detec ra khuôn mặt trong bức ảnh đó, rồi ta sẽ crop mặt đưa vào model để classification xem đang là giới tính gì. Về model và weights thì các bạn có thể tải và dùng luôn. Về giao diện, mình sẽ tạo 2 button với hai chức năng, một là lấy hình ảnh trực tiếp từ máy pc, hai là sử dụng Camera của máy tính.

Để dựng được UI như trên thì ta cần import các class App, Label, Window,...Để dựng được giao diện thì Kivy có một cách là tạo file .kv [file này cùng cấp thư mục với file main.py chính, sẽ định nghĩa UI cho App], như bên dưới đây.

: img_path: img_path GridLayout: cols:1 size: root.width, root.height FloatLayout: MDTextFieldRect: id: img_path hint_text: "Enter the image path here" multiline:False pos_hint: {"x":0.1, "top":0.83} size_hint: 0.75, 0.093 readonly: False on_text_validate: root.addBtn[] MDIconButton: icon: 'image-search' theme_text_color: 'Custom' text_color: app.theme_cls.primary_color size_hint: None, None size: 1 * dp[48], dp[48] text: '' opposite_colors: True pos_hint: {'center_x': .88, 'center_y': .794} on_release: root.file_manager_open[] MDRaisedButton: size_hint: None, None size: 3 * dp[48], dp[40] text: 'Detect gender' opposite_colors: True pos_hint: {'center_x': .5, 'center_y': .6} on_release: root.process_button_click[1] MDRaisedButton: size_hint: None, None size: 3 * dp[48], dp[48] text: 'Webcam gender detection' opposite_colors: True pos_hint: {'center_x': .5, 'center_y': .3} on_release: root.process_button_click[2]

Với UI như trên hình trên thì ta sẽ tạo một GridLayout bọc bên trong là các trường Text, Button. Để set sự kiện cho từng Button thì ta khai báo trong on_release : root.name_action với name_action tương ứng với funtion trong class MyGrid.

def process_button_click[self, index]: if index == 1: mythread = threading.Thread[target=self.gender_detection[]] mythread.start[] if index == 2: mythread = threading.Thread[target=self.gender_detection_video[]] mythread.start[]

Như bên trên thì ta sẽ phải import các class cần thiết.

from kivy.app import App from kivy.uix.label import Label from kivy.uix.popup import Popup from kivy.uix.widget import Widget from kivymd.theming import ThemeManager from kivy.properties import ObjectProperty from kivy.uix.modalview import ModalView from kivy.core.window import Window

Để có thể lấy được file image từ máy thì ta sử dụng MDFileManager:

def file_manager_open[self]: from kivymd.uix.filemanager import MDFileManager self.manager = ModalView[size_hint=[1, 1], auto_dismiss=False] self.file_manager = MDFileManager[ exit_manager=self.exit_manager, select_path=self.select_path, previous="", ] self.manager.add_widget[self.file_manager] self.file_manager.show[os.path.expanduser["~/Desktop"]] self.manager_open = True self.manager.open[]

Sau khi chọn xong file ảnh thì ta sẽ show lên [Toast] thông báo cho người sử dụng biết [mình sẽ show ra với nội dung là path của ảnh đó ].

def select_path[self, path]: self.exit_manager[] toast[path] self.img_path.text = path def toast[text]: from kivymd.toast.kivytoast import toast toast[text] def exit_manager[self, *args]: self.manager.dismiss[] self.manager_open = False

Tiếp theo là ta sẽ implement button của 2 button mà ta đã nói ở trên.

def gender_detection[self]: image_path = self.img_path.text # Path of the gender detection model model_path = "model.h5" model_weights_path = "weights.h5" im = cv2.imread[image_path] if im is None: print["Could not read input image"] popup = Popup[title='No image found', content=Label[text="Could not read input image.\nMake sure you selected an image."], size_hint=[None, None], size=[400, 200]] popup.open[] return # Load the trained model model = load_model[model_path] model.load_weights[model_weights_path] faces, confidences = cv.detect_face[im] # loop through detected faces and add bounding box for face in faces: [startX,startY] = face[0],face[1] [endX,endY] = face[2],face[3] # draw rectangle over face cv2.rectangle[im, [startX,startY], [endX,endY], [232, 145,15], 2] # Preprocessing for the detection cropped_face = im[startY:endY,startX:endX] cropped_face = cv2.resize[cropped_face, [150,150]] cropped_face = cropped_face.astype["float32"] / 255 cropped_face = img_to_array[cropped_face] cropped_face = np.expand_dims[cropped_face, axis=0] # Apply prediction to the cropped face conf = model.predict[cropped_face][0] if conf[0] > conf[1]: label = "Male" else: label = "Female" #print[conf] # Print label above the rectangle cv2.putText[im, label, [startX, startY-5], cv2.FONT_HERSHEY_SIMPLEX,1, [232, 145,15], 2] # Display output cv2.namedWindow["output", cv2.WINDOW_AUTOSIZE] cv2.imshow["output", im] cv2.waitKey[]

Như đã nói từ ban đầu là mình sẽ sử dụng lib cv để detec được face trong image, xong crop face ra. Sau đó load model rồi predict face mà ta đã crop ở trước, khi có kết quả sẽ show text lên hình ảnh đó. Và tương tự đối với Button Camera thì ta sẽ code xử lý tương tự như thế với đầu vào là video.

def gender_detection_video[self]: model_path = "model.h5" model_weights_path = "weights.h5" model = load_model[model_path] model.load_weights[model_weights_path] video_capture = cv2.VideoCapture[0] while True: # Capture frame-by-frame ret, frame = video_capture.read[] gray = cv2.cvtColor[frame, cv2.COLOR_BGR2GRAY] # TODO...

Cuối cùng là gọi phương thức run[].

class GenderDetectionApp[App]: title = "Gender detection" theme_cls = ThemeManager[] theme_cls.theme_style = "Dark" theme_cls.primary_palette = "BlueGray" Window.size = [780, 320] def build[self]: return MyGrid[] if __name__ == "__main__": GenderDetectionApp[].run[]

Và vài kết quả nhận được :

Còn video thì các bạn có thể thử.

Bên cạnh đó ta cũng có thể CRUD với database với Kivy. Các bạn có thể xem thêm tại đây.

Ngoài ra thì thằng này còn có thể code thành app Android các bạn có thể xem thêm [tất nhiên là ko bằng Android Studio hàng ngon, nhưng các bạn có thể thử ].Bên dưới mình cũng đưa một vài link hướng dẫn code thành App Android.

Tạm thời mình hướng dẫn đến đây, hẹn mọi người trong bài viết tiếp theo

Tài liệu tham khảo


Video liên quan

Chủ Đề