본문 바로가기
Python

Python PyQt5 프로젝트 - Excel / CSV 파일 데이터 그래프 그리기 (2)

by 아짱이아빠 2022. 10. 2. 23:49
반응형

2부에서는 본격적으로 Excel 파일과 CSV 파일 데이터를 그래프로 그리는 파이썬 코드에 대해 정리해보겠다.

 

프로그램 비전공자로서 프로그램에 빨리 친숙해지려면 무언가를 만들어보는 것이 가장 효과적이라 생각한다.

그래서 이 프로젝트를 통해 파이썬에서는 아주 기초적인 내용이지만 파일을 열고 내용을 그래프로 그리는 프로그램을 GUI로 구성하여 만들고 마지막에는 실행파일까지 만들어봄으로써 전체적인 구성을 이해할 수 있었다.

 

그러면 본격적으로 파이썬 코드에 대해 설명하겠다.

이 프로젝트에서는 제목에도 있듯이 Excel과 CSV 형식의 파일을 불러오고 첫 번째 column의 내용을 index로 변경하고 그다음의 column의 내용을 그래프로 도식화한다.

그리고자 하는 column은 중복적으로 선택하여 그릴 수 있으며 다시 지울 수도 있다.

그래프는 선형 그래프와 막대형 그래프를 선택할 수 있고 그래프의 스타일도 변경할 수 있다.

또한, 잘못된 형식의 파일을 불러오거나 선택했을 때에 오류창을 띄우는 기능을 포함하고 있다.

 

프로그램의 구성을 크게 보면 다음의 그림과 같다.

Excel/CSV 파일 데이터 그리기 프로그램 구성
(Excel/CSV 파일 데이터 그리기 프로그램 구성)

 

첫 번째 구성은 프로그램에 필요한 라이브러리를 불러오는 부분이고 두 번째는 각 종 버튼과 창들을 정의하고 구성하며 마우스 클릭에 의해 어떤 기능을 실행하는지를 정의하는 class로 구성된 부분이다.

마지막은 프로그램을 종료하기 위한 정의가 포함된 부분이다.

 

[라이브러리 Import]

다음의 라이브러리들이 이 프로그램에서 사용된다.

import sys
from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QHBoxLayout, QWidget, QDesktopWidget, QToolTip
from PyQt5.QtWidgets import QFileDialog, QListWidget, QListWidgetItem, QRadioButton, QLabel, QComboBox, QMessageBox
from PyQt5.QtGui import QFont, QIcon
import matplotlib.pyplot as plt
import pandas as pd

 

만약 없는 라이브러리가 있다면 pip install을 통해 설치해야 한다.

앞에서 얘기했듯이 파일을 불러오고 읽어드리며 파일 내의 데이터를 정렬하고 그래프로 그리는 각 종 기능들은 위의 라이브러리들이 있어야 가능하다.

따라서 라이브러리를 보면 어떤 버튼이나 창, 어떤 기능을 사용하는지 어느 정도 파악이 가능하다.

 

[GUI 정의]

GUI를 정의하는 코드를 보기 전에 먼저 어떤 GUI를 갖는지 알아보겠다.

 

Excel/CSV 파일 데이터 그리기 GUI 구성
(Excel/CSV 파일 데이터 그리기 GUI 구성)

 

이 프로젝트의 GUI는 위의 그림과 같으며 QLabel, 두 종류의 버튼, QComboBox, 그리고 QListWidget을 사용한다.

동작 순서는 다음의 기능 정의에서 다시 얘기하겠지만 간단히 설명하면 ‘데이터 선택’에서 Excel 또는 CSV 파일 중 하나를 선택하면 ‘<Column List>'창에 파일 내의 column 명을 보여준다. 

그래프로 그리고 싶은 column을 마우스로 더블클릭하면 해당 column 명이 ‘<Graph List>’에 보이면서 그래프 결과 창이 보인다.

선택된 column을 지우고 싶으면 ‘<Graph List>’에 있는 해당 column을 클릭하고 ‘Graph List Item Erase’를 클릭하면 해당 내용이 삭제된 그래프 결과창이 다시 나타난다.

 

