Skip to content

Instantly share code, notes, and snippets.

@takedasoft
Created September 17, 2008 03:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takedasoft/11188 to your computer and use it in GitHub Desktop.
Save takedasoft/11188 to your computer and use it in GitHub Desktop.
package jp.takeda_soft.examples
import javax.swing.{JPanel,JFrame,JButton}
import java.awt.{Color,Graphics,Point,BorderLayout}
import java.awt.event.{ActionListener,ActionEvent}
/**
JButton+Actionの記述をDSL化する
*/
class SButton extends JButton{
def this(label:String,action: => Unit){
this()
this.setText(label)
this.addActionListener( new ActionListener{
def actionPerformed( e:ActionEvent ){
//特に意味はない。キャストってこれでいいのか?
val b:SButton = e.getSource.asInstanceOf[SButton]
//コードブロックの実行
action
}
}
)
}
}
/**
設定した関数の計算結果を描画するプロッター。
*/
class Plotter(var func:Int => Int) extends JPanel{
/**
Swing機構からコールされるフックメソッド。
全描画処理のエントリポイント。
*/
override def paintComponent(g:Graphics) {
//val g2:Graphics2D = g.asInstanceOf[Graphics2D] //他にcastの方法は?
prepareAxis(g)
def drawRed = draw(g)(Color.red)_ //curry(部分適用)
drawRed( this.points() )
}
/** Seq[Point]を線分で結ぶ */
def draw(g:Graphics)(color:Color)(points:Seq[Point]){
g.setColor( color )
for( i <- 0 to points.size - 2 ){
g.drawLine( onx(points( i ).getX),ony(points( i ).getY),
onx(points(i+1).getX),ony(points(i+1).getY) )
}
}
/** 関数のセッター */
def setFunc(func:Int=>Int){
this.func = func
}
/** 設定した関数による各点の計算結果 */
def points():Seq[Point] = {
val xs = -cx.toInt to cx.toInt //X軸の範囲
//val xs2 = xs.start until xs.end by xs.step+1 //読み飛ばしもできる
xs.map { x => new Point( x, func(x) ) }
}
/**中心点 or 軸最大値*/
var cx = 0
var cy = 0
/**実点 to 描画点変換*/
def onx(x:Double):Int = cx+x.toInt
def ony(y:Double):Int = cy-y.toInt
/** 軸設定と描画 */
def prepareAxis(g:Graphics){
cx = getWidth/2
cy = getHeight/2
g.setColor( Color.black )
g.drawLine( cx, 0 ,cx, cy*2 )
g.drawLine( 0, cy, cx*2, cy)
}
}
object Main extends JFrame {
//この関数定義をきれいに書く方法?
//無名関数のListって作れない?
val f0:Int=>Int = x => x
val f1:Int=>Int = x => x*x / 200
val f2:Int=>Int = x => x*x*x / 40000
val f3:Int=>Int = x => ( 100 * Math.sin( 3.14 * x / 180 ) ).toInt
val f4:Int=>Int = x => if( x >= 0 ) x else Math.abs(x)
val f5:Int=>Int = x => x match{ case 0 => Int.MaxValue case _ => 200/x }
val f6:Int=>Int = x => x % 20 match{ case 0 => x case _ => 0 }
val f7:Int=>Int = x => if( x > 0 ) f7(x-1) - 1
else if( x < 0 ) f7(x+1) + 1
else 0
/** 関数サンプル集 */
val functions:List[Int=>Int] = f0::f1::f2::f3::f4::f5::f6::f7::Nil
/** 現在表示中の関数インデックス */
var current:Int = 7
def main(args: Array[String]){
val plotter = new Plotter( functions(current) )
val button = new SButton("change function",
{
current = if( current == functions.size - 1 ) 0
else current + 1
plotter.setFunc(functions(current))
this.repaint()
}
)
//Swing
this.getContentPane().add(button,BorderLayout.SOUTH)
this.getContentPane().add(plotter)
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
this.setBounds(10, 10, 400, 400)
this.setTitle("function plotter")
this.show
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment