python pyqt5 이미지 클릭

개요

pyqt5에서 이미지는 QPixmap의 라이브러리를 사용한다. 하지만 해당 라이브러리로 이미지를 불러온다면 클릭시 연결 함수를 제공하지 않는다.

클릭을 가능하게 하려면 몇가지 수정이 필요하다.

이미지 로드

아래와 같이 로드가 가능합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from PyQt5.QtGui import *
import os

# 현재 폴더에 현재 날짜의 폴더 이름 만들기
folderName = os.getcwd() + '\\' + str(time.localtime().tm_year) + '_' + str(time.localtime().tm_mon) + '_' + str(
time.localtime().tm_mday)

# 폴더 생성
try:
if not (os.path.isdir(folder_name)):
os.makedirs(os.path.join(folder_name))
except OSError as e:
print(e)

# 폴더에 있는 파일 리스트를 불러옴
file_list = os.listdir(folder_name)

if len(file_list) > 0:
png_list = []
# 그림파일 확장자 명만 찾아서 리스트에 추가
for file_name in file_list:
if (file_name.find('.png') == len(file_name)-4) or (file_name.find('.jpg') == len(file_name)-4):
png_list.append(file_name)

# 그림파일을 하나씩 로드함
if len(png_list) > 0:
for png_file in png_list:
pixmap = QPixmap(folder_name+'\\'+png_file)

png_path = folder_name+'\\'+png_file
PNG_LIST.append(png_path)

위 코드는 현재 날짜의 폴더를 생성하고 폴더안에 있는 그림파일을 하나씩 로드하는 코드입니다.

이미지 clickable

pixmap을 만들었다면 해당 변수를 clickable로 만들어야 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
lbl_img = QLabel()
clickable(lbl_img).connect(self.pictureListClicked)

lbl_img.setAlignment(Qt.AlignCenter)
lbl_img.setPixmap(pixmap)

def clickable(widget):
global FILE_LIST
class Filter(QObject):

clicked = pyqtSignal()

def eventFilter(self, obj, event):
if obj == widget:
if event.type() == QEvent.MouseButtonRelease:
if obj.rect().contains(event.pos()):
self.clicked.emit()
# The developer can opt for .emit(obj) to get the object within the slot.
return True

return False

filter = Filter(widget)
widget.installEventFilter(filter)
FILE_LIST.append(filter)
return filter.clicked

위 코드는 MouseButtonRelease 이벤트 발생시 signal을 보냄으로서 연결된 함수를 호출하는 코드입니다.

위 코드에서 글로벌 변수인 FILE_LIST에 filter를 추가한 것은 추후 연결된 함수에서 누가 보냈는지 구분하기 위함입니다.

self.clicked.emit()에서 obj를 보내 구분도 가능할꺼 같지만 테스트 해보지는 않았습니다.

이미지 클릭시 함수에서 이미지 구분

위 코드에서 여러 이미지의 파일을 반복문으로 부르고 한개의 함수에 이를 연결하고 있습니다.

이럴때 문제는 모든 이미지 클릭시 같은 동작을 실행한다는 것입니다.

이를 방지하기 위해서 위에서 저장했던 FILE_LIST를 이용했습니다.

1
2
3
4
5
6
7
8
9
10
11
def pictureListClicked(self):
global FILE_LIST
global PNG_LIST
png_path = ''
for i, object_name in enumerate(FILE_LIST):
if object_name == self.sender():
png_path = PNG_LIST[i]

if png_path != '':
self.grid.addWidget(self.pictureShowGroup(png_path), 0, 2, 9, 8)
self.update()

원리는 sender를 이용해 클릭된 이미지의 순서를 알아내고 따로 저장된 PNG_LIST로 해당 파일을 불러와 그 이미지를 가지고 다른 위젯에 표시하는 함수입니다.

이미지 리스트(왼쪽)와 리스트 클릭시 이미지 표시(오른쪽)

공유하기