이제 코드를 알아보겠다.

class MyApp(QWidget) :
  def __init__(self):
    super().__init__()
    self.initUI()

 

앞에서 프로그램 구성처럼 GUI와 기능을 정의하는 부분은 class로 정의된다.

사실 위의 코드의 각 라인에 대한 정확한 의미는 알지 못한다.

그냥 GUI 프로그램을 시작하기 위한 프로그램 시작부로만 이해하고 있다.

 

다음은 class 내에서 각 버튼과 창 등을 생성하는 부분이다.

모두 ‘initUI’라는 하나의 함수로 정의되어 있으나 이해를 돕기 위해서 여러 부분으로 나누어 설명하겠다.

 def initUI(self):
    self.setWindowTitle("----'s Graph Ver 1.0")
    self.setWindowIcon(QIcon('graph.png'))
    self.setGeometry(500,500,500,700)
 
    QToolTip.setFont(QFont('SansSeif', 10))

 

위의 코드는 주 창 위에 보일 이름을 정의하고 이름 옆에 아이콘을 띄울 수 있게 하며 창의 크기를 정한다.

보여주고자 하는 아이콘 ‘graph.png’ 파일은 실행하는 파이썬 프로그램이 있는 동일 폴더에 위치해 있어야 한다.

만약 다른 폴더에 해당 아이콘 파일이 있다면 파일이 있는 경로까지 같이 코드에 넣어주어야 한다.

‘self.setGeometry’는 창의 위치와 크기를 정의하는데, 앞의 두 숫자는 x, y 위치이며 그다음의 두 숫자는 순서대로 창의 너비와 높이가 된다. 

실행결과를 보면 다음과 같다.

주 창에 아이콘 및 이름 넣기
(주 창에 아이콘 및 이름 넣기)

 

위 코드의 마지막은 프로그램의 설명을 넣기 위해 ‘QToolTip’ 라이브러리를 이용하여 설명글의 폰트와 크기를 정의한 것이다.

 

다음은 QComboBox를 이용한 GUI를 정의하는 부분이다.

#불러올 파일 형식(excel or csv) 선택 창
    self.file_open_box = QComboBox(self)
    self.file_open_box.addItem('None')
    self.file_open_box.addItem('Excel File')
    self.file_open_box.addItem('CSV File')

    self.file_open_box.setToolTip('불러올 파일 형식을 선택합니다.')
    
    self.file_open_box.activated[str].connect(self.fileopenActivated)

#그래프의 스타일 선택 창
    self.graph_theme_box = QComboBox(self)
    self.graph_theme_box.addItem('default')
    self.graph_theme_box.addItem('classic')
    self.graph_theme_box.addItem('dark_background')
    self.graph_theme_box.addItem('Solarize_Light2')
    self.graph_theme_box.addItem('ggplot')
    self.graph_theme_box.addItem('seaborn-whitegrid')

    self.graph_theme_box.setToolTip(('그래프 스타일을 선택합니다.'))
    
    self.graph_theme_box.activated[str].connect(self.onActivated)

 

앞에서 봤지만 이 프로그램에서는 총 두 개의 QComboBox를 사용한다.

첫 번째는 불러올 파일 형식을 결정하는 것이고 두 번째는 그래프의 스타일을 결정하는 기능에 사용된다.

QComboBox는 여러 개의 아이템 중에서 하나를 선택하는 기능을 구현할 때 유용하다.

QComboBox를 정의하는 구성은 먼저 QComboBox를 새로운 이름으로 정의하고 여기에 QComboBox를 구성할 내부 아이템들을 ‘. addItem’을 통해서 정의해준다. 

그리고 특정 아이템을 선택했을 때에 어떤 기능으로 연결할지를 정의한다.

또한, 여기서는 이 QComboBox에 기능 설명을 넣기 위해 ‘. setTooTip’을 통해 설명 내용을 정의하여 마우스를 해당 Box에 올리면 설명이 나오도록 하였다.

설명문의 글씨체와 크기는 앞에서 정의하였다.

 

