Set property for all child components - java

I've never used Java AWT before and now I've got a piece of code that displays a JFrame and sets the font property for all child components to the same value. I'd like to set the property in one place only. How can I do this?
In .NET/WinForms, child controls inherit from their parent controls, thus it would be enough to set the font for the Form instance to have it propagate to all controls. Unexpectedly, this doesn't seem to hold for AWT.
The following little code sets the font for all components recursively:
private void setFontForAll(JFrame f, java.awt.Font font) {
f.setFont(font);
setFontRecursive(f.getContentPane().getComponents(), font);
}
private static void setFontRecursive(Component[] components, java.awt.Font font) {
for (Component c : components) {
c.setFont(font);
if (c instanceof java.awt.Container)
setFontRecursive(((java.awt.Container)c).getComponents(), font);
}
}
However, it has four drawbacks:
Extra code, which might actually be quite inefficient for large forms with nested layout panels.
Code is non-generic. If I need to do the same for another property in future, I've got to rewrite the method (or refactor it to be more general at the expense of conciseness).
Usage is non-declarative, i.e. has to be called at the very end of the form creation (after all child components have been initialized and added) instead of anywhere in a declarative manner.
It doesn't work. Components are set correctly but not all things are components. For example, the TitledBorders of JPanels don't get set.

The UIManager class is the thing you need. Before you build your user interface simply tell it what fonts you want. Be warned though; there are a lot of font keys defined and if you want to change them all, you'll have to set them all.
UIManager.put( "Button.font", new Font( "Verdana", Font.BOLD, 12f );
UIManager.put( "Label.font", new Font( "Wingdings", Font.ITALIC, 12f );
// ...etc...
You can see the keys and values that are set by programmatically inspecting UIManager.getDefaults() which returns a hashtable.

For Swing you can also set the fonts with command-line arguments:
# java -Dswing.plaf.metal.controlFont=Georgia -Dswing.plaf.metal.userFont=Tahoma -jar foo.jar foo.Foo
Add -Dswing.aatext=true for anti-aliasing which makes the whole GUI look a lot nicer. :)

Related

JTextPane: What's the renderer of/for setCharacterAttributes?

I have a JTextPane in my application and I prepare some styles for various words/letters. These styles are applied via setCharacterAttributes. Now I plan to style the background of some styles: If a style defines a background (say gray) and I want to soften the corners (round corners with ie. 3px).
Is there a way to add a special renderer that is used within setCharacterAttributes? Or, do you recommend HighlightPainter added via pane.getHighlighter().addHighlight(...)?
Ok, Your question is not very clear, but if I understand correctly, you intend to customize the default behaviour of the background properties on characters. You describes 2 approaches, and one is probably much easier than the other one.
1) Based on Character attributes (complex one) : You need to define your behaviour by overriding the paint method in javax.swing.text.GlyphView. Then, you will need to change the ViewFactory of your EditorKit to make it take your change into account. I would not recommend this approach.
2) Based on Highlights (easier one) : You need to define a new javax.swing.text.Highlighter.HighlightPainter that paints the round borders as you wish. Then you need to find every set of text where a background is set. You remove the background and add your custom highlighter instead. You can optimize the process, but I think you already got this part.

How to Disable/hide Tooltips in JavaFX

