ก้าวไปอีกหนึ่งก้าวกับ XSection Plot

สวมวิญญานใหม่ด้วย PySide2

หลังจากผมคอมไพล์ XSection Plot ใหม่ด้วยสภาวะแวดล้อมพัฒนาของ Qt5 platform ด้วย PySide2 ผมเปลี่ยนลิขสิทธิ์ของโปรแกรมเดิมที่กำกวมออกมาฟรีสมบูรณ์แบบเหมือนกันกับ Surveyor Pocket Tools สามารถนำไปทำซ้ำแจกจ่ายได้ตามอัธยาศัย แต่ห้ามดัดแปลง ห้ามนำไปจำหน่ายหรือให้เช่า

XSection Plot
Copyright (C) Prajuab Riabroy. All Rights Reserved.

XSection Plot is free for use in any environment, including but not necessarily limited to: personal, academic, commercial, government, business, non-profit, and for-profit. "Free" in the preceding sentence means that there is no cost or charge associated with the installation and use of XSection Plot. 
Permission is hereby granted, free of charge, to any person obtaining a copy of this software (the "Software"), to use the Software without restriction, including the rights to use, copy, publish, and distribute the Software, and to permit persons to whom the Software is furnished to do so.

You may not modify, adapt, rent, lease, loan, sell, or create derivative works based upon the Software or any part thereof. 

The above copyright notice and this permission notice shall be included in all copies of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

แก้ไข bugs

นอกจากย้ายโค้ดมาใช้ PySide2 แล้ว ผมเลยถือโอกาสแก้บั๊กเล็กน้อยไปหลายอย่าง เช่น

  • เวลาคลิกขวาเพื่อเรียกเมนูในช่องป้อนข้อมูล โปรแกรมจะ terminate ทันที
  • ใน Section Layout ตรง Horizontal Grid เมื่อปรับ Distance from CL to left ไปแล้ว โปรแกรมไม่จำค่าใหม่
  • อื่นๆอีกเล็กน้อยประมาณสิบกว่าอย่าง

คอมไพล์และสร้างไฟล์ execute binary ด้วย PyInstaller

ตอนนี้โปรแกรมสนับสนุนทั้ง 32 บิตและ 64 บิต ผมใช้ PyCharm เป็นทูลส์ในการพัฒนา และเลือกได้ว่าจะใช้ 32 บิตหรือ 64 บิต เมื่อโปรแกรม stable แล้ว ก็จะสร้าง execute binary file ด้วย PyInstaller ตามสภาวะแวดล้อม ต้องทำสองครั้ง ครั้งแรก 32 บิตและครั้งที่สอง 64 บิต โดยแต่ละครั้งจะได้ไฟล์ exe, pyd, dll รวมถึงไลบรารีของไพทอนที่เราเรียกใช้ และที่สำคัญคือไลบรารีของ PySide2

ทำไฟล์ Setup ด้วย Inno Setup

ไฟล์ที่ได้จาก PyInstaller ทั้งหมด ผมจะนำมาสร้างไฟล์ Setup ด้วย Inno Setup เพื่อนเก่าที่ใช้กันมานมนาน มีดีเพียงพอที่จะสร้างไฟล์ Setup ได้ง่ายๆ มี options ให้เลือกพอสมควร สุดท้ายจะได้ไฟล์ Setup ที่เป็น Execute file ไฟล์เดียวพร้อมจะนำไปอัพโหลดให้ผู้ใช้นำไปใช้งานได้

ทดสอบโปรแกรมด้วยแบบรูปตัดตามยาว

ผมจะลองทดสอบโปรแกรมจากข้อมูล ความจริง XSection Plot คือโปรแกรมสร้างหรือช่วยเขียนรูปตัดตามขวาง แต่ยังพอเอามาประยุกต์ใช้กับ Long Profile ได้ แต่ไฟล์ข้อมูลส่วนใหญ่จะมีข้อมูลเพียงหนึ่ง Section เท่านั้นจะเริ่มจากไฟล์ข้อมูลของ Existing Ground Section ก่อนครับ ข้อมูลดังในกรอบข้างล่าง สามารถ copy ไป paste ในโปรแกรม text file editor เช่น Notepad ได้จากนั้น save ตั้ง extension เป็น gxml (ตัวอย่างผมตั้งชื่อว่า lake-road.gxml)

