Java Key Bindings using Groovy Swing Builder - swing

I am trying to write in Groovy application, using "Calculator like" keys functionality. So I would like swing action to be invoked, when I:
press JButton
press corresponding keyboard key, no matther whether there is focus on JButton or not.
Probably the best solution is to use Java Key Bindings, as described here:
https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
Following combination of Groovy and Java seems to work well:
package packageSwingTest4
import groovy.swing.SwingBuilder
import javax.swing.*
import java.awt.*
import javax.swing.WindowConstants as WC
class SwingTest4 {
def static b
static void main(args) {
def swing = new SwingBuilder()
def f2Action = swing.action(name:"F2", shortDescription:"F2 button", accelerator:"F2") {
println "F2 pressed"
}
swing.edt {
def f=frame(title: 'Keborad Binding test', size:[400,300],defaultCloseOperation: JFrame.EXIT_ON_CLOSE, show: true) {
panel {
b = button(text: 'F2', actionPerformed:{println "FFFF2222 pressed"})
b.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F2"),"F2 pressed")
b.getActionMap().put("F2 pressed",f2Action)
}
}
}
}
}
But I do not like to combine Groovy/Java in this way, namely as I will:
- loose nice structure of Groovy code related to structure of GUI
- I have to define Actions separately and not "nicely" as in case of Groovy swing builder
Do you know about "cleaner" solution of my problem using pure Groovy/ SwingBuilder? I would prefer to use Key Bindings, not Key Listener..
Thank you for help and recommendations

Not 100% sure, but do you mean like this:
import groovy.swing.*
import javax.swing.*
def swing = new SwingBuilder()
def f2Action = swing.action(name:"F2 text", shortDescription:"F2 button", keyStroke:"F2") {
println "F2 pressed"
}
swing.edt {
frame(title: 'Keborad Binding test', size:[400,300],defaultCloseOperation: JFrame.HIDE_ON_CLOSE, show: true) {
panel {
button(text: 'F2',
actionPerformed:{ println "FFFF2222 pressed" }) {
action(f2Action)
}
}
}
}

def swing = new SwingBuilder()
def f2Action = swing.action(name:"F2 text", shortDescription:"F2 button", focus: JComponent.WHEN_IN_FOCUSED_WINDOW, keyStroke:"F2") {
println "F2 pressed"
}
def f3Action = swing.action(name:"F3 text", shortDescription:"F2 button", keyStroke:"F3") {
println "F3 pressed"
}
swing.edt {
frame(title: 'Keborad Binding test', size:[400,300],defaultCloseOperation: JFrame.HIDE_ON_CLOSE, show: true) {
panel {
button('F2') {action(f2Action)}
button('F3') {action(f3Action)}
}
}
}

Related

Unable to split the values in jsonobject in groovy

I'm new to groovy. I'm trying to split the values in json object in groovy but i cant seem to find a solution. Please find the sample code below
def inputFile = new File("C:\\graph.json")
def InputJSON = new JsonSlurper().parseFile(inputFile,'UTF-8')
InputJSON.each{println it}
def names = InputJSON.graph;
def name
for (int kk=0;kk<4;kk++)
{
name=names.JArray1[kk]
run.put(name.runid, name.rundetails);
println "test::"+name.runid+"--------------"+name.rundetails
}
graph.json
{
"graph": {
"JArray1": [
{
"runid": 1,
"rundetails":{
"01_Home":0.231,
"02_Login":0.561}
}
]
}
}
name.rundetails contains the below values
[01_Home:0.231, 02_Login:0.561]
I would like to split and add it as key and value in Hashmap like below format
Key:01_Home Value:0.231
Key:02_Login Value:0.561
How would i do that any advise on this would be helpful. Thanks in advance.
import groovy.json.*
def inputFile = new StringReader('''
{
"graph": {
"JArray1": [{
"runid": 1,
"rundetails": {
"01_Home": 0.231,
"02_Login": 0.561
}
}
]
}
}
''')
def json = new JsonSlurper().parse(inputFile)
json.graph.JArray1.each{run->
println "runid = ${run.runid}"
// at this point `run.rundetails` is a map like you want
println "details = ${run.rundetails}"
}
As I understand you need collection like:
[[Key:01_Home, Value:0.231], [Key:02_Login, Value:0.561]]
Then you may do:
println InputJSON.graph
.JArray1
.rundetails
.collectEntries{it}
.collect{[Key: it.key, Value: it.value]}