This is how I set my tooltips:
if(Globals.isShowTooltips()) {
locale = new Locale(Globals.getGuiLanguage());
bundle = ResourceBundle.getBundle("bundles.lang", locale);
btnSettingsApply.setTooltip(
new Tooltip(bundle.getString("btnSettingsApplyt")));
btnSettingsOk.setTooltip(
new Tooltip(bundle.getString("btnSettingsOkt")));
btnSettingsCancel.setTooltip(
new Tooltip(bundle.getString("btnSettingsCancelt")));
}
How can I hide tooltips? It seems to me that there isn't a straight-forward approach for this.
Any help is appreciated!
For Controls
Controls have a setter for tooltips. So for controls, use that.
To set the tooltip on a control:
btnSettingsOk.setTooltip(new Tooltip("OK Button"));
To remove the tooltip on a control:
btnSettingsOk.setTooltip(null);
For Nodes which are not Controls
Layout panes, shapes and other nodes do not have a setter for tooltips (because tooltips are classified as controls and the JavaFX developers wanted to avoid a dependence of the general scene graph nodes on the controls package). However those nodes can still work with tooltips using the static install and uninstall methods.
This is pretty much Ikallas's answer, though I would only advise using it when the node type in question does not supply an explicit setTooltip method - even though it will also work for controls. The set method on controls is simpler to use because the control stores a reference to the Tooltip, whereas, for an static uninstall, your application is responsible for keeping the reference to the tooltip so that it can later remove it.
To set the tooltip on a Node which is not a control:
Tooltip okTooltip = new Tooltip("OK Button");
Tooltip.install(btnSettingsOk, okTooltip)));
To remove the tooltip from a Node which is not a control:
Tooltip.uninstall(btnSettingsOk, okTooltip);
OK, just found answer to my own question :)
Tooltip.install(btnSettingsOk, new Tooltip(bundle.getString("btnSettingsOkt"))); //This is for showing
Tooltip.uninstall(btnSettingsOk, new Tooltip(bundle.getString("btnSettingsOkt"))); //This is for disabling
If there is some better way I would like to know about it ;)

How to set all Java Swing GUI component backgrounds and foreground(fonts) colors at once?

I have tons of jbuttons, jtextfields, jlabels, jmenus, gui items and it is extremely time consuming to set the background color and foreground color one at a time.
I want to be able to color the fonts(foreground) and backgrounds all the jmenus, jmenuitems,jtextfields,jbuttons, etc quickly/concisely in my project instead of having to set them one at a time.
Is there any technique to do this more concisely instead of doing it one at a time?
1) most eficient way would be to use Custom Look and Feel, part of them have got a nice Themes
2) set value to the UIDefault, Listing UIDefault Properties
EDIT:
best of all UIManager Defaults by #camickr
You can combine Swing with CSS or use a Swing Look & Feel in order to create a standard look for your components. The Java site says:
Before we get into a CSS implementation, let's consider the alternative: a custom look and feel. Swing Look and Feels (L&Fs) are sets of classes that implement the actual drawing of components at a very low level (think lines and bitmaps). They can be swapped out for new ones at runtime, often to implement the look of a native platform; i.e., the JDK for OSX has a set of classes that make Swing apps look like native Aqua apps, with candy buttons and blue tint. Custom L&Fs are powerful, but not trivial or quick to build. You will usually have to touch 20 or so classes and implement a whole bunch of special drawing code.
So CSS is easier to use. The same article goes on to give a tutorial about how to implement the CSS with Swing. They provide a nice walkthrough of creating the right rules and then going on to implement them in CSS. However, this is not simply "copy and paste" code.
If you'd just like to use a package (without having to code it yourself) the answers to the question Can I use CSS for Java Swing? suggest Flying Saucer and Jaxx.
They're all JComponents so you can make an ArrayList of everything:
//Adding everything to the ArrayList
ArrayList<JComponent> myComponents = new ArrayList<JComponents>();
JButton b1 = new JButton("Button 1");
myComponents.add(b1);
JMenuItem item = new JMenuItem("Menu Item 1");
myComponents.add(item);
//Coloring the foreground/background
for(JComponent j : myComponents) {
j.setForeground(new Color("BLUE"));
j.setBackground(new Color("RED"));
}
If you use a Look and Feel that honors the UI constants in javax.swing.UIManager then you can just set them. There are values for e.g. panel background. If not or if you can't control the look enough by this you can write you own UI delegate that draws a specific component (e.g. javax.swing.plaf.ButtonUI for JButtons). If even this is not enough you can write your own Look And Feel. If you just extend the Metal LnF it is not that hard, you would write own UI delegates and set properties, like above, but centralized.