<root version="1.0">
  <!--Generated by XSection Plot-->
  <!--This data file is Existing ground section-->
  <Header>
    <AppName>XSection Plot</AppName>
    <Developer>Prajuab Riabroy</Developer>
    <Version>4.1.512</Version>
    <SectionType>Ground</SectionType>
    <DateCreated>2017-11-12 19:24:28.634707</DateCreated>
  </Header>
  <ProjectInfo>
    <ProjectName>Cantonment Lake Road</ProjectName>
    <ClientName></ClientName>
    <ContractorName></ContractorName>
    <DrawingTitle></DrawingTitle>
    <DrawnName></DrawnName>
    <ApprovedName></ApprovedName>
    <ClientApprovedName></ClientApprovedName>
    <CheckedName></CheckedName>
    <SurveyorName></SurveyorName>
    <SurveyedDate></SurveyedDate>
    <DrawingNo></DrawingNo>
    <SheetNo></SheetNo>
    <DrawingDate></DrawingDate>
    <Revision></Revision>
    <UseLocaleLanguage>False</UseLocaleLanguage>
    <MapTexts>
      <MapText Label="Client" Locale="เจ้าของโครงการ"/>
      <MapText Label="Contractor" Locale="ผู้รับจ้าง"/>
      <MapText Label="Drawn" Locale="เขียน"/>
      <MapText Label="Design" Locale="ออกแบบ"/>
      <MapText Label="Surveyor" Locale="ผู้สำรวจ"/>
      <MapText Label="Surveyed Date" Locale="วันที่สำรวจ"/>
      <MapText Label="Checked" Locale="ตรวจสอบ"/>
      <MapText Label="Approved" Locale="อนุมัติ"/>
      <MapText Label="Client Approved" Locale="ผู้คุมงานอนุมัติ"/>
      <MapText Label="Drawing No." Locale="แบบเลขที่"/>
      <MapText Label="Plotted Date" Locale="แบบวันที่"/>
      <MapText Label="Project" Locale="โครงการ"/>
      <MapText Label="Drawing Title" Locale="แผนที่แสดง"/>
      <MapText Label="Sheet No." Locale="แบบเลขที่"/>
      <MapText Label="Scale" Locale="มาตราส่วน"/>
      <MapText Label="Vertical" Locale="ทางดิ่ง"/>
      <MapText Label="Horizontal" Locale="ทางราบ"/>
      <MapText Label="Vertical Scale" Locale="มาตราส่วนทางดิ่ง"/>
      <MapText Label="Horizontal Scale" Locale="มาตราส่วนทางราบ"/>
      <MapText Label="Legend" Locale="สัญลักษณ์"/>
      <MapText Label="Note" Locale="หมายเหตุ"/>
      <MapText Label="Geodetic Information" Locale="ข้อมูลระบบพิกัด"/>
      <MapText Label="No." Locale="ครั้งที่"/>
      <MapText Label="Amendments" Locale="ความเห็น"/>
      <MapText Label="By" Locale="โดย"/>
      <MapText Label="Date" Locale="วันที่"/>
      <MapText Label="Revision" Locale="ครั้งที่แก้ไข"/>
    </MapTexts>
  </ProjectInfo>
  <SectionOptions>
    <VerticalScale>500.0</VerticalScale>
    <HorizontalScale>1000.0</HorizontalScale>
    <HozGridSpace>10.0</HozGridSpace>
    <VertGridSpace>2.0</VertGridSpace>
    <GridLineType>0</GridLineType>
    <CalcIntersection>True</CalcIntersection>
    <CalcArea>True</CalcArea>
    <TrimTypical>False</TrimTypical>
    <NumDecimalElev>3</NumDecimalElev>
    <NumDecimalDist>3</NumDecimalDist>
    <UseIntervalText>True</UseIntervalText>
    <IntervalDist>10.0</IntervalDist>
    <PrefixText>MSL</PrefixText>
    <PostfixText>MSL</PostfixText>
    <UsePostPrefix>1</UsePostPrefix>
    <UseOffsetElevFormat>2</UseOffsetElevFormat>
    <CalcPlotAreaCut>True</CalcPlotAreaCut>
    <CalcPlotAreaFill>True</CalcPlotAreaFill>
    <NumVertCLLeft>1</NumVertCLLeft>
    <NumVertCLRight>90</NumVertCLRight>
    <NumHozTopBottom>10</NumHozTopBottom>
    <LeftSideText>LT.</LeftSideText>
    <RightSideText>RT.</RightSideText>
    <StationText>Km.</StationText>
    <SelectedTBlock>2</SelectedTBlock>
    <NumSectionRows>1</NumSectionRows>
    <NumSectionColumns>1</NumSectionColumns>
    <SurveyType>0</SurveyType>
    <PlotTBlock>True</PlotTBlock>
    <SwapLeftAndRight>False</SwapLeftAndRight>
  </SectionOptions>
  <PageSetup>
    <Size>Custom</Size>
    <Width>940.0</Width>
    <Height>200.0</Height>
  </PageSetup>
  <Sections>
    <NumSections>1</NumSections>
    <Section Name="0+000">
      <XPositionOnPaper>47.7</XPositionOnPaper>
      <YPositionOnPaper>11.7</YPositionOnPaper>
      <TopGridElev>14.0</TopGridElev>
      <NumPoints>29</NumPoints>
      <Points>
        <Point Elevation="5.741" Offset="0.0"/>
        <Point Elevation="5.802" Offset="29.5"/>
        <Point Elevation="4.186" Offset="44.5"/>
        <Point Elevation="1.955" Offset="66.778"/>
        <Point Elevation="1.04" Offset="84.5"/>
        <Point Elevation="1.017" Offset="114.5"/>
        <Point Elevation="0.895" Offset="144.5"/>
        <Point Elevation="1.162" Offset="174.5"/>
        <Point Elevation="1.012" Offset="234.5"/>
        <Point Elevation="1.145" Offset="264.5"/>
        <Point Elevation="1.16" Offset="316.642"/>
        <Point Elevation="1.317" Offset="339.5"/>
        <Point Elevation="1.619" Offset="386.947"/>
        <Point Elevation="1.518" Offset="409.5"/>
        <Point Elevation="1.311" Offset="454.5"/>
        <Point Elevation="1.261" Offset="484.5"/>
        <Point Elevation="1.065" Offset="544.5"/>
        <Point Elevation="1.113" Offset="574.5"/>
        <Point Elevation="2.799" Offset="634.5"/>
        <Point Elevation="1.664" Offset="664.5"/>
        <Point Elevation="1.442" Offset="694.5"/>
        <Point Elevation="1.108" Offset="724.5"/>
        <Point Elevation="1.099" Offset="754.5"/>
        <Point Elevation="1.854" Offset="784.5"/>
        <Point Elevation="1.549" Offset="814.5"/>
        <Point Elevation="8.402" Offset="844.5"/>
        <Point Elevation="8.555" Offset="866.792"/>
        <Point Elevation="8.68" Offset="889.5"/>
        <Point Elevation="8.58" Offset="916.9"/>
      </Points>
    </Section>
  </Sections>
</root>

ต่อไปเป็น Typical Section ขนาดเล็กกว่า ผมตั้งชื่อว่า lake-typical.txml

<root version="1.0">
  <!--Generated by XSection Plot-->
  <!--This data file is Typical section-->
  <Header>
    <AppName>XSection Plot</AppName>
    <Developer>Prajuab Riabroy</Developer>
    <Version>4.1.512</Version>
    <SectionType>Typical</SectionType>
    <DateCreated>2017-11-12 18:42:28.929847</DateCreated>
  </Header>
  <Sections>
    <NumSections>1</NumSections>
    <Section Name="">
      <XPositionOnPaper>0.0</XPositionOnPaper>
      <YPositionOnPaper>0.0</YPositionOnPaper>
      <TopGridElev>0.0</TopGridElev>
      <NumPoints>4</NumPoints>
      <Points>
        <Point Elevation="5.0" Offset="36.944"/>
        <Point Elevation="5.0" Offset="695.0"/>
        <Point Elevation="8.4" Offset="845.0"/>
        <Point Elevation="8.44" Offset="900.0"/>
      </Points>
    </Section>
  </Sections>
</root>

เปิดไฟล์ข้อมูลทดสอบบน XSection Plot

จากนั้นนำสองไฟล์มาเปิดด้วย XSection Plot เวลาเปิดไฟล์ให้เลือกรูปแบบของไฟล์ด้วยจะได้เปิดง่าย  มีชื่อ extension ตามลำดับดังนี้ gxml, txml

จะได้ข้อมูลปรากฎขึ้นบนโปรแกรมดังนี้

ตั้งหน้ากระดาษ (Page Setup)

ผมลองเลือกใช้หน้ากระดาษที่ไม่มาตรฐานเพื่อให้ฟิตกับขนาดรูปตัดตามยาว ยาว 940 มม. และกว้าง 200 มม.

ตั้งค่า (Settings)

ผมตั้งสเกลทางราบเป็น 1:1000 และสเกลทางดิ่ง 1:250 อย่างอื่นดูรูปด้านล่าง

จัดวางรูปตัดบนกระดาษ (Section Layout)

จะเห็นกระดาษขนาด 200 มม. x 940 มม. แล้วเลือกพารามิเตอร์ดังรูปด้านล่าง

ดูรูปตัด (Section Viewer)

จะเห็นรูปตัดตามยาวที่ประกอบไปด้วย Existing Ground และ Typical

ลองซูมดู ก็ได้แบบ drawing มาพอถูๆไถๆ ที่สามารถนำไปเขียนเพิ่มเติมได้ในโปรแกรมด้านเขียนแบบทั้งหลายเช่น Autocad, Microstation, Draftsight

