Modifying graphics context in Java - java

I have a form that tries to modify a JComponent's graphics context. I use, for example,
((Graphics2D) target.getGraphics()).setStroke(new BasicStroke(5));
Now, immediately after I set the value and close the form, the change is not visible. Am I not allowed to modify a JComponent's graphics context? How else would I modify the stroke, color and transformations?
Thanks,
Vlad

There are several problems with that approach. The first is that most components will set these things themselves when ever they are asked to repaint themselves. This means that your change will be lost every time the component gets to the point where it would actually use it. But, on an even more fundamental level than that, Graphics2D objects are not persistant. They are typically instantiated every time the component is redrawn, meaning that the Graphics2D object you got won't be the same the component will be using when redrawing.
What you need to do, to achieve this kind of thing is either to reimplement the specific component yourself, or implement a new look and feel that will affect the entire set of swing components. Have a look at the following link for further details about this:
http://today.java.net/pub/a/today/2006/09/12/how-to-write-custom-look-and-feel.html

Nobody to answer? I have let some time to see if there is any good answer before mine: I am not a specialist of such question...
First, I don't fully understand your question: you change a setting then close the form?
Anyway, I am not too sure, but somewhere in the process, the graphics context might be recomputed or taken from default. Perhaps if you do this operation in the paint() method, you can get some result, although I am not sure.
For a number of changes, you usually use a decorator. I explored a bit this topic when answering a question on SO: How do I add a separator to a JComboBox in Java?. I had to paint my own border there (asymmetrical), but often you just take an existing one, so it is quite simple.
I hope I provided some information, if it didn't helped, perhaps you should give more details on what you want to do (and perhaps a simple, minimal program illustrating your problem).

OK, I've worked around the problem like this: The custom JComponent now holds a Stroke object, which is set by the "Choose stroke" form when the user clicks OK. Then, in the paint method of the JComponent, I set the stroke of the graphics context passed as parameter to paint to the one contained in the object.
I have experimented and found out that, for some reason, JComponent.getGraphics().set* doesn't work.

Related

Disable repainting after modifying graph in Jung

I've a graph in Jung shown using a JFrame.
After I remove a vertex from the graph,
the shown graph automatically redrawn and presented without the removed vertex.
How can I disable it, so that only when I call the repaint method
the graph would be redrawn ?
Thank you
The simple way to do this is extend your graph by some class and add toRemove() method, where you can signify your vertex to delete in boolean array. And the second method deleteNow() which will use your boolean array and delete your vertexes - it will be alike repaint() now. The second way is add boolean value to your vertex instead of array in your extended class. I can't find any other way. Sorry if it's not helpful.
You haven't really given enough information to be able to advise you precisely, but here are some general observations.
The answer to your question is going to depend in part on how you're removing the vertex: interactively or programmatically.
If it's programmatically, then you'll need to look at the code that calls VisualizationViewer.repaint(). It's been a while since I've looked at that part of the code, but the gist is that something is listening to changes to the graph model and triggering repaints (because this is what users generally want).
If it's interactively, then it's probably on the same thread as your visualization, and you should have a fair amount of control over when repaint() gets called (see the calls in the sample code to VV.repaint()).

Overriding a deprecated JComponent method

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()?

Java Swing Range Slider U.I

I needed a slider with two knobs on it (representing a range) and I found this nifty one here. However, they created their own U.I. which extends Java's BasicSliderUI. They override the paint method to draw their own knobs. I would like to use the default knobs based on the current look and feel. I tried calling BasicSliderUI's paintThumb method, but this gives me a generic looking knob which doesn't seem to be tied to the current look and feel. As far as I can tell, JSlider gets its U.I. from MultiSliderUI. How can I create a U.I which changes like JSlider's, but draws two knobs instead of one?
Thanks in advance!
SwingX provides JXMultiThumbSlider which may be what you are looking for.
Try getting the current look and feel from the javax.swing.UIManager and calling getUI(new JSlider()) on it. This should return the current UI used for the JSlider, which should be castable to JSliderUI.
Unfortunately JSliderUI doesn't have a paintThumb(Graphics g) method, but the BasicSliderUI does, and at least on Windows XP and Windows Vista the system look and feel is a subclass of BasicSliderUI, so is the Metal look and feel.
So once you have the JSliderUI see if it is an instance of BasicSliderUI, if so you can cast it to BasicSliderUI and use the paintThumb(Graphics g) on it, otherwise default to the way you are doing it already. I don't know if this actually works, but it would be my first attempt if I needed it.
I don't have Linux or Mac to check the source if their JSliderUIs are derived from BasicSliderUI as well, but if you do then check out the java source code.
You can use RangeSlider class from
Jide Commons Layer
This is opensource.

Custom swing component - Turning a node into text

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?

How can I dynamically alter the Java LAF UIDefaults?

I'm working on cusomizing a Swing application by dynamically altering the UIDefaults. The end goal is to alter many of them (colors, fonts, sizes, borders, etc) and save the result on a per user basis. While it may give the application some non-standard looks, the client asketh and the client shall receive.
The only problem I'm running into is that GUI will only update ONCE. The first time I change a ui property everthing is great, subsequent changes don't affect anything.
// called from the EDT
// uiKeyName points to some ColorUIResource
UIManager.getDefaults().put(uiKeyName, <<color from color picker>>);
SwingUtilties.updateComponentTreeUI(rootWindow);
It works once, but never again. Ideas?
When you put the new color (for example) in the table, is it a Color object, or a ColorUIResource? As I understand it, the new value will only be taken up if the current value is null or an instance of UIResource. Thus, if you insert a plain old Color object, any subsequent changes you make will be ignored.
Also, as the linked doc page suggests, this may only help with the font and foreground/background colors; when it comes to changing things like borders and margins, you may be out of luck. This is not what Swing's Pluggable LookAndFeels were designed for. Maybe you could interest the client in a Synth-based LAF?

Categories

Resources