아이템이 선택되었을 때 수행될 기능은 ‘. activated [str]. connect’를 통해 각각의 정의된 기능으로 연결되며 파일 형식을 불러오는 QComboBox는 ‘fileopenActivated’란 이름의 함수에 연결되고 그래프 스타일을 결정하는 QComboBox는 ‘onActivated’란 이름의 함수에 연결된다.

각 함수의 기능 정의는 다음에 설명하겠다.

 

두 번째 QComboBox는 matplotlib 라이브러리에서 제공하는 여러 그래프 스타일을 정의하였다.

 matplotlib 라이브러리는 훨씬 더 많은 그래프 스타일이 있지만 여기서는 몇 가지만 적용하였다.

참고로 matplotlib에서 제공하는 전체 그래프 스타일을 확인하려면 ‘plt.style.available’ 명령을 통해 확인할 수 있다.

 

이렇게 정의해서 보이는 결과는 아래와 같다.

QComboBox 및 툴팁 기능
(QComboBox 및 툴팁 기능)

 

다음은 아이템을 지우는 버튼과 그래프 종류를 선택하는 버튼을 정의하는 코드이다.

#그래프 그리기 / 지우기 버튼 정의    
    self.graph_erase_btn = QPushButton('Graph List\n     Item Erase     ')
    self.graph_erase_btn.adjustSize()
    
    self.graph_erase_btn.setToolTip('Graph List에서 선택한 항목을 지우고 그래프를 다시 그립니다.')
    
    self.graph_erase_btn.clicked.connect(self.grapherase)
    self.graph_erase_btn.clicked.connect(self.graphplot)

#그래프 종류 결정 버튼 정의
    self.line_graph_btn = QRadioButton('Line Plot')
    self.line_graph_btn.setChecked(True)           
    self.line_graph_btn.setToolTip('선형 그래프를 그립니다.')
    self.line_graph_btn.clicked.connect(self.graph_selec)

    self.hist_graph_btn = QRadioButton('Histogram')
    self.hist_graph_btn.setToolTip('막대형 그래프를 그립니다.')
    self.hist_graph_btn.clicked.connect(self.graph_selec)

 

선택된 아이템을 지우는 버튼은 QPushButton으로 정의한다. 

버튼의 이름을 정의하고 마우스를 올려놓았을 때 설명이 나오도록 설정하며 버튼이 클릭 시 수행될 기능은 ‘grapherase’와 ‘graphplot’ 함수에 연결한다.

기능 연결 코드에서 알 수 있듯이 이 버튼을 클릭하면 선택된 아이템 즉, column을 지우고 그래프를 그리는 명령 없이 그래프를 다시 그린다.

 

그래프 종류 선택 버튼은 QRadioButton 두 개를 이용하며 하나는 선형 그래프, 다른 하나는 막대형 그래프를 선택할 수 있도록 한다.

이 버튼 정의 구성은 위의 다른 버튼과 유사하다.

그리고 ‘. setChecked(True)’ 기능을 통해서 선형 그래프를 디폴트 그래프로 결정해 놓는다.

각 버튼은 클릭 시 동일한 함수인 ‘graph_select’로 연결된다.

 

다음은 파일의 column을 읽어와서 보여줄 창과 그래프를 그리고자 선택된 column을 보여주는 창, 그리고 각 창의 이름을 정의한다.

#파일의 컬럼을 넣을 List 생성
    self.listwidget_01 = QListWidget(self)
    self.listwidget_02 = QListWidget(self)

    self.listwidget_01.setToolTip('불러온 파일의 컬럼명을 보여줍니다.\n원하는 컬럼을 더블클릭하면 그래프로 보여줍니다.')
    self.listwidget_02.setToolTip('선택한 컬럼명을 보여줍니다.\n항목을 선택한 후 Erase 버튼을 사용하여 삭제할 수 있습니다.')

#listwidget_01에서 선택한 항목을 listwidget_02에 보여주면서 그래프 생성
    self.listwidget_01.itemDoubleClicked.connect(self.doubleclicked_listwidget)
    self.listwidget_01.itemDoubleClicked.connect(self.graphplot)

#각 List의 이름 생성
    self.label1 = QLabel('< Column List >')
    self.label2 = QLabel('< Graph List >')
    self.label3 = QLabel('')

 