Save to DXF

จัดเก็บไฟล์ในรูป Autocad DXF เพื่อสามารถนำไปเปิดในโปรแกรมอื่นได้

เปิดไฟล์แบบรูปตัดตามยาว

ผมใช้ Microstation เปิดแบบรูปตัดตามยาวได้ผลลัพธ์ดังนี้และพร้อมจะนำแบบไปเขียนเพิ่มเติมตามความต้องการ

ครับคงอีกไม่นานก็จะคงจะปล่อยเวอร์ชั่นเสถียรให้สามารถดาวน์โหลดได้ พบกันใหม่ครับ

แนะนำการย้ายโค้ดจาก PyQt5 เป็น PySide2

ย้ายโค้ด XSection Plot

ในขณะนี้ทำงานอยู่ที่บังคลาเทศ โครงการก่อสร้างรถไฟฟ้าที่กรุงธากา มีโอกาสกลับมาพัก ก็พอมีเวลาว่างพยายามย้ายโค้ดของโปรแกรม XSection Plot จากของเดิมที่พัฒนาด้วย PyQt5 ที่ยังติดเรื่องลิขสิทธิ์บางส่วน โดยย้ายมาใช้ PySide2 ที่เปิดกว้างกว่า ความจริงทั้งคู่ใช้เครื่องยนต์ (Engine) เดียวกันคือ Qt5 platform ดังนั้นเมื่อย้ายโค้ดสำเร็จแล้วเวลารันก็หน้าตาเหมือนกันเป๊ะดังรูปด้านล่างที่คอมไพล์ด้วย PySide2

จัดการปลั๊กอิน PySide2

การย้ายโค๊ดใช้เวลาไม่นานนัก ใช้เวลาประมาณ 2 ชั่วโมง เนื่องจากผมเคยย้ายโค้ด Surveyor Pocket Tools ทำให้รู้แนวทางลัดพอสมควร อันดับแรกขอย้อนกลับหน่อย เนื่องจาก PySide2 จะมองหาโฟลเดอร์ลิ๊งค์ไลบรารีของตัวเองชื่อ “plugins” ถ้าไม่เจอจะ error แล้วหยุดทันที ดังนั้นก่อนอื่นควรจะแทรกโค๊ดนี้เข้าไปก่อน เริ่มตั้งแต่ import PySide2 ตามด้วยตรวจสอบว่า PySide2 อยู่ที่โฟลเดอร์ไหนจัดเก็บเข้าตัวแปร dirname จากนั้นค้นหาพาทของ “plugins” ที่อยู่ใต้โฟลเดอร์ dirname ด้วยคำสั่ง os.path.join()

import os
import sys
import PySide2
dirname = os.path.dirname(PySide2.__file__)
plugin_path = os.path.join(dirname, 'plugins', '')
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = plugin_path
print('plugin_path = ', plugin_path)

ที่เครื่องคอมพิวเตอร์ผม จะปริ๊นท์พาทของ “plugins” ดังนี้

plugin_path =  C:\Miniconda3\envs\py36_64\lib\site-packages\PySide2\plugins\

เพราะว่าผมใช้ Miniconda เป็นตัวจัดการระบบ environment ของ python ผมสร้าง envs ชื่อ “py36_64” เป็น python รุ่น 3.6 แบบ 64 บิต และ PySide2 ก็จะถูกติดตั้งมาอยู่ภายใต้โฟลเดอร์นี้ อีก envs หนึ่งที่สร้างไว้ชื่อ “py36_32” เป็น python รุ่น 3.6 แบบ 32 บิต เมื่อรันโปรแกรมแล้วจะปริ๊นท์พาทมาดังนี้

plugin_path =  C:\Miniconda3\envs\py36_32\lib\site-packages\PySide2\plugins\

วิธีการสร้าง environment สำหรับไพทอนก็กลับไปดูโพสต์เก่าของผมได้ครับ

เปลี่ยนคำ PyQt5 เป็น PySide2

ยังอยู่ในส่วน import ที่โค๊ดเดิมของโปรแกรมผมเรียกใช้ไลบรารีของ PyQt5 ดังนี้

from PyQt5.QtGui import QPixmap, QIcon, QKeySequence, QFont, QIntValidator, QCursor
from PyQt5.QtCore import Qt, pyqtSlot, QSettings, QFileInfo, QSize, QFile
from PyQt5.QtWidgets import QUndoStack, QSplashScreen, QApplication, QMainWindow, QTabWidget, QAction, QStatusBar,\
     QMenu, QWidget, QSizePolicy, QLineEdit, QFileDialog, QMessageBox, QDesktopWidget

เปลี่ยนเป็น

from PySide2.QtGui import QPixmap, QIcon, QKeySequence, QFont, QIntValidator, QCursor
from PySide2.QtCore import Qt, Slot, QSettings, QFileInfo, QSize, QFile
from PySide2.QtWidgets import QUndoStack, QSplashScreen, QApplication, QMainWindow, QTabWidget, QAction, QStatusBar,\
     QMenu, QWidget, QSizePolicy, QLineEdit, QFileDialog, QMessageBox, QDesktopWidget

ส่วนใหญ่เกือบ 99.99% ที่เหมือนกัน ยกเว้น Signal & Slot

Signal and Slot

มีข้อแตกต่างกันเล็กน้อย เช่นเดิมใน PyQt5 เรียกใช้ pyqtSlot, pyqtSignal ให้เปลี่ยนเป็น Slot, Signal ใน PySide2 ครับ
นอกจากส่วน import แล้ว ในโค๊ดเดิมที่ประกาศคลาส โค้ดเดิมผมเรียกใช้ Signal and Slot ดังนี้

class OverlapSection(QObject):
    '''Horizontal &amp; Vertical overlapped.'''
    overlapped = pyqtSignal(str)
 
    def __init__(self):
            QObject.__init__(self)
 
    def emitOverlapSignal(self, message):
        self.overlapped.emit(message)

เปลี่ยนใหม่เป็น

class OverlapSection(QObject):
    '''Horizontal &amp; Vertical overlapped.'''
    overlapped = Signal(str)
 
    def __init__(self):
            QObject.__init__(self)
 
    def emitOverlapSignal(self, message):
        self.overlapped.emit(message)

ติดตั้ง PySide2 จากไฟล์ wheel

ก็ขอแนะอีกนิดว่า PySide2 เวลาติดตั้งให้ใช้แพ๊คเกจแบบ wheel ที่ทางทีมงานได้ทำไว้ดีกว่าครับ ติดตั้งง่ายไม่งอแง ดาวน์โหลดได้ตามลิ๊งค์นี้ จะสังเกตเห็นชื่อไฟล์ประมาณนี้

PySide2-5.6-cp35-cp35m-win32.whl 	 
PySide2-5.6-cp35-cp35m-win_amd64.whl 	 
PySide2-5.6-cp36-cp36m-win32.whl 
PySide2-5.6-cp36-cp36m-win_amd64.whl