Grails 3 and Json: "Request method 'POST' not supported"

I'm porting a working webapp from Grails 2.3 to 3.0.1. When I post the Json string {"command":"ping"} to the server i get the following result:
{"timestamp":1429380750958,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/rps/request"}
Here's the controller:
import org.grails.web.json.JSONObject
class RequestController {
def jsonManagerService
def index() {
JSONObject json = request.JSON
if(!json){
render "{json or gtfo}"
return
}
render jsonManagerService.parseJson(json)
}
}
Here's the JsonManagerService:
import grails.transaction.Transactional
import org.grails.web.json.JSONObject
#Transactional
class JsonManagerService {
def parseJson(JSONObject o) {
switch (o.command){
case("ping"):
return '{"result":"pong"}'
break;
default:
return '{"result":"unknown command"}'
}
}
}
And here's my UrlMappings.groovy (it's the default one):
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?(.$format)?"{
constraints {
// apply constraints here
}
}
"/"(view:"/index")
"500"(view:'/error')
"404"(view:'/notFound')
}
}
It looks like a Spring related issue. All the search on this matter provided no results. Any idea?
Edit: thanks #dmahapatro, added UrlMappingsgroovy. Corrected the controller, dumb mistake, but result is still the same.

Right Click on a Button / Scala

I'm currently trying to code a minesweeper using scala, but I can't find the way to listen to a right click on a button.
I've already searched on the Internet the way to do it, but I definitely was not able to find it.
If anyone could help me out, I would be really grateful :)
Thanks,
Schnipp
(Note: Scala is a new language to me and I am not a Java user, so I am sorry if my questions sound dumb)
EDIT:
I am trying to find (or implement) a function 'ButtonClickedRight' that could listen to a right-click on a button.
like this
import scala.swing._
import scala._
import scala.swing.event._
object Right extends MainFrame with App {
title = ""
visible = true
val b = new button("")
listenTo(b)
reactions += {
case ButtonClicked(`b`) => *code*
case ButtonClickedRight(`b`) => *code*
}
}
EDIT 2 --
I would like to know if the user has clicked on the Button "1" or not. The problem I have is that this code prints "Mouse clicked at " + e.point+" type "+e.modifiers when I click on the label but not on the button.
object App extends SimpleSwingApplication {
lazy val ui = new GridPanel(2,1) {
contents += new Button("1")
contents += new Label("2")
listenTo(mouse.clicks)
reactions += {
case e: MouseClicked =>
println("Mouse clicked at " + e.point+" type "+e.modifiers)
}
}
def top = new MainFrame {
contents = ui
visible = true
preferredSize = new Dimension(500,500)
}
}
Button events are fired through a specific publisher .mouse.clicks.
import scala.swing._
import scala.swing.event._
object App extends SimpleSwingApplication {
lazy val ui = new GridPanel(2,1) {
val button = new Button("1")
contents += button
contents += new Label("2")
listenTo(button.mouse.clicks) // !
reactions += {
case evt # MouseClicked(`button`, pt, _, _, _) =>
val which = evt.peer.getButton
if (which > 1) {
println(s"Mouse clicked at (${pt.x}; ${pt.y}) - button: $which")
}
}
}
lazy val top = new MainFrame {
contents = ui
size = new Dimension(500,500)
}
}
Note that at least on Linux my right button has number 3 not 2. You could also use the triggersPopup flag, but then you must ensure to monitor both MousePressed and MouseReleased, as this flag is platform-dependent.
I think that you are on the right path, for my understanding of scala swings I think that the problem is that you are not attaching the listener correctly. For one I would assign the button to a value and call listenTo only on it:
val button = new Button("1")
listenTo(button)
Then, in the reactions, I would write the pattern checking in the event that it comes from the button (probably redundant if you only call listenTo passing the button) and that it has the correct button:
case ButtonClicked(b) if b == button && b.peer.getButton == MouseEvent.BUTTON_2 => ...
So the code you provided in your edit would become:
object App extends SimpleSwingApplication {
lazy val ui = new GridPanel(2,1) {
val button = new Button("1")
contents += button
contents += new Label("2")
listenTo(button)
reactions += {
case evt # MouseClicked(b, pt, _, _, _) if b == button && evt.peer.getButton == java.awt.event.MouseEvent.BUTTON2 =>
println(s"Mouse clicked at (${pt.x}; ${pt.y}) - button: ${evt.peer.getButton}")
}
}
def top = new MainFrame {
contents = ui
visible = true
preferredSize = new Dimension(500,500)
}
}
The following works for me:
new Button {
listenTo(mouse.clicks)
reactions += {
case MouseClicked(_, _, c, _, _) => handleClick(c == 0)
}
}
def handleClick(isLeftClick: Boolean): Unit = {
//
}