Column명을 보여줄 두 창은 모두 QListWidget을 이용한다.

두 QListWidget 중 불러온 파일 안에 있는 column 명들을 보여줄 창은 ‘self.listwidget_01’이란 이름으로 정의하며 column 중 하나를 마우스 더블 클릭하면 ‘doubleclicked_listwidget’ 함수와 ‘graphplot’ 함수에 연결된다. 

 

반응형

 

각 QListWidget 창에 이름을 보여주기 위해서 QLabel을 사용한다.

마지막에 있는 빈 QLabel은 여백을 주기 위해 정의하였으며 아래에 레이아웃 구성에서 어떻게 사용되는지 설명하도록 하겠다.

 

GUI 정의의 마지막은 앞에서 정의한 버튼과 창, 라벨 등을 화면에 배치하는 내용이다.

이 부분은 코드만을 통해서 각 종 버튼과 창을 원하는 위치에 배치해야 하므로 좀 헷갈리는 부분이다.

이 부분을 직관적이고 쉽게 구현할 수 있게 해주는 것이 1부에서 알아본 QT Designer이다.

 

 

Python PyQt5 프로젝트 - Excel / CSV 파일 데이터 그래프 그리기 (1)

파이썬 PyQt5를 이용하여 Excel 파일과 CSV 파일을 선택하여 불러오고 파일 안의 데이터를 다양한 그래프로 그려주는 프로그램을 만들어 본다. 불러온 파일은 자동으로 컬럼의 이름을 확인하여 표

superhky.tistory.com

#위치 결정
    hbox_1 = QHBoxLayout()
    hbox_1.addWidget(self.file_open_box)
    hbox_1.addWidget(self.graph_theme_box)
    hbox_1.addWidget(self.graph_erase_btn)

    hbox_2 = QHBoxLayout()
    hbox_2.addWidget(self.line_graph_btn)
    hbox_2.addStretch(1)
    hbox_2.addWidget(self.hist_graph_btn)

    vbox_1 = QVBoxLayout()
    vbox_1.addLayout(hbox_1)
    vbox_1.addLayout(hbox_2)

    vbox_2 = QVBoxLayout()
    vbox_2.addWidget(self.label3)
    vbox_2.addWidget(self.label1)
    vbox_2.addWidget(self.listwidget_01)
    vbox_2.addWidget(self.label2)
    vbox_2.addWidget(self.listwidget_02)

    vbox_3 = QVBoxLayout()
    vbox_3.addLayout(vbox_1)
    vbox_3.addLayout(vbox_2)

    hbox_3 = QHBoxLayout()
    hbox_3.addStretch(1)
    hbox_3.addLayout(vbox_3)
    hbox_3.addStretch(1)

    self.setLayout(hbox_3)

    self.center()       
    self.show()

 

레이아웃은 구성 요소를 수평으로 정렬하는 QHBoxLayout과 수직으로 정렬하는 QVBoxLayout을 이용하여 작은 영역씩 묶어서 구성하며 작은 영역의 레이아웃은 다시 묶어서 좀 더 큰 레이아웃이 된다. 

이 코드 부분은 글로 설명하기보다는 아래의 그림을 보는 것이 더 쉽게 이해될 것이다.

레이아웃 구성
(레이아웃 구성)

앞에서 설정했던 빈 QLabel은 ‘vbox_2’로 묶고 ‘vbox_3’를 정의할 때 ‘vbox_1’과 ‘vobx_2’ 간에 여백을 주는 역할을 수행한다.

모든 구성은 최종적으로 hbox_3란 이름의 수평 레이아웃이 되고 ‘. setLayout’으로 창의 메인 레이아웃으로 설정된다.

 

‘self.center()’는 실행 결과 창을 화면의 중심에 항상 나타나도록 하는 역할을 하고 마지막에 ‘self.show()’를 통해 실행된다.  

 

 

다음 3부에서는 각 버튼과 창에 기능을 설정하는 부분에 대해 알아보고 샘플 데이터를 통해 이 프로그램의 결과를 확인해 보겠다.

 

반응형

댓글