Is there anyway to avoid the stateChange event being fired more than one time when the toggleButton is clicked? Or am I using the wrong event handler? It gets called 5 times for every toggle.
#!/usr/bin/env groovy
import groovy.swing.SwingBuilder
import static javax.swing.JFrame.EXIT_ON_CLOSE
def swing = new SwingBuilder()
swing.edt {
lookAndFeel 'nimbus'
frame(title : "Throttle",
pack : true,
show : true,
defaultCloseOperation: EXIT_ON_CLOSE,
id : "frame" ) {
boxLayout()
toggleButton(text: 'fl',
selected : false,
rolloverEnabled: false,
toolTipText : 'f1',
stateChanged : { e ->
println e.source
})
}
}
swing.doLater { frame.size = [128, 320] }
I switched to from stateChanged to actionPerformed then it worked as what I expected. Not sure why I used stateChanged in the first place!
Related
I am looking for a way to change the text of a button in Groovy when it is clicked. I can't find any documentation on it. I'm using Swingbuilder to lay the buttons out (it is for a Battleship game). I'm fairly new at using this lang.
What I'm using is:
import groovy.swing.SwingBuilder
import javax.swing.*
import java.awt.BorderLayout
class FrontEnd {
FrontEnd() {
def builder = new SwingBuilder()
builder.edt {
frame(title: 'Battleship', size: [500, 350], show: true, locationRelativeTo: null, resizable: false,
defaultCloseOperation: WindowConstants.EXIT_ON_CLOSE) {
borderLayout(vgap: 5)
panel(constraints: BorderLayout.CENTER) {
tableLayout {
tr {...
}
tr {
td {
label '1'
}
td {
button(id: 'a1', text: ' ', actionPerformed:)
}
td {
button(id: 'b1', text: ' ', actionPerformed:)
}
I don't know if it is even possible with this setup, so if there is another way I'd be glad to know about it.
Thank you.
The following example assigns a button to the variable myButton which is then used for reference. Clicking on the button will set the text to hello 0, hello 1, etc:
import groovy.swing.SwingBuilder
import groovy.beans.Bindable
import static javax.swing.JFrame.EXIT_ON_CLOSE
import java.awt.*
class Example {
static def count = 0
static void main(String[] args) {
def swingBuilder = new SwingBuilder()
swingBuilder.edt {
frame(title: 'Example', size: [140, 80],
show: true, locationRelativeTo: null,
defaultCloseOperation: EXIT_ON_CLOSE) {
borderLayout(vgap: 5)
panel(constraints: BorderLayout.SOUTH) {
myButton = button text: 'Save', actionPerformed: {
myButton.setText("hello ${count++}")
}
}
}
}
}
}
I have a simple Object hierarchy : RESTError with 2 attributes (httpCode and message), and 4 subclasses of it. One of the subclasses, RESTBusinessError has two additional fields.
I've simplified my code here below, but a RESTError variable (which is actually a RESTBusinessError) is used within a switch statement. Whenever I try to access the fields of the subclass, I've a EXC_BAD_ACCESS. Any idea ? this looks obvious, and in the debug area, I can see that all my variables have the expected values.
I have this issue ONLY in case RESTError conforms to the protocol ErrorType.
Any Idea ?
var tmpError:RESTError;
tmpError=RESTBusinessError(httpCode: 422, message: "error", businessCode: "003", businessMessage: "error");
switch tmpError {
case is RESTAuthorisationError:print("AUTH Error");
case let bError as RESTBusinessError:
let s1=bError.httpCode;
let s2=bError.message;
let s3=bError.businessCode; // <- This systematically fails.
let s4=bError.businessMessage;
print("OK \(s1) \(s2) \(s3) \(s4)");
default: print("default");
}
Object Hierarchy is here below :
public class RESTError : ErrorType{
var httpCode:Int
var message:String
init(httpCode:Int,message:String) {
self.httpCode=httpCode;
self.message=message;
}
}
class RESTAuthorisationError : RESTError {}
class RESTServerError : RESTError {}
class RESTOtherError : RESTError {}
public class RESTBusinessError : RESTError {
var businessCode:String
var businessMessage:String
init(httpCode:Int,message:String, businessCode:String, businessMessage:String) {
self.businessCode=businessCode;
self.businessMessage=businessMessage;
super.init(httpCode: httpCode, message: message);
}
}
check this example
import Foundation
func f() {
let queue = dispatch_queue_create("a", DISPATCH_QUEUE_CONCURRENT)
var i: Int! = 0
dispatch_async(queue) {
i = nil
}
usleep(200000)
print(i) // this is wrong
}
f() // debugger will stop here !!!!
import groovy.beans.Bindable;
import groovy.swing.SwingBuilder
import java.awt.BorderLayout
import javax.swing.JFrame
#Bindable def people = [[name:"Mary", age:18],
[name:"Tom", age:25]]
def swingBuilder = new SwingBuilder()
swingBuilder.edt { // edt method makes sure UI is build on Event Dispatch Thread.
lookAndFeel 'system' // Simple change in look and feel.
frame( title: 'Display a table',
size: [400,300],
show: true,
locationRelativeTo: null,
defaultCloseOperation: JFrame.EXIT_ON_CLOSE)
{
menuBar() {
menu(text: "File", mnemonic: 'F'){
menuItem(text: "Add",
actionPerformed: {
people << [name:"Harry", age:17]
println people
}
)}
}
panel(layout: new BorderLayout()) {
scrollPane(constraints: BorderLayout.CENTER) {
table() {
def listTeacher
tableModel(list: people) {
propertyColumn(header: 'Name', propertyName: 'name')
propertyColumn(header: 'Age', propertyName: 'age')
}
}
}
}
}
}
When click "Add" one entry is added to the list people but the JTable is not updated. How can I fix it?
You can make it an ObservableList, and then refresh the table model when the list changes in some way:
import groovy.beans.Bindable;
import groovy.swing.SwingBuilder
import java.awt.BorderLayout
import javax.swing.JFrame
import java.beans.PropertyChangeListener
#Bindable ObservableList people = [ [name:"Mary", age:18],
[name:"Tom", age:25] ]
def swingBuilder = new SwingBuilder()
swingBuilder.edt { // edt method makes sure UI is build on Event Dispatch Thread.
lookAndFeel 'system' // Simple change in look and feel.
frame( title: 'Display a table',
size: [400,300],
show: true,
locationRelativeTo: null,
defaultCloseOperation: JFrame.HIDE_ON_CLOSE) {
menuBar() {
menu(text: "File", mnemonic: 'F'){
menuItem(text: "Add", actionPerformed: {
people << [name:"Harry", age:17]
println people
}
) }
}
panel(layout: new BorderLayout()) {
scrollPane(constraints: BorderLayout.CENTER) {
table {
def listTeacher
tableModel( id:'model', list: people) { m ->
propertyColumn(header: 'Name', propertyName: 'name')
propertyColumn(header: 'Age', propertyName: 'age')
}
}
}
people.addPropertyChangeListener( { e -> model.fireTableDataChanged() } as PropertyChangeListener )
}
}
}
Why does this code fail ?
I want to change the color of one panel in a series of several panels, dynamically constructed (total number of panels not known beforehand).
For some reason, this code works when referencing the name of a particular panel (for example 'panel2'), but not when I refer to it dynamically ('panelID').
import groovy.swing.SwingBuilder
import javax.swing.WindowConstants as WC
import javax.swing.JOptionPane
import javax.swing.BoxLayout as BXL
swing = new SwingBuilder()
frame = swing.frame(title:'test',
defaultCloseOperation:WC.DISPOSE_ON_CLOSE) {
panel(id:'mainPanel'){
def panelID
(1..6).each {
panelID = 'panel' + it
panel(alignmentX: 0f, id: panelID , opaque:true ,background : java.awt.Color.GREEN){
label('description')
textField(id: "description$it", text: panelID, columns: 70 )
button(id: "button$panelID", text: panelID, actionPerformed : {
panelID.background = java.awt.Color.RED
panelID.repaint()
})
}
}
boxLayout(axis: BXL.Y_AXIS)
panel(id:'secondPanel' , alignmentX: 0f){
button('Quit', actionPerformed:{
dispose()
})
}
}
}
frame.pack()
frame.show()
To get the element based on it's ID, you need to access the ID as a parameter of the SwingBuilder, like so:
import groovy.swing.SwingBuilder
import javax.swing.WindowConstants as WC
import javax.swing.JOptionPane
import javax.swing.BoxLayout as BXL
swing = new SwingBuilder()
frame = swing.frame(title:'test', pack:true, visible:true, defaultCloseOperation:WC.DISPOSE_ON_CLOSE) {
panel(id:'mainPanel'){
(1..6).each { num ->
def panelID = "panel$num"
def pane = panel( alignmentX:0f, id:panelID, background:java.awt.Color.GREEN ) {
label('description')
textField(id: "description$num", text:panelID, columns: 70 )
button(id: "buttonpanel$num", text:panelID, actionPerformed : {
swing."$panelID".background = java.awt.Color.RED
})
}
}
boxLayout(axis: BXL.Y_AXIS)
panel(id:'secondPanel' , alignmentX: 0f){
button('Quit', actionPerformed:{
frame.visible = false
})
}
}
}
I have run the following code in this page RsyntaxTextArea using Java and i run the program exactly the way that is been mentioned in this site.And i'm getting the output as intended. But i have tried to modify this java code to Groovy code, something like:
import groovy.swing.SwingBuilder
import javax.swing.*
import java.awt.*
swing = new SwingBuilder()
frame = swing.frame(title : "test", defaultCloseOperation:JFrame.EXIT_ON_CLOSE, pack:true, show : true, size :[100,100])
{
panel
{
RSyntaxTextArea textArea = new RSyntaxTextArea();
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
}
}
And when i try to run this script as follows:
groovyc -classpath rsyntaxtextarea.jar TextEditorDemo.groovy
I get the errors stating that:
groovy: 9: unable to resolve class RSyntaxTextArea
# line 9, column 19.
RSyntaxTextArea textArea = new RSyntaxTextArea();
^
/home/anto/Groovy/Rsyntax/ST.groovy: 9: unable to resolve class RSyntaxTextArea
# line 9, column 30.
RSyntaxTextArea textArea = new RSyntaxTextArea();
^
/home/anto/Groovy/Rsyntax/ST.groovy: 10: unable to resolve class RSyntaxTextArea
# line 10, column 7.
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
I guess i have made wrong in running the program. How i do i run the program in this case by defining the classpath too.
It doesn't look like you're importing the package for RSyntaxTextArea. Have you tried adding the following imports to your program?
import org.fife.ui.rtextarea.*;
import org.fife.ui.rsyntaxtextarea.*;
This code should do what you want... You needed to add the RSyntaxTextArea into the view (using the widget method)
You also needed to add it into a JScrollPane, so that it scrolls nicely when full.
import groovy.swing.SwingBuilder
import java.awt.BorderLayout as BL
import static javax.swing.JFrame.EXIT_ON_CLOSE
import org.fife.ui.rsyntaxtextarea.*
RSyntaxTextArea textArea = new RSyntaxTextArea()
textArea.syntaxEditingStyle = SyntaxConstants.SYNTAX_STYLE_JAVA
swing = new SwingBuilder()
frame = swing.frame(title:"test", defaultCloseOperation:EXIT_ON_CLOSE, size:[600,400], show:true ) {
borderLayout()
panel( constraints:BL.CENTER ) {
borderLayout()
scrollPane( constraints:BL.CENTER ) {
widget textArea
}
}
}
edit
Without using widget, your code would need to look something like this:
import groovy.swing.SwingBuilder
import java.awt.BorderLayout as BL
import static javax.swing.JFrame.EXIT_ON_CLOSE
import org.fife.ui.rsyntaxtextarea.*
RSyntaxTextArea textArea = new RSyntaxTextArea()
textArea.syntaxEditingStyle = SyntaxConstants.SYNTAX_STYLE_JAVA
swing = new SwingBuilder()
frame = swing.frame(title:"test", defaultCloseOperation:EXIT_ON_CLOSE, size:[600,400], show:true ) {
borderLayout()
panel( constraints:BL.CENTER ) {
borderLayout()
sp = scrollPane( constraints:BL.CENTER )
sp.viewport.add textArea
}
}