DEEP.I - Lab

오프라인 공간의 지능화를 꿈꾸는 딥아이 연구실입니다.

Python/PyQt

[Python] PyQt 에서 로딩(애니메이션) 화면 구현하기

Jongwon Kim 2020. 11. 23. 14:25
반응형

GUI 기반 프로그램에서는 직관적이고 편리한 UI/UX 구성도 중요하지만, 프로그램에서 특정 액션이 발생할 때 사용자에게 지금 어떤 '상황'인지 알려주는 상호작용 역시 매우 중요합니다. 예를 들어, 버튼 클릭은 된건지, 접속은 된건지 현재 액션에 대한 반응으로 사용자가 느낄수 있어야 합니다. 이번 포스팅에서는 PyQt에서 간단하게 이벤트가 입력되었을때 로딩중이다라는것을 보여 줄 수 있는 창을 한번 구현해보겠습니다.

 

 

그림 1. 로딩 이미지

 

 

 

1. 로딩 이미지 파일 (GIF, SVG, APNG) 만들기

 

동적 로딩화면 구현을 위해서는 GIF, SVG, APNG 등과 같이 애니메이션 효과가 가능한 파일이 필요합니다.  저는 아래 사이트에서 무료로 제작 가능한 로딩 이미지를 받아서 사용했습니다. 이번 포스팅에서는 GIF를 활용해보겠습니다.

 

loading.io/

 

loading.io - Your SVG + GIF + PNG Ajax Loading Icons and Animation Generator

Build Your Ajax Loading Icons, Animated Text and More with SVG / CSS / GIF / PNG !

loading.io

2. MainWindow 클래스 생성

 

import sys

from PyQt5 import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import*
from PyQt5 import uic

FROM_CLASS_MainWindow = uic.loadUiType("mainwindow.ui")[0]

class MainWindow(QMainWindow,FROM_CLASS_MainWindow):    

    def __init__(self):
        super().__init__()
        
        # UI 파일 로드
        self.setupUi(self) 
        self.show()
        
        # 버튼 클릭 매서드
        self.button.clicked.connect(self.loading)
        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ShowApp = MainWindow()
    sys.exit(app.exec_())   

 

첨부된 UI파일을 이용하시거나 진행중인 프로젝트에서 메인 클래스를 불러와줍니다. 저는 QT Designer를 통해 UI를 만든다음, uic.loadUiType 함수로 불러오는것을 선호하고 있습니다.

 

 

3. Loading 클래스 생성

 

FROM_CLASS_Loading = uic.loadUiType("load.ui")[0]

class loading(QWidget,FROM_CLASS_Loading):
    
    def __init__(self,parent):
        super(loading,self).__init__(parent)    
        self.setupUi(self) 
        self.center()
        self.show()
        
        # 동적 이미지 추가
        self.movie = QMovie('loading.gif', QByteArray(), self)
        self.movie.setCacheMode(QMovie.CacheAll)
        # QLabel에 동적 이미지 삽입
        self.label.setMovie(self.movie)
        self.movie.start()
        
        # 윈도우 해더 숨기기
        self.setWindowFlags(Qt.FramelessWindowHint)   
    
    # 위젯 정중앙 위치
    def center(self):
        size=self.size()
        ph = self.parent().geometry().height()
        pw = self.parent().geometry().width()
        self.move(int(pw/2 - size.width()/2), int(ph/2 - size.height()/2))

 

동일한 방식으로 로딩화면을 구현할 위젯 클래스를 생성해줍니다. center 함수는 위젯이 생성되엇을때 현재 실행중인 프로그램 윈도우의 정중앙에 배열해줍니다. 이후 버튼 클릭 매서트를 메인 클래스에 추가하여 Loading 클래스를 생성할 수 있게 합니다.

 

 

3-1. Loading gif 실행

 

        # 동적 이미지 추가
        self.movie = QMovie('loading.gif', QByteArray(), self)
        self.movie.setCacheMode(QMovie.CacheAll)
        # QLabel에 동적 이미지 삽입
        self.label.setMovie(self.movie)
        self.movie.start()

 

QMovie를 통해 gif 이미지 파일을 동적으로 재생되도록 해줍니다. SVG 파일의 경우, 별도의 SVG 위젯과 직접 연결하여 사용하면 됩니다. 그리고 아직까지 QT에서 APNG 파일은 정식적으로 지원하지는 않는것같습니다. 이미지는 출력되지만 애니매이션 효과는 발생하지않네요.

 

 

 

 

4. 버튼 클릭 이벤트 함수 생성 (MainWindow)

 

        # 버튼 클릭 매서드
        self.button.clicked.connect(self.loading)
        
    def loading(self):
        # 로딩중일때 다시 클릭하는 경우
        try: 
            self.loading
            self.loading.deleteLater()
            
        # 처음 클릭하는 경우    
        except:
            self.loading = loading(self)

 

clicked.connect()를 통해 loading 함수와 연결해줍니다. loading 함수에서는 클래스를 생성해주는 역할만 수행됩니다. 이미 로딩 화면이 실행 중일 경우에는 이를 삭제하여 로딩 화면을 삭제하는 1버튼 2매서트 방식으로 구현하였습니다. deleteLater()은 실행중인 클래스를 현재 함수 종료 이후 삭제해주는 함수입니다.

 

 

5. 최종 완성 코드

 

# -*- coding: utf-8 -*-
"""
Created on Sun Nov  8 13:05:23 2020
@author: DEEP.I Inc.
"""
import sys

from PyQt5 import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import*
from PyQt5 import uic

FROM_CLASS_MainWindow = uic.loadUiType("mainwindow.ui")[0]
FROM_CLASS_Loading = uic.loadUiType("load.ui")[0]

class MainWindow(QMainWindow,FROM_CLASS_MainWindow):    

    def __init__(self):
        super().__init__() 
        self.setupUi(self) 
        self.show()
        
        # 버튼 클릭 매서드
        self.button.clicked.connect(self.loading)
        
    def loading(self):
        # 로딩중일때 다시 클릭하는 경우
        try: 
            self.loading
            self.loading.deleteLater()
            
        # 처음 클릭하는 경우    
        except:
            self.loading = loading(self)
        

#%% Loading Img
class loading(QWidget,FROM_CLASS_Loading):
    
    def __init__(self,parent):
        super(loading,self).__init__(parent)    
        self.setupUi(self) 
        self.center()
        self.show()
        
        # 동적 이미지 추가
        self.movie = QMovie('loading.gif', QByteArray(), self)
        self.movie.setCacheMode(QMovie.CacheAll)
        # QLabel에 동적 이미지 삽입
        self.label.setMovie(self.movie)
        self.movie.start()
        # 윈도우 해더 숨기기
        self.setWindowFlags(Qt.FramelessWindowHint)
    
    # 위젯 정중앙 위치
    def center(self):
        size=self.size()
        ph = self.parent().geometry().height()
        pw = self.parent().geometry().width()
        self.move(int(pw/2 - size.width()/2), int(ph/2 - size.height()/2))

        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ShowApp = MainWindow()
    sys.exit(app.exec_())   


    

 

 

그림 2. 구현 화면

 

 

 

Loading.zip
0.06MB

 

 

 

 

# Jetson 시리즈 응용 임베디드 머신러닝 시스템 제작

# 머신러닝 프로젝트 제작, 상담 및 컨설팅  / 머신러닝 접목 졸업작품 컨설팅

# 데이터 가공, 수집, 라벨링 작업 / C, 파이썬 프로그램 제작

# email : deepi.contact.us@gmail.com

# site : www.deep-i.net

 

 

 

 

 

반응형