จะเห็นว่า PySide2 สนับสนุนทั้งไพทอน 3.5 และ 3.6 และในตอนนี้ Qt5 รุ่น  5.6 สำหรับคำสั่งที่ติดตั้งก็ง่ายๆใช้ pip ตามด้วยชื่อไฟล์ wheel

pip install PySide2-5.6-cp36-cp36m-win_amd64.whl

สรุปแล้วการย้ายโค้ดง่ายๆไม่ลำบากกินแรง แต่ไปกินแรงเข็นครกอีกทีคือตอนสร้างไบนารีไฟล์ด้วย Pyinstaller ความจริง Pyinstaller ถ้าเข้าใจแล้วปรับใช้ได้ไม่ยาก แต่สำหรับมือใหม่บอกตรงๆว่า ถ้าโปรแกรมที่พัฒนาเรียกใช้ไลบรารีมากหลายอันแล้ว เป็นนรกลูกย่อมๆครับ ถ้าไลบรารีตัวไหนมีคนเขียนไฟล์ hook ให้ก็ง่ายหน่อย แต่ถ้าไม่มีต้องออกแรงกันพอสมควร สำหรับ PySide2 ผมจัดการแบบ manual ครับ รู้ว่าตอนโปรแกรมรันมันต้องการอะไร ตอนใช้ Pyinstaller ผมก็จัดการ copy ไฟล์ไปตามต้องการ ถ้ามีโอกาสจะมาเขียนเรื่องการใช้ Pyinstaller อีกสักตอน พบกันตอนหน้าครับ

เริ่มต้น Python ด้วย PySide2 + Miniconda + PyCharm

ขอนำเสนอวิธีการติดตั้งในเบื้องต้นเพื่อใช้ PySide2 สำหรับผู้ที่เริ่มต้นศึกษาเขียนไพทอน บางครั้งไม่รู้จะเริ่มต้นตรงไหน ผมจะขอแนะนำสามสหายที่จะมาช่วยทำให้ชีวิตง่ายขึ้น

  • PySide2 อยู่ระหว่างการพัฒนาจากเจ้าของ Qt framework เองจึงไม่ต้องห่วงว่าโครงการจะล้มลาเลิกร้างกันก่อน ฟรีและมีสัญญาอนุญาตแบบ LPGL v2 สามารถพัฒนาโปรแกรมเพื่อการค้าได้ รุ่นเสถียรอีกไม่นานนักน่าจะออกมาแล้ว
  • Miniconda3 เป็นส่วนหนึ่งของ Anaconda ซึ่งเป็นเฟรมเวิร์คสำหรับการทำ data science สำหรับภาษาไพทอน ส่วน Miniconda เป็นตัวจัดสภาพแวดล้อมให้ไพทอน เช่นถ้าต้องการพัฒนาโปรแกรมให้สามารถรันได้ทั้ง 32 บิตและ 64  บิต ก็ต้องตัวนี้เลย สามารถเลือกรุ่นของ Python ได้ด้วย อย่างเช่น PySide2 ต้องการไพทอน 3.5 สามารถกำหนดรุ่นของไพทอนได้ทีหลังด้วยการ config ที่ง่ายไม่กี่ขั้นตอน ฟรีแบบมีสัญญาอนุญาตแบบ BSD 3-clause
  • PyCharm สภาพแวดล้อมในการพัฒนาทั้ง editor, debugger ครบครัน ใช้งานสะดวก ง่าย ฟรีสำหรับรุ่น community ครั้งหนึ่งผมเคยชมว่า Eric ดีแต่ตัวนี้ดีกว่ามาก รุ่น community ฟรีมีสัญญาอนุญาตแบบ Apache license

ต่อไปจะลำดับความเรียงว่าต้องติดตั้งตัวไหนก่อนตัวไหนหลัง

ดาวน์โหลดและติดตั้ง Miniconda

ขณะที่เขียนอยู่นี้เวอร์ชั่น 3 ต้องการดาวน์โหลดก็ตามลิ๊งนี้ download miniconda ส่วนตัวผมเลือกรุ่น 64 บิตขนาดประมาณ 60 MB ติดตั้งก็ง่ายๆ เมื่อได้ไฟล์มาแล้วตอนติดตั้ง ช่วงที่ถามว่าจะเอาโปรแกรมไปเก็บไว้ที่ไหนผมขอแนะนำให้ไว้ตรงรากของไดรว์ C จะหาง่ายและสะดวกที่สุดตอนคลิกเข้าไปดูไฟล์

Miniconda3-latest-Windows-x86_64 (1)_2017-04-23_16-57-39

เมื่อติดตั้งเสร็จ เวลาใช้โปรแกรมนี้ใน windows 10 ใช้ปุ่มวินโดส์ (Win) บนคีย์บอร์ดแล้วพิมพ์คำว่า “anaconda” บางทีพิมพ์แค่คำว่า “ana” ก็จะเห็น shortcut “Anaconda Prompt” ขึ้นมาก็ enter เข้าได้เลย จะแสดงพาทที่ติดตั้งไว้ด้วยเครื่องผมคือ “C:\Miniconda3” ลองเรียก python ดูจะเห็นว่าเป็นรุ่น 3.6.0

cmd_2017-04-24_04-54-34

สมมติว่าผมต้องการติดตั้ง python รุ่น 3.5 เพราะว่า Pyside2 ต้องการรุ่นนี้ และผมต้องการพัฒนาโปรแกรมด้วย PySide2 ทั้ง 32 bit และ 64 bit ที่คอมมานด์ พร็อมป์จัดการพิมพ์ตามนี้

set CONDA_FORCE_32BIT=1
conda create -n py35_32 python=3.5

คำสั่งแรกบังคับให้ miniconda อยู่ในโหมด 32 บิต คำสั่งถัดไปสร้างสภาพแวดล้อมชื่อ py35_32 แล้ว Miniconda จะดาวน์โหลดไลบรารีที่เกี่ยวข้องมาติดตั้งให้ทันที โดยในที่นี้ก็คือ Python รุ่น 3.5  เวลาต้องการใช้งานสภาพแวดล้อมนี้ใช้คำสั่งนี้

activate py35_32

จะได้ผลลัพธิ์ดังนี้ จะเห็นตัวหนังสือด้านหน้าจะเปลี่ยนเป็น “py35_32”

cmd_2017-04-23_18-47-30

ต่อไปสร้างสภาวะแวดล้อมเป็นไพทอน 64 บิต คำสั่งแรกปลดล็อคการใช้โหมด 32 บิต และคำสั่งที่สองสร้างสภาวะแวดล้อมชื่อ “py35_64” ระบุไปว่าเราต้องการไพทอนรุ่น 3.5

set CONDA_FORCE_32BIT=
conda create -n py35_64 python=3.5

เวลาใข้งานต้องการจะใช้ในโหมดนี้ ใช้คำสั่ง

activate py35_64