grails.converters.JSON except few properties

I am using grails-1.3.2 and hbase-0.2.4.
I have the following domain class:
class MyClass{
String val1
String val2
String val3
//----
}
class MyClassController{
def someAction = {
def myClass = new MyClass()
//----
String valAsJson = (myClass as JSON)
render valAsJson
}
}
My question is, is any short way render only part of properties(for example render all except val3 property) ?
You can do something like this :
def myClass = MyClass.get(1)
//include
render myClass.part(include:['val1', 'val2']) as JSON
//except
render job.part(except:['val2','val3']) as JSON
Bootstrap.groovy :
import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor as Events
class BootStrap {
def grailsApplication
def excludedProps = [Events.ONLOAD_EVENT,
Events.BEFORE_DELETE_EVENT, Events.AFTER_DELETE_EVENT,
Events.BEFORE_INSERT_EVENT, Events.AFTER_INSERT_EVENT,
Events.BEFORE_UPDATE_EVENT, Events.AFTER_UPDATE_EVENT]
def init = { servletContext ->
grailsApplication.domainClasses.each{ domainClass ->
domainClass.metaClass.part= { m ->
def map= [:]
if(m.'include'){
m.'include'.each{
map[it]= delegate."${it}"
}
}else if(m.'except'){
m.'except'.addAll excludedProps
def props= domainClass.persistentProperties.findAll {
!(it.name in m.'except')
}
props.each{
map[it.name]= delegate."${it.name}"
}
}
return map
}
}
}
def destroy = {
}
}
If you know how to create our own plugin, then just create one plugin for this, so that you can use it across all the grails applications.
If you want to only include specific properties all the time, you would really want to use the ObjectMarshaller interface. See this article for more details.
If you simply want to render an instance of MyClass as JSON, excluding certain properties, here's a solution that uses the JSONBuilder class provided by Grails
import grails.web.JSONBuilder
class MyClassController{
def someAction = {
def myClass = new MyClass()
def builder = new JSONBuilder.build {
myClass.properties.each {propName, propValue ->
// Properties excluded from the JSON
def excludes = ['class', 'metaClass', 'val3']
if (!excludes.contains(propName)) {
setProperty(propName, propValue)
}
}
render(text: builder.toString(), contentType: 'application/json')
}
}
Or, you could just create a map of the properties you wanted, then encode them as JSON
Map m = [ 'val1', 'val2' ].inject( [:] ) { map, val -> map."$val" = a."$val" ; map }
render m as JSON
To exclude properties, you would need to do something like this (UNTESTED)
def exclude = [ 'val3' ]
Map m = new DefaultGrailsDomainClass( MyClass.class ).properties.findAll {
!( it.name in exclude )
}.inject( [:] ) { map, val ->
map."$val.name" = a."$val.name" ; map
}
render m as JSON
The JSON Exclusion Marshaller Plugin
I needed to solve this problem recently. I went ahead and packaged the solution into a plugin that allows you to easily exclude class properties from the JSON converter's output. It is available on the Grails Plugin Portal.
After you install the plugin, you will have access to a method on the grails.converters.JSON class called excludeFor*().
More extensive documentation can be found here: How to use the JSON Exclusion Marshaller
But basically it can be used as such:
import grails.converters.JSON
def json, resultTeachersWillSee, resultOtherStudentsWillSee
// Given a TestStudent Domain Class
def student = new TestStudent([
firstName: "Tobias",
lastName: "Funke",
gradePointAverage: 3.6,
studentID: "FS-210-7312",
socialSecurityNumber: "555-55-5555"
])
student.save(flush: true)
// When
JSON.excludeForTeachers(TestStudent, ['socialSecurityNumber', 'id', 'class'])
JSON.use('excludeForTeachers') {
json = new JSON(student)
}
resultTeachersWillSee = json.toString()
// Then
assert resultTeachersWillSee == '{"firstName":"Tobias",
"gradePointAverage":3.6, "lastName":"Funke",
"studentID":"FS-210-7312"}'
// And When
JSON.excludeForOtherStudents(TestStudent, ['gradePointAverage', 'studentID',
'socialSecurityNumber', 'id', 'class'])
JSON.use('excludeForOtherStudents') {
json = new JSON(student)
}
resultOtherStudentsWillSee = json.toString()
// Then
assert resultOtherStudentsWillSee == '{"firstName":"Tobias",
"lastName":"Funke"}'
JSON.excludeForTeachers(...) creates a named object marshaller called "excludeForTeachers". The marshaller excludes three properties of the student object from the resulting JSON output. the 'socialSecurityNumber' property is explicitly defined in the class, while the 'id' property was added by GORM behind the scenes. In any case, teachers don't need to see any of those properties.
The plugin is serving me well... I hope others find it helpful too.

Interacting with actors in scala swing applications

I'm writing a small application in scala. The application processes simple log files. Because the processing takes some time, I've decided to let my application core extend Actor.
class Application extends Actor {
def react() {
loop {
react {
case Process(file) => // do something interesting with file...
}
}
}
}
The processing of a log file is triggered by clicking a button in the gui. The gui uses scala swing.
object Gui extends SimpleSwingApplication {
val application = new Application().start()
def top = new MainFrame {
val startButton = new Button
reactions += {
case ButtonClicked(`startButton`) => application ! Process(file)
}
}
}
Now, the application core needs to notify the gui about the current progress.
sender ! Progress(value) // whenever progress is made
I've solved this by creating a separate actor inside the gui. The actor is executed inside the edt thread. It listens to messages from the application core and updates the gui.
object Gui extends SimpleSwingApplication {
val actor = new Actor {
override val scheduler = new SchedulerAdapter {
def execute(fun: => Unit) { Swing.onEDT(fun) }
}
start()
def act() {
loop {
react {
case ForwardToApplication(message) => application ! message
case Progress(value) => progressBar.value = value
}
}
}
}
}
Since the application core needs to know about the sender of the message, I also use this actor to forward messages from the gui to the application core, making my actor the new sender.
reactions += {
case ButtonClicked(`startButton`) => actor ! ForwardToApplication(Process(file))
}
This code works just fine. My question: Is there a simpler way to do this? It whould be nice to simple use the reactions mechanism for my application messages:
reactions += {
case Progress(value) => progressBar.value = value
}
Any ideas how to achieve this?
I have extended on gerferras idea of making my application a swing.Publisher. The following class acts as intermediator between a swing.Reactor and an Actor.
import actors.Actor
import swing.Publisher
import swing.event.Event
import swing.Swing.onEDT
case class Send(event: Any)(implicit intermediator: Intermediator) {
intermediator ! this
}
case class Receive(event: Any) extends Event
case class Intermediator(application: Actor) extends Actor with Publisher {
start()
def act() {
loop {
react {
case Send(evt) => application ! evt
case evt => onEDT(publish(Receive(evt)))
}
}
}
}
Now my reactions can include both swing events and application events.
implicit val intermediator = Intermediator(application)
listenTo(intermediator, button)
reactions += {
case ButtonClicked(`button`) => Send(Process(file))
case Receive(Progress(value)) => progressBar.value = value
}
Note how the case class Send provides some syntactic sugar to easily create events and pass them to the intermediator.
Maybe this is simpler but don't know if it's better. Instead of making your application backend an actor, you can create an anonymous actor every time you need to process the file:
reactions += {
case ButtonClicked(`startButton`) => application.process(file, { v: Int => Swing.onEDT(progressBar.value = v) })
}
For the progress update part, you can pass a callback to the process method to be executed every time a new progress is made:
import scala.actors.Actor.actor
def process(f: File, progress: Int => Unit) {
actor {
// process file while notifying the progress using the callback
progress(n)
}
}
Alternatively (haven't tested) you could make your application a scala.swing.Publisher and, instead of using the callback, publish and event every time. So the code could be:
listenTo(startButton, application) //application is a Publisher
reactions += {
case ButtonClicked(`startButton`) => application.process(file)
case Progress(v) => progressBar.value = v
}
And in the application:
import scala.actors.Actor.actor
def process(f: File) {
actor {
// process file while notifying the progress using an scala.swing.event.Event
publish(Progess(n))
}
}