I'd like to add an extra feature to the debug mode of the programme I've taken over.
What I want to be able to do add tooltips to all the buttons, tables on the GUI so that they display something like this in them:
Class: JButton
Name: myShineyButton
Method: myShineyButtonActivateMethod
I know the general form for using reflection of this is like so:
for(Fields bits: this.GetClass().getDeclaredFields){
if(bits instanceof Component){
String methodName = bits.getMethod().toString();
....
}
}
But then how do I add the tooltip to each item on the gui?
You may want to look into an aspect-oriented programming (AOP) tool, such as AspectJ. You can examine/modify an object after returning from a call to its constructor. As a concrete example, this aspect, cited here, detects all EDT rule violations. More examples may be found here.
Related
errorPopup= popFactory.getPopup(this, errorBox,
(verifierTopComponent.super.getX()+verifierTopComponent.super.getWidth()/2),
(verifierTopComponent.super.getY()+verifierTopComponent.super.getHeight()/2));
The code above works, and properly centers the popup... but only if the window is fullscreen, on my main monitor.
How do I make it more robust? I'd like to center it in the middle of the current RCP instance.
(verifierTopComponent is my incorrectly named TopComponent in the module).
After the comment below, I'm wondering if maybe y'all typically use a vastly different method to create a popup? I'm just trying to put something in the user's face to let them know why things won't work as they have done them.
When using the NetBeans RCP you should rather use DialogDisplayer and DialogDescriptor
Something like this:
DialogDescriptor dd = new DialogDescriptor(errorBox, "Error message");
Object result = DialogDisplayer.getDefault().notify(dd);
It will automatically take care of calculating the correct position.
I'm unsure how to solve your specific issue but in my experience you can/should use NetBeans' org.openide.NotifyDescriptor class to show notifications to the user. You will need to add a dependency for the Dialog API to your module to use the following.
NotifyDescriptor nd = new NotifyDescriptor(
"This is the message that will go in the main body of the message. This could also be a custom JPanel",
"Title of Dialog",
NotifyDescriptor.DEFAULT_OPTION,
NotifyDescriptor.ERROR_MESSAGE,
null, // this could be an array of JButtons that will replace the dialog's built-in buttons
NotifyDescriptor.OK_OPTION);
Object returnedValue = DialogDisplayer.getDefault().notify(nd);
if (returnedValue == NotifyDescriptor.OK_OPTION) {
// user pressed OK button
}
As always, see the javadoc for NotifyDescriptor for more info
Edit As described in another answer you could use the DialogDescriptor class which extends the NotifyDescriptor class and adds the ability to set the dialog to modal along with a couple of other useful features.
There are also a couple of other useful classes that extend the NotifyDescriptor class that may be useful for other situations. See the javadoc for NotifyDescriptor for a list of subclasses.
I started to look into using GWT in combination with UiBuilder. I'm a bit puzzled about how you can use the #UiHandler(..) directive to make simple event handle code as written down in the GWT documentation:
#UiHandler("button")
void handleClick(ClickEvent e) {
Window.alert("Hello, AJAX");
}
In this case the method handleClick is used.
How do you know for each GWT widget what methods can be created with #UiHandler? For some you can also create a doClose() method.
But what can you use with, for instance, a ListBox to get an event an item is selected? Where in the documentation can I see this?
The parameter you pass to the #UiHandler annotation is the name of the appropriate field you want to assign that *Handler. So, in this case you are assigning a ClickHandler to a Button button (actually, we just know the field's name).
As for how this exactly works - it's part of GWT magic :) My guess is that, just like any other UiBinder related code (I think there was a presentation on Google IO, that showed the code that UiBinder generates), at compilation time the compiler figures out what goes where. In this example: we have a Button button, and we have a #UiHandler annotated method that has a ClickEvent parameter -> that must mean it's a ClickHandler (notice that the method's name doesn't matter). So let's add some code at compile time (in the constructor, probably) that adds that handler to the button. If you are interested in a more comprehensive answer - check out the source :D
But what can you use with, for
instance, a ListBox to get an event
an item is selected? Where in the
documentation can I see this?
In the GWT API reference. In this case, you are probably looking for ListBox.addChangeHandler. But you usually won't find #UiHandler related code there - that's because it would be redundant - you always construct the #UiHandler methods the same way:
You check the *Handler that you want to add, say ChangeHandler
It has a void onChange(ChangeEvent event) - so, your method needs a ChangeEvent parameter and should look like this:
#UiHandler("listBox")
void whateverName(ChangeEvent event) {
// ...
}
Probably your problem is in your onModuleLoad method:
public void onModuleLoad()
{
HelloWorld helloWorld = new HelloWorld("BOTAO");
// Using this way #UiHandler will not work
//Document.get().getBody().appendChild(helloWorld.getElement());
// correct way
RootPanel.get().add(helloWorld);
}
In a rich client CRUD framework I'm working on, I have a so-called edit panel, which as the name suggests, is involved in editing row objects via the usual swing input components.
Now, the panel has a default focus component field, which references the input field which should receive focus when the edit panel is initialized or cleared. The problem is the most logical name for the method which performs the focus request.
public boolean requestDefaultFocus()
return getDefaultFocusComponent().requestFocusInWindow();
}
The edit panel extends JPanel so this overrides the now deprecated JComponent method. The method name I'm currently using to avoid this is setDefaultFocus().That just doesn't sound quite right, although I will be able to live with it in case the answer to the question turns out to be a resounding no.
So, what are your thoughts on overriding a deprecated method like that?
I would not recommend it. There's no way to stop your code from issuing deprecation warnings. It makes it look like there's something wrong. And that takes developer time to verify that the warnings are spurious.
How about setInitialFocus()?
A shout out to the Swing gurus out there!!
I've been doing Swing programming for several years but have always been unclear on this.
As you know Swing/AWT gives you several ways to execute a particular action when a button is clicked. I've seen it done several different ways in the applications I've worked on. The project I'm currently working on tends to follow this approach:
someButton.setActionCommand("mycommand");
someButton.addActionListener(listener);
--snip--
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals("mycommand"))
doThis();
else if (command.equals("someothercommand"))
doThat();
etc.
This seems kind of clunky to me - is there any benefit to this style of programming, or is it better to use Swing Actions?
Or are there different situations where the different approaches are better/worse?
IMO, it is better to use separate listeners for Actions.
That way you leave the delegating of what action should happen up to Swing. You don't have to compare Strings to decide what to do.
Having one huge ActionListener for more than one action feels like breaking the pattern to me.
From a design point of view, I think it is better to have one class to handle one specific action for a component as opposed to one class that is a "lets handle everything for all components here" type of design.
Also, if you use Action you can a) apply it to more than one component (e.g. a button and a menu item) b) call setEnable to enable/disable it for all components its attached to and c) Also use it to define various settings on the components its attached to (namely, the text label, the tooltip text, the accelerator key, icon, etc.). This last one is done via the putValue method and calling this method again will change the settings for all components its attached to.
Specifically, I would advise to subclass AbstractAction for your needs.
I know that's demo code but since you're working on this stuff I thought I'd mention that swing tends to be really repetitive if you're not careful.
Using Action classes tends to let you refactor better. In swing, one of the best ways to start is to ensure that NO strings are in your code. Nearly every "New" will be in a loop of some sort, reading from a dataset (Often the dataset is as simple as an array)--Once you start reading from a dataset like that, actions can help you a lot.
You use data to create your action, data to create your control, and data to associate the two--in this way you can end up very close to (or at) 0 lines of code for a new control.
Once you start programming this way and can see the patterns, it's at least as quick as the repetitive way and much less error prone.
its Useful if you have several buttons or components that perform the same action (ie. several exit buttons on the same page will use the same code)
Set them all to the same action command and they will all use the same code in the listener
JButton.addActionListener(this);
JButton2.addActionListener(this);
JButton.setActionCommand("exit");
JButton2.setActionCommand("exit");
public void ActionPerformed(ActionEvent e){
if(e.getActionCommand=="exit")
System.exit(0);
}
I'm writing a custom swing component (something completely new, but think JTree or JList). I'm trying to follow the general design of JTree, JTable, JList etc for consistency (I've also seen various poor 3rd party components abandon the separable model and/or renderer approach).
So, I have a model full of nodes, the component itself and a renderer. At some point the node has to be turned into text and displayed by a renderer. I'm not clear on the best way to do this:
Pass the node itself (as Object) to the renderer, and let the renderer decide how to display it.
This is how JList does it.
Requires a customised renderer just to change the text.
Allows great flexibility in how to display the node (doesn't even have to be text).
Pass the node itself (as Object) to the renderer, but have a convertValueToText() method in the component class.
This is how JTree does it.
Renderers can be just as flexibile as before - don't have to use this method.
Have to override component to change the text transformation.
As above, but delegate convertValueTotext() to the model.
This is how JXTable does it.
The model is probably the best place for this method - and it's easier to override there.
I don't want to have to customise the renderer just to change the text, but I'd like to be able to customise the renderer to do more than display a model-displayed string (else why bother with renderers). I really don't like the fact that JXTable uses reflection to look for convertValueToText() in the model - this smells of bad magic to me.
Can anyone shed any light on this oft-neglected part of Swing?
SOLUTION
What I ended up doing was this:
Add a method to the model which returns a string for the given node. Importantly, this can be null to indicate that the renderer should know what to do or that we simply can't provide anything useful.
The component has the same method, and passes the call on to the model. This is important for view-model separation. The renderer calls this method, so it doesn't talk to the model directly.
The default renderer calls the above method and if it's not null, it uses it, otherwise it can call toString on the value, or provide a default, or whatever.
This leaves developers a choice when they want to override the displayed value
- Override the method with a non-null return value knowing that the default renderer will display this text.
- Provide a custom renderer which is passed the actual node object so it can do "clever" things if it needs to.
I'm quite happy with it - it "feels" right, it works, and it's easy to use.
Thanks for your perspectives!
Good question. This is not specific to Swing, but a philosophical question about the difference between a model and a view.
In general, is converting objects into text the job of the model or the view? My purist head says that actually you want a hierarchy of views - one to convert object model to text, and one to display the text. You might even want more than two - for instance, object-to-text, text-to-document-structure, document-structure-to-HTML, and then CSS to present to the user.
However, pragmatism says this may get too hard to remember and maintain. So in your circumstance I would suggest: think about how likely it is you'll ever want to extract non-text data from the model. If it is not very likely, then put the equivalent of convertValueToText in the model.
Otherwise, allow the component to either use a renderer, if it is given one, or else take the object value and convert it to text internally.
This allows maximum flexibility and probably makes things feel most natural to the users of the API. I believe this is the JTable model though I haven't used Swing for a long time.
AFAIK neither JList nor JTree require the renderer to render text. The renderer gets passed the data object and return a JComponent which gets positioned as a child in Tree/List itself and then rendered.
I would go with this. A renderer for text would simply return a JLabel. If you want to be able to change the way, the text is constructed pass a Formatter to the TextRender, and you are done.
Stephan
If you had to write your own component do it as simple as possible. In a lot of cases if you need a custom renderer then you don't care about interpretation by component or model. Model holds your data. And in this case is also custom written. From my point of view the good choice is based on first option. Provide DefaultRenderer which implements AbstractRenderer and add there all methods like toText(Object o) and so on. Then allow me to decide whether I want to use default functionality or I prefer to wrote my own. Do you really need custom component? To make it works correctly it is a LOT of work. Is this component worth all this?