2016-06-23

【備忘録】PlotCanvas と横線 ─ wxPython

JavaFX で作っていたプログラムで、リソース不足 (OutOfMemoryError) に悩まされているため、結局同じことになるかもしれないと思いつつも、軽快に GUI が動く wxPython にプログラムを移植しています。python のプログラミングに不慣れなためハマった個所を備忘録としてブログ用のサンプルに書き換えて残しています。

今回は PlotCanvas に横線を引くサンプルです。

もともと JavaFX で作っていたプログラムで抱えていたリソース不足の一因は、チャート (LineChart) にありました。機能が単純なわりに、データポイントがインスタンスになるため結構なリソースを消費します。本ブログでは、JavaFX の LineChart についてはズーム機能の追加を重点的に紹介していました。実際はそれだけでなく、細かな機能を追加していましたが、紹介しきれていません。横線(あるいは縦線)を引く、というような単純な機能もその一つで LineChart に追加していましたが、wxPython の PlotCanvas でも、横線を引くのに、結局、機能の追加に迫られました。

そんなわけで、品質管理に使うようなトレンドチャートにリミット線を引く場合、というサンプルにして紹介します。

動作環境は次の通りです。

  • OS: Fedora 24 (x86_64)
  • python-2.7.11-5.fc24.x86_64
  • wxPython-3.0.2.0-10.fc24.x86_64
  • IDE: eclipse-pydev-5.0.0-1.fc24.x86_64
# -*- coding: utf-8 -*- 
import wx
import wx.lib.plot as plot

class XbarChart(plot.PlotCanvas):
    def __init__(self, parent, data, LSL, USL, gTitle, xLabel, yLabel):
        plot.PlotCanvas.__init__(self, parent, wx.ID_ANY, style=wx.SIMPLE_BORDER)
        self.SetFont(wx.Font(11, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
        self.SetFontSizeAxis(11)

        self.LSL = LSL
        self.USL = USL

        line = plot.PolyLine(data, colour='blue', width=1)
        marker = plot.PolyMarker(data, colour='blue', marker="circle")

        gc = plot.PlotGraphics([line, marker], gTitle, xLabel, yLabel)
        self.Draw(gc, xAxis=(0, len(data) + 1), yAxis=(4, 8))

    def _drawAxes(self, dc, p1, p2, scale, shift, xticks, yticks):
        super(XbarChart, self)._drawAxes(dc, p1, p2, scale, shift, xticks, yticks)
        
        # LSL, USL
        penWidth = self.printerScale * self._pointSize[0]
        dc.SetPen(wx.Pen(wx.Colour(255, 0, 0), penWidth))

        x1 = scale[0] * p1[0] + shift[0]
        x2 = scale[0] * p2[0] + shift[0]

        for spec in [self.LSL, self.USL]:
            y = scale[1] * spec + shift[1]
            dc.DrawLine(x1, y, x2, y)

class MyFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, wx.ID_ANY, "SPC", size=(600, 300))

        # X bar Chart
        data = [(1, 6.2), (2, 5.3), (3, 5.4), (4, 6.5), (5, 4.8),
                (6, 6.7), (7, 5.3), (8, 6.1), (9., 5.7), (10, 4.9),
                (11, 5.1), (12, 5.6), (13, 5.2), (14, 6.5)]
        lsl = 5.0
        usl = 7.0
        chart = XbarChart(self, data, lsl, usl, "X-bar Chart", "Lot", "Measurement")

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(chart, proportion=1, flag=wx.EXPAND, border=0)
        self.SetSizer(sizer)
        self.Layout()

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None)
        frame.Show(True)
        return True

if __name__ == "__main__":
    app = MyApp(False)
    app.MainLoop()
    

実行例を以下に示しました。

 

参考サイト

  1. wxWidgets/wxPython: This is the repository for "Classic"

 

ブログランキング・にほんブログ村へ
にほんブログ村

0 件のコメント: