#!/usr/bin/env ruby require "qte" require "qpe" include Qte include Qpe class SampleWindow < QMainWindow def initialize() super() setCaption(tr("サンプル")) @buf = QPixmap.new(640,480) # 描画バッファVGAサイズ @buf.fill(Qt::white) # 地の色 # 表示用ウィジェット @sv = QScrollView.new(self) # スクロールビュー setCentralWidget(@sv) @canvas = PaintWidget.new(@buf, @sv) @canvas.resize(@buf.width, @buf.height) # バッファと同じサイズに @sv.addChild(@canvas) # @sv上にキャンバスを置く draw # 描画 @canvas.repaint # 描画バッファの内容を@canvasにコピー # @buf.save("test.png", "PNG") # ファイル保存 catchEvent end # 描画バッファに対して描画 def draw tt = Turtle.new(@buf) tt.move(320,240) # Sample draw_triangle(tt) # draw_square(tt) # draw_circle(tt) # draw_whirl(tt, 73) # draw_tree(tt, 10) # draw_forest(tt, 5) # draw_lissajous(tt) end def draw_lissajous(tt) tt.draw(true) tt.move(0, 240) tt.forward(640) tt.draw(false) tt.move(320, 0) tt.right(90) tt.draw(true) tt.forward(480) tt.draw(false) t = 0 x = 100 * Math.sin(3 * t * Math::PI / 180) y = 100 * Math.cos(5 * t * Math::PI / 180) x = x + 320 y = 240 - y tt.move(x, y) tt.draw(true) while t < 360 x = 100 * Math.sin(3 * t * Math::PI / 180) y = 100 * Math.cos(5 * t * Math::PI / 180) x = x + 320 y = 240 - y tt.move(x, y) t = t + 2 end end def draw_forest(tt, n) tt.move(640,350) tt.draw(true) tt.left(180) m = n - 1 draw_forest_s(tt, 0, 550, m) end def draw_forest_s(tt, c, l, m) if c > m tt.forward(l) return end draw_forest_s(tt, c + 1, l * 0.6, m) tt.right(85) draw_forest_s(tt, c + 1, l / 3, m) tt.left(170) draw_forest_s(tt, c + 1, l / 3, m) tt.right(85) draw_forest_s(tt, c + 1, l * 0.35, m) end def draw_tree(tt, n) tt.move(320, 400) tt.draw(true) tt.left(90) l = 30 a = 30 draw_tree_s(tt, l, a, n) end def draw_tree_s(tt, l, a, n) return if n == 0 tt.left(a) tt.forward( 2 * l) draw_tree_s(tt, 0.9 * l, a, n - 1) tt.back(l * 2) tt.right(a * 2) tt.forward(l) draw_tree_s(tt, 0.9 * l, a, n - 1) tt.back(l) tt.left(a) end def draw_whirl(tt, a) tt.draw(true) l = 2 draw_whirl_s(tt, l, a) end def draw_whirl_s(tt, l, a) return if l > 300 tt.forward(l) tt.right(a) draw_whirl_s(tt, l + 1, a) end def draw_circle(tt) tt.draw(true) 36.times do 360.times do # 円を描く tt.forward(2) tt.right(1) end tt.left(10) end end def draw_square(tt) tt.draw(true) 36.times do # 36回リピート 4.times do # 四角形を描画 tt.forward(200) # 200進む tt.right(90) # 右へ90度回転 end tt.left(10) end end def draw_triangle(tt) tt.draw(true) 3.times do tt.forward(200) tt.left(120) end end end class Turtle Degree = Math::PI / 180 def initialize(canvas) @canvas = canvas @pen = QPen.new( Qt::blue, 1) # 青、幅1 @paint = QPainter.new @x = @y = 0 # 現在の座標 @px = @py = 0 # ひとつ前の座標 @dir = 0 # 向き @draw = false # trueなら描画 end def draw(bool) # 描画する/しない @draw = bool end def turn(deg) # 向きを絶対指定 @dir = deg if @dir >= 0 @dir -= 360 while @dir > 359 else @dir += 360 while @dir < 0 end end def left(deg) # 向きを左へ turn(@dir + deg) end def right(deg) # 向きを右へ turn(@dir - deg) end def move(x,y) # 絶対座標で移動 @px = @x @py = @y @x = x @y = y if @draw @paint.begin(@canvas) @paint.setPen(@pen) @paint.drawLine(int(@px), int(@py), int(@x), int(@y)) @paint.end end end def forward(n) # 前進 line(n, @dir) end def back(n) # 後退 dir = @dir + 180 dir -= 360 if dir > 359 line(n, dir) end def line(n, dir) dx, dy = delta(n, dir) @px = @x @py = @y @x += dx @y += dy if @draw @paint.begin(@canvas) @paint.setPen(@pen) @paint.drawLine(int(@px), int(@py), int(@x), int(@y)) @paint.end end end def delta(n, dir) # 移動のx.y成分を返す dx = n * Math.cos(dir * Degree) dy = -1 * n * Math.sin(dir * Degree) return dx,dy end def int(n) # 数値を四捨五入して整数化 if n >= 0 (n + 0.5).to_i else (n - 0.5).to_i end end end class PaintWidget < QWidget def initialize(buf, parent) super(parent) @buf = buf catchEvent end # repaintで呼ばれる def paintEvent(p) bitBlt(self, 0, 0, @buf) end end $defaultCodec = QTextCodec.codecForName("utf8") app = QPEApplication.new([$0]+ARGV) app.setDefaultCodec($defaultCodec) QApplication.setFont(QFont.new("lcfont",18)) app.showMainWidget(SampleWindow.new) app.exec