파이썬으로 지역 검색 및 지도에 나타내기 – 4. 검색 메인 창 구현(Final)

안녕하세요. 언제나 휴일의 언휴예요.

이제 “파이썬으로 지역 검색 및 지도에 나타내기 “프로젝트의 마지막 작업입니다.

이번에는 QT를 이용하여 메인 창을 구현할 거예요.

1. LSMainWindows.py 구현

PyQt5의 Widget 들과 WebEngineView, QUrl을 사용합니다.

그리고 앞에서 작성한 LocaleSearcher.py의 SearchLoacle 함수를 사용합니다.

(파이썬 개발 환경에 PyQt5, PyQtWebEngine 모듈 설치가 필요합니다.)

#LSMainWindow.py

from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtCore import QUrl
from LocaleSearcher import  *

QMainWindow에서 파생한 LSMainWindow 클래스를 정의할게요.

생성자에서는 기반 클래스 생성자 호출하고 화면을 구성합니다.

class LSMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

QGridLayout을 이용하여 배치하기로 할게요.

QGridLayout은 Widget에 배치해야 합니다.

        self.resize(1080,640)
        self.widget = QWidget() #QGridLayout개체를 배치할 Widget 개체 생성
        self.setCentralWidget(self.widget) #LSMainWindow의 CentralWidget 설정
        self.grid = QGridLayout(self.widget) #QGridLayout 개체 생성
실행 화면

첫 번째 컬럼은 질의를 입력은 QLineEdit, 그리고 QPushButton, QListWidget으로 구성합니다.

QGridLayout에 Widget을 배치할 때 row, column을 전달합니다.

        self.setWindowTitle('지역 검색 by Kakao API') #윈도우 타이틀
        self.query = QLineEdit()
        self.query.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.grid.addWidget(self.query,0,0)
        self.btn = QPushButton()
        self.btn.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
        self.grid.addWidget(self.btn, 1, 0)
        self.btn.setText("확인")
        self.lbox=QListWidget()
        self.grid.addWidget(self.lbox,2,0)#row, column, row_span, column_span

두 번째 컬럼은 QWebEngineView로 배치합니다.

row는 0, column은 1, row_span은 3칸 차지, column_span은 1칸 차지입니다.

        self.webEngineView = QWebEngineView()
        self.grid.addWidget(self.webEngineView, 0, 1, 3, 1)  # row, column, row_span, column_span

QWebEngineView 개체에 보여줄 사이트 주소는 http://localhost/kmap/kmap.html로 할게요.

kmap.html의 코드는 맨 아래에 작성하기로 할게요.

        self.webEngineView.load(QUrl("http://localhost/kmap/kmap.html"))

grid 개체의 row의 높이 비율은 1:1:16 column의 너비 비율은 1:4로 지정할게요.

        self.grid.setRowStretch(0 ,1)
        self.grid.setRowStretch(1, 1)
        self.grid.setRowStretch(2, 16)
        self.grid.setColumnStretch(0,1)
        self.grid.setColumnStretch(1,4)

버튼 클릭과 리스트 항목 선택의 리스너를 연결한 후 시각화할게요.

        self.btn.clicked.connect(self.Search)
        self.lbox.currentItemChanged.connect(self.LboxSelectChanged)
        self.show()

Search 메서드를 정의합시다.

리스트 박스의 항목을 지워줍니다.

검색 질의 내용으로 주소 검색을 수행한 후 결과를 리스트 박스 항목에 추가합니다.

    def Search(self):
        self.lbox.clear()
        text = self.query.text()
        self.locales =SearchLocale(text)
        for locale in self.locales:
            self.lbox.addItem(locale.pn)

LboxSelectChanged 메서드를 정의합시다.

선택 항목이 없다면 메서드를 종료합니다.

그렇지 않다면 선택 항목에 해당하는 지역의 위도(y), 경도(x)를 얻어와 지도의 Center를 이동시킵니다.

지도의 Center를 이동시키는 부분은 Move 메서드를 정의하기로 할게요.

    def LboxSelectChanged(self):
        row = self.lbox.currentRow()
        if row == -1:
            return
        x = self.locales[row].x
        y = self.locales[row].y
        self.Move(x,y)

Move 메서드를 정의합시다.