JTree nodes' rendering and font changes

I have a problem with rendering nodes in JTree. When node's font is changed and node's text gets wider that way then node's text is cut and end of text replaced with dots.
How to tell the JTree then that it should widen area to render tho whole node.
Thank you for help
You can use custom renderer and set to the component (JLabel) something like this
final Dimension size = label.getPreferredSize();
label.setMinimumSize(size);
label.setPreferredSize(size);
or just set text like this
setText("<html>" +valueText+"</html>")
Sounds like the trigger of the font change happens under the feet of the tree: internally, the ui delegate does lots of size caching which must be updated on any change which effects the cached sizes. That's done automatically on changes to the treeModel, to relevant expansion state and some visual changes to the tree itself.
So the basic question is: what triggers the change of the font? If it's some change of the model/nodes, the model implementation is incorrect in not firing an appropriate TreeModelEvent, the obvious solution would be to fix that :-) If it's something outside the model, the solution depends on the details of your context, nothing generally applicable.
Size caching
The JTree uses a renderer to render nodes. The renderer is the same renderer for all OSs, so the differnt lookings are inside ComponentUIs. JTree uses by default a JLabel to paint nodes, so its the JLabel's size wo guides us to cut the text using ....
Lets make a short excourse: Swing has differen LookAndFeels for different Operation Systems, they are detached from the components in UI-Classes like the BasicLabelUI (and this is the source of your problem). BasicLabelUI caches the size of the label to prevent recalculation if no changes has made. So BasicLabelUI did not clear the cache of theese old size values. BasicLabelUI do clear the cache if he gets informed about any changes.
The question is, why does the BasicLabelUI did not get informed about changes? Well, if you modify/expand/rename the Tree programatically you must tell the ComponentUI to drop that cache!
You lucky, you do not need to write much code because a genius already wrote something for you, the creators of the TreeUI-class Rob Davis and Scott Violet wrote startEditingAtPath and stopEditing.
Example
TreeUI ui = tree.getUI();
for (TreePath treePath : selectionPaths) {
ui.startEditingAtPath(tree, treePath);
}
tree.setSelectionPaths(selectionPaths);
tree.expandPath(expandPaths.getSelectionPath());
ui.stopEditing(layer);
Call your TreeModel's reload()

How do I get the default font for Swing JTabbedPane labels?

Does the text in Swing components have a default font? In particular, what about tab labels on JTabbedPanes?
I'm working on a mock-up of a GUI made with Swing and want it to blend it with a screen image I grabbed of a Swing app.
It depends on the Look and Feel. If it's an application you've written, get the values from UIManager.getDefaults().getFont("TabbedPane.font")
The UIManager Defaults shows what the values are for all properties for all components (including "TabbedPane.font").
Based on the answer of Reverend Gonzo, this piece of code lets you know what keys are in the UIDefaults. As the keys are self-explanatory, you know what key you can use. I had to know the key for the JTextField font, for example, and could only find it this way.
Set<Object> keys = UIManager.getDefaults().keySet();
for (Object key : keys) {
if (key instanceof String && ((String) key).contains("font")) {
System.out.println(key + "=" + UIManager.getDefaults().get(key));
}
}
If you're looking for a font, in your case, just cast the key to a String and check whether it contains the word "font". This way you narrow the set of keys you have potential interest for.
I got a list
Menu.font=...
TextField.font=...
RadioButtonMenuItem.font=...
ToolTip.font=...
TitledBorder.font=...
...
TabbedPane.font=...
...
And thus you would need to pick TabbedPane.font.
It may depend on the 'Look and Feel' you are using, but for me Swing's default font is
DejaVu Sans - Plain
For most components the font size defaults to around 12 or 13
It looks like it's Arial. That's what Identifont tells me and it looks right.
The Java GUI default font is "Helvetica", bold size 9, color gray.

Categories

Resources