反应堆对gui按钮

时间:2018-06-09 11:21:51

标签: eclipse scala swing

我正在使用scala(2.12.6),OpenCV和Eclipse(Neon 3a)在图像上进行人脸检测。

我有一组检测到的面孔,我想通过使用一个小的gui应用程序来验证,在这个应用程序中可以进行图像的缩放和平移。对于实现,我选择将检测到的面集传递给主gui对象,该对象在trun中具有用于提取用户验证结果的公共方法(一旦验证完成):一组经过验证的自动检测和一组移除的检测和一组手动添加的检测。

最初检测到的面部显示为绿色矩形:

  • 如果用户点击绿色矩形:它将从集合中删除并以灰色显示
  • 如果用户点击灰色矩形:它会再次添加到集合中并以绿色显示

为了知道何时可以从gui对象中提取信息,需要暂停执行主程序,直到用户确认(通过按下按钮)完成验证。为了实现这种阻止,我让自己受到Return a value from a Scala + Swing app的启发,其中Luigi Plinge建议使用Reactor来收听确认按钮。

此设置正常工作,直到我开始单击图像以操作检测到的面部集或者我调整gui窗口的大小。在这些情况下,gui会选择确认按钮事件,但似乎Reactor对gui确认按钮感到聋。

下面我使用相同的实现策略添加了类似gui的代码(简化:仅提取最后一次用户点击的坐标),这与调整gui窗口大小或单击图像内部存在相同的问题。

此外,在启动应用程序后,我注意到一些非常奇怪的行为:

  • 点击图像中的0,1或2次(无缩放)&单击“确定”按钮:确定
  • 在图像中单击3次(无缩放)&单击确定按钮:NOK
  • 在同一个地方点击2x,在其他地方点击1x:有时候OK,有时候是NOK(?!?)
  • 1x缩小&点击图片中的2次&单击“确定”按钮:确定
  • 1x放大&点击图片中的2次&单击确定按钮:NOK

代码示例的图片:qm.png

import scala.concurrent.{ Promise, Await }
import scala.concurrent.duration.Duration
import scala.util.{ Try, Success, Failure }
import scala.swing.{ MainFrame, Label, ScrollPane, BoxPanel, Orientation, Button, Action, Swing, Reactor }
import scala.swing.event.{ ButtonClicked, WindowClosing, MouseClicked }
import java.io.File
import java.awt.image.BufferedImage
import java.awt.{ Point, BasicStroke, Color }
import javax.swing.ImageIcon
import javax.imageio.ImageIO

object BecomingDeaf02 {
    class gui( fh:File, x0:Int, y0:Int ) extends MainFrame {
        // public buttons: the calling function listens to these to determine whether the user is ready to continue
        val okButton = new Button { action = Action("OK") { println( "[gui] OK button pushed..." ) } }
        val abortButton = new Button { action = Action("Abort Validation") { println( "[gui] Abort button pushed..." ) } }

        // in reality these are lists of rectangles (detected objects), which can be modified by user-gui-interaction
        private var x = x0   
        private var y = y0

        def getX():Int = x
        def getY():Int = y

        private var sf = 1.0f  // scale factor

        private val imgIconLabel = new Label {
            def update():Unit = {
                val imgBase = ImageIO.read(fh)
                val g = imgBase.createGraphics()
                g.setStroke(new BasicStroke(3))
                g.setColor(Color.RED)
                g.drawOval(x, y, 3, 3)
                val imgIcon = new ImageIcon(imgBase)
                val w = math.round(imgIcon.getIconWidth*sf)
                val h = math.round(imgIcon.getIconHeight*sf)
                icon_=(new ImageIcon( imgIcon.getImage.getScaledInstance(w, h, java.awt.Image.SCALE_SMOOTH) ))
            }
            update()
        }

        private val scrPane = new ScrollPane { 
            def updateXY( p:Point ):Unit ={
                val xOffset = (this.size.getWidth.toInt - imgIconLabel.icon.getIconWidth)/2
                val yOffset = (this.size.getHeight.toInt - imgIconLabel.icon.getIconHeight)/2
                // to simplify the example code, scroll bars are not taken into account
                x = math.round( (p.x - xOffset)/sf )
                y = math.round( (p.y - yOffset)/sf )
            }
            contents_=(imgIconLabel)
            listenTo(mouse.clicks)
            reactions += { case MouseClicked(_,p,_,_,_) => { println(s"[gui.scrPane] clicked @ (${p.x},${p.y})"); updateXY(p); imgIconLabel.update() } }
        }

        private val boxP_flowControl = new BoxPanel( Orientation.Horizontal ) {
            contents += okButton
            contents += Swing.HStrut(10)
            contents += abortButton
            contents += Swing.HStrut(10)
            contents += Button("zoom +") { sf = sf*1.2f; imgIconLabel.update() }
            contents += Button("zoom -") { sf = sf*0.8f; imgIconLabel.update() }
        }

        // main gui component
        title = "Validation Window"
        contents = new BoxPanel( Orientation.Vertical ) {
            contents += scrPane
            contents += Swing.HStrut(10)
            contents += boxP_flowControl
        }
    }  // class gui

    def main(args: Array[String]) {
        val imgFP = """./resources/qm.png"""
        val ui = new gui( new File(imgFP), -1, -1 )
        ui.visible = true

        val promisedUserResponse = Promise[String]()

        var val1 = 0
        var val2 = 0

        new Reactor {
            listenTo(ui.okButton)
            listenTo(ui.abortButton)
            listenTo(ui)
            reactions += {
                case ButtonClicked(b) if b == ui.okButton => { 
                    println( s"[main] Reaction detected: user clicked OK button. Processing corresponding reaction block..." )
                    val1 = ui.getX()
                    val2 = ui.getY()
                    promisedUserResponse.success("Status: validated user selection extracted.")
                }
                case ButtonClicked(b) if b == ui.abortButton => promisedUserResponse.failure(new Exception( "User clicked Abort button...") )
                case e: WindowClosing => promisedUserResponse.failure(new Exception( "User closed window before chosing...") )
            }
        }

        // this blocks until the future (linked to promisedUserResponse) is complete
        val userResponse = Try( Await.result(promisedUserResponse.future, Duration.Inf) )
        ui.visible = false
        userResponse match {
            case Success(str) => println( s"[main] user clicked @ ($val1,$val2) $str" )
            case Failure(exc) => println( s"[main] Failed to complete validation: '${exc.getMessage}'" )
        }
    }
}

我在这里做错了什么?所有帮助都非常受欢迎!

0 个答案:

没有答案