현재 webEngineView의 page를 참조합니다.

page 개체에 실행할 JavaScript를 문자열로 만듭니다.

JavaScript 함수는 setMyCenter로 정의하고 위도, 경도를 인자로 전달받게 정의하기로 할게요.

    def Move(self,x,y):
        page = self.webEngineView.page()
        script = str.format("setMyCenter({0},{1});",y,x)
        page = page.runJavaScript(script)

다음음 LSMainWindows.py의 전체 소스 코드입니다.

#LSMainWindow.py

from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtCore import QUrl
from LocaleSearcher import  *

class LSMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.resize(1080,640)
        self.widget = QWidget() #QGridLayout개체를 배치할 Widget 개체 생성
        self.setCentralWidget(self.widget) #LSMainWindow의 CentralWidget 설정
        self.grid = QGridLayout(self.widget) #QGridLayout 개체 생성

        self.setWindowTitle('지역 검색 by Kakao API') #윈도우 타이틀
        self.query = QLineEdit()
        self.query.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.grid.addWidget(self.query,0,0)
        self.btn = QPushButton()
        self.btn.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
        self.grid.addWidget(self.btn, 1, 0)
        self.btn.setText("확인")

        self.lbox=QListWidget()
        self.grid.addWidget(self.lbox,2,0)#row, column, row_span, column_span

        self.webEngineView = QWebEngineView()
        self.grid.addWidget(self.webEngineView, 0, 1, 3, 1)  # row, column, row_span, column_span
        self.webEngineView.load(QUrl("http://localhost/kmap/kmap.html"))
        self.grid.setRowStretch(0 ,1)
        self.grid.setRowStretch(1, 1)
        self.grid.setRowStretch(2, 16)
        self.grid.setColumnStretch(0,1)
        self.grid.setColumnStretch(1,4)

        self.btn.clicked.connect(self.Search)
        self.lbox.currentItemChanged.connect(self.LboxSelectChanged)
        self.show()
    def Search(self):
        self.lbox.clear()
        text = self.query.text()
        self.locales =SearchLocale(text)
        for locale in self.locales:
            self.lbox.addItem(locale.pn)
    def LboxSelectChanged(self):
        row = self.lbox.currentRow()
        if row == -1:
            return
        x = self.locales[row].x
        y = self.locales[row].y
        self.Move(x,y)
    def Move(self,x,y):
        page = self.webEngineView.page()
        script = str.format("setMyCenter({0},{1});",y,x)
        page = page.runJavaScript(script)

다음은 kmap.html 소스 코드입니다.

이 파일은 가상 디렉토리로 설정한 폴더에 옮기세요.

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<title>Kakao 지도 시작하기</title>
</head>
<body>
	<div id="map" style="width:800px;height:600px;"></div>
	<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=발급받은 내 애플리케이션의 JavaScript 키"></script>
	<script>
		var container = document.getElementById('map');
		var options = {
			center: new kakao.maps.LatLng(33.450701, 126.570667),
			level: 3
		};


		var map = new kakao.maps.Map(container, options);
		var marker = new kakao.maps.Marker({ 
			// 지도 중심좌표에 마커를 생성합니다 
			position: map.getCenter() 
		}); 
		// 지도에 마커를 표시합니다
		marker.setMap(map);
		function setMyCenter(lat,lng) {            
			// 이동할 위도 경도 위치를 생성합니다 
			var moveLatLon = new kakao.maps.LatLng(lat,lng);
    
			// 지도 중심을 이동 시킵니다
			map.setCenter(moveLatLon);
			marker.setPosition(moveLatLon);
		}
	</script>
</body>
</html>

2. main.py 구현

이제 진입점으로 사용할 main.py를 구현합시다.

단순히 QApplication  개체와 LSMainWindows 개체를 생성하고 종료를 대기하는 코드가 끝입니다.

#main.py
import sys
from PyQt5.QtWidgets import QApplication
from LSMainWindow import  LSMainWindow
def main():
    app = QApplication(sys.argv)
    ex = LSMainWindow()
    sys.exit(app.exec_())
if __name__ == '__main__':
    main()

이상으로 “파이썬으로 지역 검색 및 지도에 나타내기” 프로젝트를 마칠게요.