2011-04-23 4 views
4

scala.swing.Component으로 믹스 할 수있는 스칼라 특성을 찾고 있는데,이를 통해 마우스 입력을 사용하여 해당 구성 요소의 위치를 ​​조정하고 크기를 조정할 수 있습니다. 나는이 느낌 enter image description herescala swing : draggable/resizable component trait

은 매우 일반적인 작업, 그리고 거기에 몇 가지 특성이 있어야한다 :

이상적으로는 구성 요소가 크기를 조정할 수 있습니다 사용자에게 표시하는 "핸들"로 작은 상자를 추가 그것을 지원합니다.

+0

에서, 사용자의 위치 및 크기를 할 수있는 패널에있을 필요가 있지만 직접 구성 요소의 크기와 위치에 구성 요소는 패널 유형에 따라 다릅니다. – gerferra

답변

5

저는 현재 프로젝트에서 이것을 사용하고 있습니다. 아마도 자신의 라이브러리로 Vector 라이브러리를 대체하고 implicid def를 추가해야 할 것입니다. 스윙의 포인트/치수를 사용하십시오. 구성 요소는 NullPanel 같은 나는이 몇 가지 특별한 패널/레이아웃에 의해 구현 될 수 있다고 생각 http://dgronau.wordpress.com/2010/08/28/eine-frage-des-layouts/

trait Movable extends Component{ 
    var dragstart:Vec2i = null 
    listenTo(mouse.clicks, mouse.moves) 
    reactions += { 
     case e:MouseDragged => 
      if(dragstart != null) 
       peer.setLocation(location - dragstart + e.point) 
     case e:MousePressed => 
      this match { 
       case component:Resizable => 
        if(component.resizestart == null) 
         dragstart = e.point 
       case _ => 
        dragstart = e.point 

      } 
     case e:MouseReleased => 
      dragstart = null  
    } 
} 

trait Resizable extends Component{ 
    var resizestart:Vec2i = null 
    var oldsize = Vec2i(0) 
    def resized(delta:Vec2i) {} 
    listenTo(mouse.clicks, mouse.moves) 
    reactions += { 
     case e:MouseDragged => 
      if(resizestart != null){ 
       val delta = e.point - resizestart 
       peer.setSize(max(oldsize + delta, minimumSize)) 

       oldsize += delta 
       resizestart += delta 

       resized(delta) 
       revalidate 
      } 
     case e:MousePressed => 
      if(size.width - e.point.x < 15 
      && size.height - e.point.y < 15){ 
       resizestart = e.point 
       oldsize = size 

       this match { 
        case component:Movable => 
         component.dragstart = null 
        case _ => 
       } 
      } 
     case e:MouseReleased => 
      resizestart = null 
    } 
} 
+0

이것은 매우 유용합니다. 감사합니다! – evilcandybag

0

내가 아는 유일한 구성 요소는 드래그 가능이며 크기 조정 가능은 JDesktop의 InternalFrame입니다.

import swing._ 
import event._ 

import javax.swing.{UIManager,JComponent} 
import javax.swing.KeyStroke.getKeyStroke 
import java.awt.{Graphics2D,Graphics} 

object InternalFrameDemo extends SimpleSwingApplication{ 
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName) 

    val top = new MainFrame{ 
     title = "InternalFrameDemo" 
     preferredSize = new Dimension(640,480) 
     val desktop = new javax.swing.JDesktopPane 

     val jc = new JComponent{ 
      override def paint(g:Graphics){ 
       import g._ 
       drawLine(0,0,20,20) 
       drawLine(0,20,20,0) 
       println("yay draw") 
      } 

      setVisible(true) 
     } 

     desktop add jc 

     contents = Component.wrap(desktop) 

     menuBar = new MenuBar{ 
      contents += new Menu("Document"){ 
       mnemonic = Key.D 

       contents += new MenuItem("New"){ 
        mnemonic = Key.N 
        action = new Action("new"){ 
         def apply = createFrame 
         accelerator = Some(getKeyStroke("alt N")) 
        } 
       } 

       contents += new MenuItem("Quit"){ 
        mnemonic = Key.Q 
        action = new Action("quit"){ 
         def apply(){ 
          quit() 
         } 
         accelerator = Some(getKeyStroke("alt Q")) 
        } 
       } 
      } 
     } 

     def createFrame{ 
      val newFrame = MyInternalFrame() 
      newFrame setVisible true 
      desktop add newFrame 
      newFrame setSelected true 

     } 
    } 
} 

import javax.swing.{JDesktopPane,JInternalFrame} 
import collection.mutable.ArrayBuffer 

object MyInternalFrame{ 
    var openFrameCount = 0; 
    val xOffset, yOffset = 30; 

    def apply() = { 
     openFrameCount += 1 
     val jframe = new javax.swing.JInternalFrame("Document #" + openFrameCount,true,true,true,true) 

     jframe.setSize(300,300) 
     jframe.setLocation(xOffset*openFrameCount,yOffset*openFrameCount) 

     jframe //Component.wrap(jframe) 
    } 
} 

하지만 JInternalFrame의과에서 JDesktop 모두 스칼라 스윙 패키지에 통합 수동으로 포장 할 필요가있다 예를 들면 다음과 같습니다.