ถ้าดูโฟลเดอร์ของ miniconda จะเห็นว่ามีการสร้างโฟลเดอร์ให้สองโฟลเดอร์ ตามที่เราสร้างด้วยคำสั่ง create

explorer_2017-04-24_04-58-04

ติดตั้งไลบรารีบนสภาพแวดล้อม 32 บิต

ต่อไปจะติดตั้งไลบรารีต่างๆ ซึ่งก็แล้วแต่ละคนที่จำเป็นต้องใช้ ตัวอย่างที่ผมต้องการใช้งานได้แก่ openpyxl, pyproj, geographiclib, pyshp, gmplot, simplekml และที่สำคัญที่สุดคือ pyside2 เนื่องจากไลบรารี openpyxl บางครั้งผมติดตั้งจากคำสั่ง pip และไลบรารีตัวนี้ต้องการ lxml บางครั้งติดตั้งแล้วใช้งานไม่ได้ ต้องไปดาวน์โหลดไฟล์ wheel มาติดตั้งเอง หมายเหตุว่าไฟล์ wheel คุณสมบัติพิเศษของมันคือสามารถแนบไฟล์ที่ต้องการใช้มาได้ด้วยเช่นไฟล์ dll

ต่อไปจะติดตั้งไลบรารีในโหมด 32 บิตก่อน อย่าลืมใช้คำสั่ง

activate py35_32

ติดตั้ง lxml ด้วยการไปดาวน์โหลดไฟล์ wheel ที่เว็บนี้มีเกือบทุกอย่างที่ต้องการ download python extension packages ไปถึงแล้วก็ค้นหาในเว็บหา lxml เจอแล้วก็ดาวน์โหลดมาทั้ง 32 บิตและ 64 บิต และไฟล์ต้องมีคำว่า cp35 ด้วยเป็นการระบุว่าใช้กับ python 3.5

firefox_2017-04-24_14-12-55

pip install lxml‑3.7.3‑cp35‑cp35m‑win32.whl

ต่อไปติดตั้งไลบรารีของไพทอนตัวที่เหลือ

pip install openpyxl

pip install geographiclib

pip install pyshp

pip install pyproj

pip install gmplot

pip install simplekml

ติดตั้ง PySide2 ด้วย wheel

เนื่องจาก PySide2 เวอร์ชั่นจริงยังไม่ได้ออกมา ดังนั้นต้องอาศัยไฟล์ wheel หรืออีกทางหนึ่งก็คือไปดึงไฟล์โค๊ดจาก github มาคอมไพล์เอง แต่ผมทำไม่สำเร็จ เลยต้องอาศัยวิธีนี้ ดาวน์โหลดไฟล์ wheel ได้จากลิ๊งค์นี้ download pyside2

ในตอนนี้จะเห็นไฟล์อยู่สองไฟล์ดังรูปด้านล่าง จะเห็นว่าชื่อไฟล์มีคำว่า cp35 คือระบุว่าต้องการไพทอนรุ่น 3.5 ก็เหมือนที่ผมบอกไปแล้วว่าทำไมเราต้องการไพทอนรุ่น 3.5 ให้ดาวน์โหลดไปทั้งสองไฟล์ครับ

firefox_2017-04-24_07-35-19

ใช้ command prompt ของ miniconda ทำการ cd เข้าไปหาไฟล์ที่เก็บไว้แล้วติดตั้งด้วย pip

pip install  PySide2-2.0.0.dev0-cp35-cp35m-win32.whl

สำหรับเครื่องคอมพิวเตอร์ผม ตอนติดตั้ง PySide2 ดูจากรูปด้านล่าง

cmd_2017-04-24_07-41-40

ติดตั้งไลบรารีบนสภาพแวดล้อม 64 บิต

เหมือนกับติดตั้งให้ 32 บิต เพียงแต่ตอนติดตั้ง PySide2 ใช้ไฟล์ wheel คนละตัว เริ่มด้วยคำสั่งนี้ก่อน

activate py35_64

จากนั้นก็ใส่ยาวเลย

pip install lxml‑3.7.3‑cp35‑cp35m‑win_amd64.whl

pip install openpyxl

pip install geographiclib

pip install pyshp

conda install pyproj

pip install gmplot

pip install simplekml

pip install PySide2-2.0.0.dev0-cp35-cp35m-win_amd64.whl

ลองทดสอบเรียกไพทอน แล้ว import ไลบรารีเหล่านี้ดูกัน

cmd_2017-04-24_07-52-59

ผ่านฉลุยครับไม่มี error เลย

ติดตั้ง PyCharm

ต่อไปจะดาวน์โหลด PyCharm รุ่น Community ได้ตามลิ๊งค์นี้ download pycharm เลือกเอารุ่น community ซึ่งจะฟรี ได้ไฟล์มาแล้วก็ทำการติดตั้งจากไฟล์ installer ที่ดาวน์โหลดมา เมื่อติดตั้งเสร็จแล้ว ที่สำคัญคือจะ config ให้ pycharm รู้จัก python ว่าต้องใช้สภาพแวดล้อมไหนอย่างไร รัน Pycharm ครั้งแรกถ้ายังไม่มีไฟล์ project เลยเรียกเมนู File > New Project… แล้วใส่ชื่อโครงการ และที่สำคัญคือสามารถเลือกสภาวะแวดล้อมได้ ผมเลือก “py35_64”

pycharm64_2017-04-24_08-05-09

เมื่อเข้าไปแล้วโครงการยังว่าง ผมสร้างไฟล์ใหม่ ด้วยคำสั่ง File > New… เลือกเป็น python file จะเห็นหน้าตาโล่งๆ ว่างปล่าว

pycharm64_2017-04-24_08-11-26

แต่ถ้าต้องการเปลี่ยนเป็นสภาวะแวดล้อม “py35_32” ในโหมด 32 บิต จะต้องไปที่เมนู File > Settings… จะเห็นไดอะล็อกที่สามารถเปลี่ยนได้ที่ Project Intepreter

pycharm64_2017-04-24_08-12-59

โปรแกรมตัวอย่างทดสอบ PySide2

มาลอง PySide2 กันครับ ตรงหน้าว่างๆของ test.py ลองพิมพ์ตัวอย่างนี้เข้าไป หรือ copy & paste ไปก็ได้ แต่มือใหม่ควรจะหัดพิมพ์ สำหรับโปรแกรมมิ่งจะไม่อธิบายนะครับ แต่ผมแนะนำว่าให้หาอ่านจาก PyQt5 ดีกว่าเพราะ tutorial เยอะมาก

class=”code”># -*- coding: utf-8 -*-

import sys
from PySide2.QtWidgets import QApplication, QWidget

if __name__ == ‘__main__’:

app = QApplication(sys.argv)

w = QWidget()
w.resize(250, 150)
w.move(300, 300)
w.setWindowTitle(‘Simple’)
w.show()

sys.exit(app.exec_())

จะทำการรันดู ที่เมนู Run > Run… เลือกไฟล์ test.py  จะได้ผลลัพธ์คือ error ไม่มีอะไรครับ PyCharm  หาไลบรารีของ PySide2 ไม่เจอ

