I'm building a Swing application in Java and I want the colours to be consistent. So I could do something like:
public class Colours {
public static final String BACKGROUND = "#D9DADE";
}
But then I thought maybe an enum would be better, so I did this:
public enum ColourStyles {
BACKGROUND("#D9DADE");
private String colourValue;
private ColourStyles(String value) {
colourValue = value;
}
public String getColourValue() {
return colourValue;
}
};
But then that made the String now a ColourStyle type and I can't decode it using Color.decode(BACKGROUND).
Is there any better way of doing this completely, like a properties file? I've done Wicket but never come across the same sort of structure for labels/colours in Swing.
Thanks!
The 2 options are good, but i'd prefer a 3rd way and it's using a property file. So you don't have to recompile your application if you want to change.
1st)
public final class Colours {
private Colours(){}
public static final BACKGROUND = "#D9DADE";
}
.
2nd) It's ok, but you can add a method to the enum to return the color.
public enum ColourStyles {
BACKGROUND("#D9DADE");
private String colourValue;
private ColourStyles(String value) {
colourValue = value;
}
public String getColourValue() {
return colourValue;
}
public Color getColour(){
return Color.decode(colourValue);
}
}
And 3rd) create a file for example lookAndFeel.properties
colour.background=#D9DADE
Make a class that could be a singleton to load the properties file and you can add a util method to return the colour like in the enum, the good thing of this is that you can change the values wihout compiling again your application.
4th) If you are using a customizable look&feel you can set that properties using UIManager.put(); to set properties for all components. Here is an example of properties for Nimbus L&F Nimbus defaults
Related
I have a Java application (an interpreter written in antlr4 to be precise) with numerous options in the code I would like to be [power] user configurable. Something like a config.properties file. Most of them are Boolean flags, if set, do this, else do that.
Currently, I have one class per flag, and the classes are scattered through-out the code, mostly in the same package where the implementation needs it. And, you can say:
import my.package.DoThis;
if (DoThis.isSet()) {
doThis();
} else {
doThat();
}
where the code for DoThis is something like
package my.package;
public class DoThis {
private static Boolean doThis = true; // the default
public static Boolean isSet() { return doThis; }
public static void set() { doThis = true; }
public static void clear() { doThis = false; }
}
And, there is a centralized part of the code that main calls, that initializes these options.
public void setup() {
DoThis.set();
DoAnother.clear();
if (cmd.option.debug()) { DoThird.set(); } else { DoThird.clear(): }
}
But, as I said, I'd like to clean the code up and use a configuration file that I can keep in the resources or a power user can override. A properties file or maybe a json file would seem like the right user interface.
However, properties read strings, do I check for yes/no, true/false? to set the flag. Or is there something better to do?
Should I also make all the options part of one class and perhaps store them in a map? What will make adding configuration options easiest?
Most importantly, I'd like to follow some form of Java best practices for doing so. I don't want to be that person who can write FORTRAN in any language. I want the code to look like what other Java programmers would naturally write. I'm pretty certain what I have now is not it.
I am not aware of a universally-accepted "best" approach for this. My preference would be not to have a separate class per flag, but rather to rather to centralise all the flags within a single class called, say, Config. It's public API might be something like the following (assuming the flags are called x, y and z):
public class Config {
private boolean x;
private boolean y;
private boolean z;
void setX(boolean value) { x = value; }
boolean getX() { return x; }
void setY(boolean value) { y = value; }
boolean getY() { return y; }
void setZ(boolean value) { z = value; }
boolean getZ() { return z; }
}
If you don't want to have to pass an instance of Config as a parameter to lots of different operations/constructors in your application, then you could create a singleton instance of Config.
I don't think my suggestion above would be too controversial among programmers. What is more likely to attract controversy is opinions about the "best" way to initialise the Config object. Some people might suggest that the Spring Framework should be used to inject values obtained from an XML file. Some other people might suggest that your setup() operation should read values from a configuration file in whatever happens to be your favourite syntax (properties, JSON, XML or whatever) and possibly allowing command-line options to override values specified in the configuration file
I have a question about implementing a Swing control which uses a custom class as one of its properties. My goal is to use this control within the netbeans IDE and configure it in design-time like any other component. I already implemented a custom property editor for my ConnectionInfo object which works fine.
However - when I configure my IntLEDs ConnectionInfo property in Netbeans and save it, I can see, in the generated code by Netbeans, that it had troubles to init my ConnectionInfo class.
This is actually what the Netbeans IDE generated:
intLED1.setConnection(???);
So I guess that Netbeans doesn't know how to instantiate my ConnectionInfo class.
But how to tell Netbeans how to do it? :)
This code is basicly a stripped version of my component
public class IntLED extends JPanel {
private ConnectionInfo connection = new ConnectionInfo("", 11159, "", "", Variable.VARIABLE_TYPE.INT);
public IntLED() {
initComponents();
PropertyEditorManager.registerEditor(ConnectionInfo.class, PviCpuPropertyEditor.class);
}
public ConnectionInfo getConnection() {
return connection;
}
public void setConnection(ConnectionInfo connection) {
this.connection = connection;
}
}
Here the ConnectionInfo code. Just some members and Getters/Setters.
public class ConnectionInfo {
private String pviHost = "";
private int pviPort = 11159;
private String pviTask = "";
private String pviVarname = "";
private Variable.VARIABLE_TYPE pviType;
public ConnectionInfo() {
}
public ConnectionInfo(String pviHost, int pviPort, String pviTask, String pviVarname, Variable.VARIABLE_TYPE type) {
this.pviHost = pviHost;
this.pviPort = pviPort;
this.pviTask = pviTask;
this.pviVarname = pviVarname;
this.pviType = type;
}
public String getPviHost() {
return pviHost;
}
public void setPviHost(String pviHost) {
this.pviHost = pviHost;
}
public int getPviPort() {
return pviPort;
}
public void setPviPort(int pviPort) {
this.pviPort = pviPort;
}
public String getPviTask() {
return pviTask;
}
public void setPviTask(String pviTask) {
this.pviTask = pviTask;
}
public String getPviVarname() {
return pviVarname;
}
public void setPviVarname(String pviVarname) {
this.pviVarname = pviVarname;
}
public Variable.VARIABLE_TYPE getPviType() {
return pviType;
}
public void setPviVarname(Variable.VARIABLE_TYPE pviType) {
this.pviType = pviType;
}
}
I also tried to put the members of the ConnectionInfo-Class directly into my IntLED-Class which works fine! But I really need to let the user configure those Members directly in one editor since the editor also provides a tester to test those settings et cetera.
I hope someone can point me to the right direction :)
Thank you very much in advance!
I found the 'missing link' between my Custom Property and the Matisse Code generator!
In my Custom Property Editor (which extends PropertyEditorSupport) I did not override the method getJavaInitializationString().
Apperently when this method is not overwritten, it returns '???' which is exactly what I saw.
Here is how I fixed it:
#Override
public String getJavaInitializationString() {
return String.format("new ConnectionInfo(\"%s\", %d, \"%s\", \"%s\", Variable.VariableType.BOOLEAN)", getValue().getHost(), getValue().getPort(), getValue().getTask(), getValue().getVarname());
}
Surely there should be some Nullpointer checks and so on. But this is basicly how to tell Matisse how to init your Custom Class!
I hope I'm understanding your question, but as I see it you want to be able to add your custom JPanel (IntLED) as a component that you can use in the GUI Editor (Matisse) like every other component?
There is an answer here (https://stackoverflow.com/a/18409887/963076) that explains how to add custom components to the GUI Editor.
EDIT:
Ok, I see. To change the code that Netbeans is generating, you should look for that parameter in the Properties dialog for that component. Right click the component and click "Properties." Then find connection in the list of properties. connection should appear because Netbeans looks for all get() and set() methods and adds them as properties that you can edit. Once you find connection press the ... button to the right. It'll bring up a dialog allowing you to set that component's property. You'll probably need to select "custom code".
(In the pictures below, I used the columnModel property as an illustration).
From the screen below, select "custom code".
i would like to change the background-color property of a gwt cell column. The problem is that this color can change at each render of the cell (background color depends on the value of the cell).
I have already tried to override the cell style names method of TextColumn as follow :
#Override
public String getCellStyleNames(final Context context, final Object data) {
if (my_condition) return "a custom style";
else return "default style"; // or null...
}
Well as you certainly know its only add a class name to the property so i can't use it to set a color "dynamically" due to the static css file definition.
Thx for ur help !
You can use CellFormatter, if you are using Grid. E.g.
grid.getCellFormatter().setStyleName(row, column, "dynamicStyleName");
For dynamic update of 'color' property I would recommend to extend TextCell (and pass it to 'TextColumn' constructor). Something like that:
public class CustomCell extends TextCell<String> {
interface Template extends SafeHtmlTemplates {
#Template("<div style=\"color:{0}\">{1}</div>")
SafeHtml div(String url, String text);
}
private static Template template;
public CustomCell () {
if (template == null) {
template = GWT.create(Template.class);
}
}
#Override
public void render(Context context, String value, SafeHtmlBuilder sb) {
String color = "red";
if (value != null) {
// The template will sanitize the URI.
sb.append(template.div(color, value));
}
}
}
public class CustomColumn<T> extends TextColumn<T> {
public CustomColumn() {
super(new CustomCell());
}
}
Since you didn't give details of the component you are using, I'll give a generic suggestion for trying to find out which properties you might need to play with.
I use eclipse and suggest using the GWT Designer to help you with POC stuff. It helps me get an idea of which properties I might want to play with:
GWT Designer Refererence:
https://developers.google.com/web-toolkit/tools/download-gwtdesigner
Example of how to use GWT Designer:
https://developers.google.com/web-toolkit/tools/gwtdesigner/tutorials/loginmanager
I found many simple solutions to this (such as Intent.putExtra(String, String) and Bundle.putString(String, String)), but this is not helpful for my situation.
I have a class called MyMP3 which contains non-primitive types. I need to pass the following for MyMP3...
private AudioFile audioFile;
private Tag tag;
private int index;
private boolean saved, startedWithLyrics;
private String id3lyrics;
AudioFile and Tag are both classes that I imported from a .jar file. How can I go about passing these to another Activity via Intents? I tried messing with implementing Parcelable for my "MyMP3" class, but I am not sure how to correctly use these methods when not passing primitive types.
Could you help me out and look at my code below and try to tell me how to correctly use Parcelable with a custom class like mine? How do I set the Parcel in the writeToParcel function and how do I correctly retrieve the class in another Activity?
Below is my code (the part that is important, at least). I've been trying different things for a couple of days now, but I cannot get it to work. Please help me out!
public class MyMP3 extends AudioFile implements Parcelable
{
private AudioFile audioFile;
private Tag tag;
private int index;
private boolean saved, startedWithLyrics;
private String id3lyrics;
public MyMP3(File f, int index)
{
this.audioFile = AudioFileIO.read(f);
this.tag = this.audioFile.getTag();
this.index = index;
this.saved = false;
this.id3lyrics = getLyrics();
}
#Override
public int describeContents()
{
return 0;
}
#Override
public void writeToParcel(Parcel out, int flats)
{
/* This method does not work, but I do not know how else to implement it */
Object objects[] = {this.audioFile, this.tag, this.index, this.saved, this.startedWithLyrics, this.id3lyrics};
out.writeArray(objects);
}
public static final Parcelable.Creator<MyMP3> CREATOR = new Parcelable.Creator<MyMP3>()
{
public MyMP3 createFromParcel(Parcel in)
{
/* Taken from the Android Developer website */
return new MyMP3(in);
}
public MyMP3[] newArray(int size)
{
/* Taken from the Android Developer website */
return new MyMP3[size];
}
};
private MyMP3(Parcel in)
{
/* This method probable needs changed as well */
Object objects[] = in.readArray(MyMP3.class.getClassLoader());
}
}
You can make your MyMP3 class Parcelable like that. Make sure you get the read/write order correct. The non-primitives must also be Parcelable, so you might not have control over that unfortunately. Alternatively, you could come up with your own serialization/deserialization. You could use a text format, like JSON or XML. Another alternative is to use subclass Application (make sure you declare it in your manifest) and use it is as a place to hang objects that span Activities. This keeps the object in memory for the lifecycle of your app, so be careful with doing this.
I have been trying to create a custom textfield in tapestry which will render some javascript when it gains focus. But I have been having trouble trying to find an example of this.
Here is some of the code i have started off with:
package asc.components;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.Field;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.ComponentDefaultProvider;
public class DahserTextField implements Field {
#Parameter (defaultPrefix = "literal")
private String label;
#Inject
private ComponentResources resources;
#Inject
private ComponentDefaultProvider defaultProvider;
#Parameter
private boolean disabled;
#Parameter
private boolean required;
String defaultLabel(){
return defaultProvider.defaultLabel(resources);
}
public String getControlName() {
return null;
}
public String getLabel() {
return label;
}
public boolean isDisabled() {
return disabled;
}
public boolean isRequired() {
return required;
}
public String getClientId() {
return resources.getId();
}
}
I have been unsure on what to do next. I do not know what to put into the .tml file. I would be grateful if anyone could help or point me in the right direction.
There is no need to replicate any of TextField's functionality in your own component, instead you should create a component mixin. Mixins are designed to add behaviour to existing components.
From the Tapestry 5 docs:
Tapestry 5 includes a radical feature,
component mixins. Component mixins are
a tricky concept; it basically allows
a true component to be mixed together
with special limited components called
mixins. The component plus its mixins
are represented as just a single tag
in the component template, but all the
behavior of all the elements.
You would use the mixin like this:
<input type="text" t:type="TextField" t:mixins="MyMixin" t:someParam="foo" />
A mixin stub:
#IncludeJavaScriptLibrary("MyMixin.js")
public class MyMixin {
/**
* Some string param.
*/
#Parameter(required = true, defaultPrefix = BindingConstants.LITERAL)
private String someParam;
#Environmental
private RenderSupport renderSupport;
#InjectContainer
private AbstractTextField field;
#AfterRender
void addScript() {
this.renderSupport.addScript("new MyJavascriptClass('%s', '%s');",
this.field.getClientId(), this.someParam);
}
}
Note the #InjectContainer annotation, which injects the containing TextField into your Mixin. In this case, we want the TextField's clientId.
Also note the #IncludeJavaScriptLibrary("MyMixin.js") annotation, which includes the required Javascript file.
The Javascript could look like this:
MyJavascriptClass = Class.create({
initialize: function(textField, someParam)
{
this.textField = $(textField);
this.someParam = someParam;
this.textField.observe('focus', this.onFocus.bindAsEventListener(this));
},
onFocus: function(event)
{
//do something
}
}
The key difference to your approach is that this involves defining your own JS class and using Tapestry's built-in facilities to load and initialize the JS. The use of mixins is also relatively light-weight and elegant in comparison to creating your own components.
The .tml
<t:textfield onfocus="somethingCool()" />
The Java should probably extent TextField? It will need to import a new stylesheet too probably.
--
Pages are actually components, so you would build a component just like you would have any other page. You can embed any other component into them. I hope this is a good starting point for you.