pycharm64_2017-04-24_08-23-45

มีวิธีหลายวิธีตั้งแต่ environment variables  ให้วินโดส์ วิธีแรกที่จะแนะนำนั้นง่ายเพิ่มโค๊ดประมาณ 5 บรรทัด

# -*- coding: utf-8 -*-
import sys
import os
import PySide2

dirname = os.path.dirname(PySide2.__file__)
plugin_path = os.path.join(dirname, 'plugins', '')
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = plugin_path

from PySide2.QtWidgets import QApplication, QWidget

if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = QWidget()
    w.resize(250, 150)
    w.move(300, 300)
    w.setWindowTitle('Hello world')
    w.show()

    sys.exit(app.exec_())

โดยเฉพาะบรรทัดที่ dirname = os.path.dirname(PySide2.__file__) จะเป็นการดึงเอาที่อยู่ของไดเรคทอรีหรือโฟลเดอร์ของ PySide2 ที่่เราใช้งานอยู่ ไม่ว่าเรากำลังใช้ 32 บิตหรือ 64 บิต ก็ไม่มีปัญหา ลองรันดูที่นี้ผ่านครับ

pycharm64_2017-04-24_14-39-17

วิธีที่สองใช้วิธีเขียน Environment Variables ที่คีย์บอร์ดกดคีย์ win  ค้างไว้กด x (Win + x) จะมีเมนูของวินโดส์เลือก System แล้วเลือก Advance system settings จากนั้นจะมีไดอะล็อกอีกตัวขึ้นมา คลิกเลือก Environment Variables

SystemPropertiesAdvanced_2017-04-24_17-19-09

คลิก New… ที่ System Variables ถ้าเครื่องผมป้อนดังรูปด้านล่าง สำหรับสภาพแวดล้อม 64 บิต ถ้า 32 บิต แก้ตัวหนังสือ py35_64 เป็น py35_32

SystemPropertiesAdvanced_2017-04-24_17-21-36

วิธีนี้อานุภาพรุนแรงครับ เพราะว่าโปรแกรมบางโปรแกรมที่เขียนด้วย PyQt5 หรือ Qt5 ที่ติดตั้งไว้บนเครื่องคอมพิวเตอร์จะพร้อมใจกัน error เพราะหาไลบรารีของ  Qt5 ไม่เจอ เพราะ system variable ตัวนี้ QT_QPA_PLATFORM_PLUGIN_PATH สิทธิ์จะมากที่สุด ปกติโปรแกรมที่พัฒนาด้วย Qt จะเขียนไฟล์ qt.conf ไว้เพื่อระบุว่าไฟล์ไลบรารีของ Qt อยู่ที่ไหน โดยที่ไฟล์ qt.conf ก็วางที่เดียวกับ execute file แต่ถ้าเจอ system variable ตัวนี้จะไม่อ่านไฟล์ qt.conf ก่อน แต่จะวิ่งมาที่พาธที่เราตั้งนี้

เวลาจะเขียนโปรแกรมด้วย PyCharm ผมจะมาตั้งก่อน เสียเวลานิดหน่อย เวลาไม่ได้เขียนก็ลบออก โปรแกรมอื่นๆจะทำงานได้ตามปกติ แต่ตอนที่ผมยังใช้ PyQt5 ไม่มีปัญหาครับ ไม่ต้องมานั่งใส่ใหม่และลบออก ชีวิตยุ่งขึ้นมานิด แต่แลกเอาสัญญาอนุญาตของ PySide2 ที่เปิดกว้างกว่าครับ พบกันตอนหน้าครับ

ปลดพันธนาการ PyQt5 ด้วย PySide2

ตอนนี้ถือว่ามาเล่าสู่กันฟังจากประสบการณ์ เป็นเรื่องโปรแกรมมิ่ง ถ้าไม่สนใจเรื่องโปรแกรมมิ่งก็ผ่านไปได้ครับ

PyQt5 กับลิขสิทธิ์แบบ GPL v3

ผมเขียนไพทอนด้วยการใช้ PyQt5 มาได้สักระยะเวลาหนึ่ง น่าจะสองปีกว่าได้ ยอมรับว่าชอบมากๆ ก็ไม่ได้ระแวดระวังเรื่องกฎหมายลิขสิทธิ์เท่าไหร่นัก ลิขสิทธิ์ของ PyQt5 เป็นแบบ GPL v3 ซึ่งสาระโดยรวมๆสามารถเอาไปใช้ได้สองกรณีคือ พัฒนาโปรแกรมแบบเปิดโค๊ด (open source) และแจกจ่ายฟรีพร้อมโค๊ด กรณีนี้ไม่จำเป็นต้องเสียเงินค่าลิขสิทธิ์ แต่ถ้าเป็นกรณีที่สองคือการพัฒนาโปรแกรมเพื่อการค้าและปิดโค๊ด จะต้องเสียค่าลิขสิทธิ์ประมาณ 500US$ ต่อปี ซึ่งไม่น่าจะมากมายนัก ผมเองเอา PyQt5 มาใช้และแจกจ่ายโปรแกรมของผมให้ฟรีก็จริงแต่ปิดโค๊ด ยังไม่พร้อมที่จะเปิดโค๊ดและจ่ายค่าลิขสิทธิ์เนื่องจากไม่ได้หารายได้จากโปรแกรมที่แจกจ่ายไป

ทางสองแพร่ง

ผมลองมองหาเครื่องมือพัฒนาตัวอื่นๆที่มีลิขสิทธิ์เอื้อแบบปิดโค๊ดแต่ยังสามารถใช้ได้ฟรี ที่อ่านๆมาแล้วอยู่ในใจคือ Kivy Platform

  • Kivy framework Platform รองรับภาษาไพทอน ข้อดีหลายอย่างคือ  cross platform  เขียนโปรแกรมครั้งเดียวสามารถนำไปคอมไพล์ บิวด์ได้บน Linux, Mac OS หรือสามารถพอร์ตลงไปหามือถือ Android, IOS ก็ได้ ที่สำคัญคือเป็นโครงการเปิดโค๊ด มีลิขสิทธิ์แบบ MIT License ซึ่งนอกจากจะเปิดโค๊ดแล้ว ยังอิสระเสรีมาก ซอฟแวร์ที่ใช้ลิขสิทธิ์แบบนี้ ผู้ใช้สามารถเอาไปทำอะไรก็ได้ตั้งแต่ก๊อปปี้ แก้ไข รวม แจกจ่ายหรือกระทั่งนำไปขายก็ได้ สุดท้ายถ้าใช้ Kivy พัฒนาก็ยังสามารถนำโปรแกรมไปทำการค้าได้
  • แต่ปัญหาของผมคือ โปรแกรมที่เขียนมีขนาดค่อนข้างใหญ่แล้ว การพอร์ตจากโค๊ดของ PyQt5 ไปยัง Kivy ไม่ใช่่จะทำได้ง่ายๆ เนื่องจาก Kivy มีรูปแบบ GUI ของตัวเอง ไม่ง่ายครับต้องใช้เวลามาก

PySide2 ผู้มาช่วยชีวิต

ในขณะที่กำลังจะจมน้ำอยู่นั้น นึกถึง PySide รุ่นแรกซึ่งรองรับและใช้ได้แค่ Qt4 ไม่ใช่ Qt5 ที่ผมตกร่องปล่องชิ้นไปแล้ว การจะ downgrade กลับหลังหันไปใช้ Qt4 ผ่าน PySide รุ่นหนึ่งไม่ได้ง่ายต้องรื้อโค๊ดพอสมควร เผลอๆอาจจะยากกว่าการกลับไปขอคืนดีกับแฟนเก่า 🙂 ส่วนเรื่องลิขสิทธิ์เท่าที่ทราบมาคือ PySide ใช้ลิขสิทธิ์แบบ LGPL v2.1 คือสามารถนำไปใช้พัฒนาโปรแกรมสำหรับปิดหรือเปิดโค๊ดได้ ทั้งแจกจ่ายฟรีและขายได้ เพียงแต่ไปเอาไลบรารีตัวไหนที่เป็น LPGL มาใช้จะต้องคงความเป็น LGPL ไว้คือต้องเปิดโค๊ตไลบรารีตัวนั้นไปให้ผู้ใช้ด้วย  ข่าวร้ายของ PySide รุ่นหนึ่งคือโครงการตาย ไม่ขยับมาแล้วสามปีกว่า ผมลองค้นเข้าไปลึกๆ ปรากฎว่าโครงการนี้ตอนแรกๆ ได้มีนักพัฒนาอิสระ fork โครงการมาบน Github กลุ่มเล็กๆต่อมาได้ย้ายและไปพัฒนาต่อเป็นทางการจาก Qt Company เจ้าของ Qt framework ตัวจริงเสียงจริง เหมือนฟ้ามาโปรด แต่ยังไม่แน่ใจว่าโค๊ดเดิม PyQt5 ของผมจะ compatible กับ PySide2 แค่ไหน

ในขณะที่ไม่รู้จะทำอะไรก็เลยไปดาวน์โหลดหยิบเอา PySide ตอนนี้เป็นรุ่น PySide2 ที่กำลังพัฒนาอยู่ เป็นไฟล์ wheel ครับที่ทีมงานได้คอมไพล์และบิวท์มาให้ลองใช้ก่อน รุ่นที่ผมหยิบมาใช้ในขณะนี้ บิวท์นานมาแล้วประมาณหกเดือนกว่า รุ่นล่ากว่านี้ยังไม่มี

PySide2 ใช้ลิขสิทธิ์แบบ LGPL v2 เหมือนกันกับ PySide รุ่นหนึ่ง เมื่อดาวนโหลดมาแล้วก็ติดตั้ง มาลองดูว่าพอไปได้ไหม ผมใช้เวลาว่างๆตอนเลิกงานลองไปหก เจ็ดวัน สำเร็จครับ ส่วนใหญ่ใช้ได้กับโค๊ดเดิม แค่ตอน import ไลบรารีเปลี่ยนแค่หัวจาก PyQt5 มาเป็น PySide2 มีส่วนนิดเดียวผมแก้ไขโค๊ดใหม่ให้เข้ากับ PySide2 แต่น้อยมาก และที่เจออีกหนักอีกหน่อยคือ ระบบรายงานผลการแสดงภาพบนจอมอนิเตอร์คือ Screen ยังไม่เสร็จ ทำให้ผมไม่สามารถตรวจได้ว่าผู้ใช้ใช้จอที่ resolution เท่าไหร่ มี dot pixel  ratio เท่าไหร่ อันนี้สำคัญเพราะว่าจอ HiDPI เช่นจอ 4K ทั้งหลาย ตอนนี้ใช้กันมากแล้ว เมื่อ PySide2 ไม่มีให้ ต้องไปหาโค๊ดมาช่วย ใช้ Windows API ไปพลางๆก่อน พอเสร็จเมื่อไหร่ ค่อยกลับมาใช้โค๊ดของ PySide2 ที่เสร็จแล้วต่อ

ผมพูดได้ว่าตอนนี้โปรแกรมของผม เกือบจะ 99.9% ใช้ของเดิม มาปรับแต่งเองเพียง 0.1% มันง่ายหรือเพราะโปรแกรมผมไม่ได้ใช้เขียนอะไรพิศดารหรือปล่าวเช่นระบบกราฟฟิคที่เลิศหรู แต่เอาละต้องขอบคุณทีมงาน PySide2 มา ณ ที่นี้ด้วยครับ

ข้อจำกัด PySide2 รุ่นพัฒนา

ข้อจำกัดของ PySide2 รุ่นพัฒนายังมีอยู่มากครับ บางครั้งผมรันโปรแกรมผ่านบรรทัดที่ผิด ไม่มีการนับแปดครับ โดนน๊อคกลางอากาศค้างไปดื้อๆ ก็น่าจะอีกสักพักครับ ที่ทีมงานของ Qt จะบิวท์มาให้ใช้กันใหม่ เพราะของเก่าผ่านมาหกเดือนกว่าแล้ว ตัวใหม่น่าจะเสถียรกว่า ดีกว่า

แปลงเป็นไฟล์ Execute ให้รันได้ นรกของโปรแกรมเมอร์ไพทอน

ปกติผมใช้ PyInstaller  สำหรับแปลงโค๊ดไพทอนเป็น execute file (exe) ที่สามารถนำไปรันได้ ทั้งที่ข้อดีของไพทอนคือเขียนง่าย อ่านง่าย ทรงพลัง และไลบรารีที่มีให้เลือกให้ใช้มากมายมหาศาล แต่เป็นที่รู้กันว่างานแปลงไฟล์จากโค๊ดไปเป็นไฟล์ exe ที่รันใช้งานได้ มันเป็นงานสุดหินสุดโหด ตอนผมเริ่มต้นใหม่ๆ ผมก็ไม่รู้ว่าไลบรารีตัวไหน ต้องการขนเอาไฟล์อะไรไปบ้างเพื่อให้สามารถรันได้ บางตัวขนกันไปเป็นโฟลเดอร์ คือแบบเรือพ่วงลากกันไปเป็นพวงๆ ตอนหลังมารู้ว่า มีไฟล์ hooks ที่ PyInstaller  อ่านมาเพื่อตัดสินใจว่าจะขนอะไรไปให้ โฟลเดอร์ไหน ก็ง่ายขึ้น ไฟล์ hooks ส่วนใหญ่มากับ PyInstaller  ถ้าไม่มีก็ไปค้นหาดาวน์โหลดมาได้

ตอนนี้ PySide2 ยังมีนักพัฒนาเอาไปใช้ในวงจำกัดอยู่ จึงไม่มีไฟล์ hooks ปล่อยมา นรกกลับมาเริ่มต้นกับผมอีกครั้ง ต้องลองทดสอบว่า PySide2 เอาอะไรไปใช้บ้าง ตอนนี้ขณะเขียนบทความนี้ ยังไม่สำเร็จครับ กำลังลองผิดลองถูก ไม่เป็นไรชีวิตย่อมมีหนทางเสมอ ผมใช้เวลาในวันอาทิตย์เกือบค่อนวันก็สำเร็จ สามารถนำไฟล์ exe ไปรันได้ตามปกติ สาเหตุที่ไม่ผ่านในตอนแรก ตัว PyInstaller มีปัญหากับโมดูลระบบชื่อ requests ต้องเอา requests รุ่นที่ไม่มีปัญหากันมาใส่แทน

เมื่อไฟล์ exe รันแล้วไม่ติดขัด ก็จะเป็นขั้นตอนต่อไปคือใช้โปรแกรมจำพวก installer มาใช้เช่น Inno Setup ขวัญใจมหาชนเจ้าประจำผมใช้อยู่ ขั้นตอนนี้ง่ายครับ เตรียมไฟล์ exe ให้พร้อม ไฟล์ไลบรารีทั้งหลาย โฟลเดอร์ที่จำเป็นต้องใช้ จากนั้นทำการ build ก็ได้โปรแกรมติดตั้ง ที่สามารถนำไปติดตั้งใช้งานได้

ดาวน์โหลด (Download)

ไปดาวน์โหลดโปรแกรมรุ่นที่บิวท์ด้วย PySide2  เป็นรุ่น V0.70 build 513 ได้แล้วที่หน้า Download ใครที่ใช้รุ่นก่อนหน้านี้ขอความกรุณาช่วย uninstall และมาดาวน์โหลดรุ่นใหม่ไปใช้ด้วย

python_2017-04-22_18-37-32
Surveyor Pocket Tools ในฉบับของ PySide2 เหมือนเดิมเพราะ engine คือตัว Qt framework เดียวกัน
python_2017-04-22_18-49-45

ตัวอย่างหน้าตาของ Transform Coordinates

ความเป็นมาของ Qt framework

เล่าเรื่อง PyQt5 vs. PySide2 ผู้อ่านบางท่านอาจจะงง ถีงที่มาที่ไป PyQt และ PySide คือเครื่องมือสำหรับพัฒนาโปรแกรมประยุกต์ ที่มีพื้นฐานมาจาก Qt framework ที่พัฒนาด้วย C++ ผู้สร้าง Qt คือบริษัท Trolltech บริษัทเล็กๆนอรเวย์ จากนั้นถูกซื้อไปในปี 2008 โดยโนเกีย (Nokia) ยักษ์ใหญ่ในตอนนั้นจากฟินแลนด์ (ย้อนหลังไป 15-25 ปีที่แล้ว คงไม่มีใครไม่รู้จักโนเกียเพราะเป็นเจ้าพ่อแห่งวงการมือถือ ยุคก่อน IPhone OS และ Android) ทำให้ลิขสิทธิ์ของ Qt ตกมาอยู่กับโนเกีย และโนเกียพยายามจะพัฒนาให้ Qt สามารถใช้กับมือถือได้ (แต่ก็ไม่ทัน ไอโอเอสและแอนดรอยด์ จนแพ้สงครามนี้ในที่สุด) ช่วงที่ Qt อยู่กับโนเกีย ในขณะนั้น Riverbank Computing บริษัทจากอังกฤษได้พัฒนา PyQt  แต่ตอนหลังมีปัญหากัน เพราะ Riverbank ไม่ยอมเปลี่่ยนลิขสิทธิ์ของ PyQt ที่ใช้แบบ GPL ส่วน Qt ใช้ลิขสิทธิ์แบบ LGPL ซึ่งยืดหยุ่นกว่า โนเกียก็ได้พัฒนา PySide ขึ้นมาเพื่อให้มีลิขสิทธิ์แบบเดียวกันกับ Qt แต่สถาณการณ์ของโนเกียตอนนั้นกำลังย่ำแย่มากๆ เพราะมือถือจากไอโอเอสของแอปเปิ้ลกับแอนด์ดรอยของกูเกิ้ลได้ครองตลาดเบ็ดเสร็จแล้ว

ในปี 2011 โนเกียขาย Qt ให้บริษัท Digia จากฟินแลนด์ หลังจากนั้นฉากสุดท้ายแล้วก็เป็นที่ทราบกันดีว่าโนเกียถูกซื้อเสนอซื้อโดยไมโครซอฟท์ในปี 2013 เฉพาะส่วนที่เกี่ยวกับมือถือสมาร์ทโฟนจบการดีลการซื้อขายในปี 2014 และจบตำนานโนเกียในที่สุด สะท้อนของสัจธรรมที่ว่าในโลกนี้ไม่มีอะไรเที่ยงแท้แน่นอน หลังจาก Digia ได้ Qt ไปในปี 2014 ได้ก่อตั้งบริษัท Qt Company และเป็นผู้พัฒนา Qt จนถึงปัจจุบัน และตามที่ผมกล่าวมาแล้ว Qt Company ได้ดึงโครงการ PySide มาสานต่อเป็นโครงการ PySide2 ซึ่งถ้าเปิดใช้เป็นทางการเมื่อไหร่ ผมก็เป็นคนหนึ่งที่ตั้งหน้าตั้งตารอคอย

โครงการในอนาคต

ก็เป็นโครงการที่วาดฝันครับ คือพอร์ตโปรแกรม Surveyor Pocket Tools ลงบนมือถือด้วย Kivy framework คงแยกแต่ละ tool ไปเป็นแต่ละ app ซึ่งก็มีฟรีบ้างขายบ้าง ก็เป็นเรื่องอนาคตไม่ได้ตั้งความหวังอะไรมากมาย ปัจจุบันคือพัฒนาและปรับปรุงโปรแกรมทั้งหลายบน Desktop ให้ใช้งานกันต่อไป และยังยืนยันว่าฟรีเหมือนเดิม และความคิดก็ยังเหมือนเดิมครับ “โลกนี้จะน่าอยู่ ถ้าทุกคนแบ่งปัน ถ้อยทีถ้อยอาศัยกัน

ทิ้งท้ายกันนิดหนึ่งจากหัวข้อ “ปลดพันธนาการ” ก็ดูจะโหดร้ายไป ตั้งให้น่าสนใจแค่นั้นครับ PyQt5 นั้นเป็นเครื่องมือพัฒนาโปรแกรมที่ดีมาก มี document ให้อ่านเยอะแยะ ติดขัดตรงไหน Stackoverflow ช่วยได้ สำหรับคนใช้เครื่องมือเพื่อการค้า ก็อุดหนุนซื้อกันไป แต่ถ้าพัฒนาโปรแกรมแบบเปิดโค๊ดก็ตัวนี้เลย ไม่ผิดหวัง สำหรับผมขอเลือก PySide2 ด้วยเหตุผลที่กล่าวมาข้างต้นทั้งหมด พบกันตอนต่อไปครับ