Some of the names are clear, like background, foreground, focus etc. But some are just confusing, like light, hightlight, shadow, darkshardow etc. I noticed that these are consistently used in swing UI, so I infer these are part of java's jargon. Does any body know if there is a document out there that explains these names ?
RadioButton.background
RadioButton.darkShadow
RadioButton.disabledText
RadioButton.focus
RadioButton.foreground
RadioButton.highlight
RadioButton.light
RadioButton.select
RadioButton.shadow
These are UIResource elements related to JRadionButton. Each Look & Feel provides different radio button appearance, and may set different defaults for these elements. It is also to up to L&F implementation to use these keys or not.
For example, here is a method from javax.swing.plaf.basic.BasicBorders that uses RadioButton.light and RadioButton.highlight:
public static Border getRadioButtonBorder() {
UIDefaults table = UIManager.getLookAndFeelDefaults();
Border radioButtonBorder = new BorderUIResource.CompoundBorderUIResource(
new BasicBorders.RadioButtonBorder(
table.getColor("RadioButton.shadow"),
table.getColor("RadioButton.darkShadow"),
table.getColor("RadioButton.light"),
table.getColor("RadioButton.highlight")),
new MarginBorder());
return radioButtonBorder;
}
However, it is may not be used by concrete L&F implementations.
PS:
UIManager Defaults by #camickr can be handy to visualize different keys.
Related
I am working on a java swing application using synth Look and Feel.
There are already styles for every possible swing component
I must change the whole application's LookAndFeel, redefining different styles for every possible swing component.
I am now working on a sandbox, launched outside of the application. The sandbox loads my new set of styles, while the application still loads the old ones. No problems for now
However, I must then integrate it 'progressively' in the application. Meaning that in the same java application, some HMIs must use the old set of styles, while some must use the new ones
The difficulty being that each set of styles define synth "region" styles that automatically apply to the corresponding component, and I don't know how deal with several region styles that correspond to the same component type
Anybody has an idea of how I can do this ?
I saw that in swing's UIManager, one can change the LookAndFeel, but it then changes for the whole application
Only workaround I saw on the internet was to change the LookAndFeel before instanciating a Component, then change it back, which looks like an awful solution
Thanks in advance
Only workaround I saw on the internet was to change the LookAndFeel before instanciating a Component, then change it back, which looks like an awful solution
This is a very very very x 10 times bad solution.
I'm the author of the material-ui-swing and with the material style, you need to work with this concept of different style, and this is the main focus that I had during my development with the library, also because at the same time we integrate the library in one of the famous swing application called JMars where we need to respect a design system given by the UX team.
To make an example, material-ui-swing give two types of API:
one it the Material Theme System to define in a declarative way the theme around the App, and
the second is to give the lower-level API to implement the UI component with a different style.
In your case, we need the second power of material-ui-swing which is the lower-level API, and I will add an example also reported inside the repository online at the following link, and the complete doc is available here
A possible example of customization is the following on
public class ContainedButtonUI extends MaterialButtonUI {
//The propriety order inside the method installUI is important
//because some propriety should be override
#Override
public void installUI(JComponent c) {
super.mouseHoverEnabled = false;
super.installUI(c);
super.mouseHoverEnabled = true;
super.colorMouseHoverNormalButton = MaterialColors.PURPLE_500;
super.background = MaterialColors.PURPLE_700;
c.setBackground(super.background);
if(super.mouseHoverEnabled){
c.addMouseListener(
MaterialUIMovement.getMovement(c, this.colorMouseHoverNormalButton)
);
}
//If you want use this style also for Default button
// super.defaultBackground = MaterialColors.PURPLE_700;
//super.colorMouseHoverDefaultButton = MaterialColors.PURPLE_500;
super.borderEnabled = false;
}
After that to keep all your app architecture clean you can add the following specialization of JButton
/** #author https://github.com/vincenzopalazzo */
public class ContainedButton extends JButton {
public ContainedButton() {}
public ContainedButton(Icon icon) {
super(icon);
}
public ContainedButton(String text) {
super(text);
}
public ContainedButton(Action a) {
super(a);
}
public ContainedButton(String text, Icon icon) {
super(text, icon);
}
#Override
protected void init(String text, Icon icon) {
super.init(text, icon);
// When you don't want anymore you just delete the
// following line
setUI(new ContainedButtonUI());
}
Of curse, maybe the library can not help you in all your component styles, but nobody said that the library can not evolve with the help of the community.
A not complete description of components can be found here
Thank you all for your answers and sorry for my lack of reactivity during the holidays
I think I found a solution, which is not exactly what I asked for but answers my problem :
I will not make several LookAndFeels coexist.
Instead, I will load all styles, new and old, in the same LookAndFeel, and use different setName() for new and old components
For region styles (which was the problematic here), I will make a custom SynthStyleFactory which will redirect to the correct region style
Once all HMIs are migrated, I will delete the old styles and the custom factory which won't be needed anymore
I'm trying to change the text color of the Substance Look and Feel (in fact I'm using the SubstanceGraphiteGlassLookAndFeel .
I don't know how to do that...
Ultimately you have to mess with the color schemes.
Since you are using the Graphite Glass skin, messing with the color schemes is considerably easier since they values are not set in Java code. If you copy he file /org/pushingpixels/substance/api/skin/graphite.colorschemes into your classpath, you can go into the various scheme definitions and change the colorForeground entries to be whatever you want. Possibly black (#FFFFFF) or the various greys (#cccccc, #999999, #666666, #333333). But since they are hex colors you can do whatever you want.
change all Keys in UIManager by killing all things that to create this great theme
change value for all Keys in UIManager for all JComponents or concrete JComponent
change value for all value in Highlighter(s) for all JComponents or concrete JComponent
I'm not sure if this theme to use or not the Trident too, have to check on former Kirill's forum
or simpler to change for concrete JComponents instance, have to repeated for all JComponents
disclaimer
never to change Colors or Fonts for Custom Look and Feels, have to check if is or isn't there direct way implemented by author of L&F, never to tried that for all JComponents and this theme isn't my favorite, then point second is safer by eliminate side effect implemented in Custom L&F, but in this case you probably to loose implemented Highlighter(s)
Is it possible to set different L&F to specific component (in my case JTable) than is already used? If so, how to do it?
Edit: I wrote this piece of code according to this tutorial. Why is this code not working? No fails or exceptions, but JTable is still the same.
NimbusLookAndFeel nb = new NimbusLookAndFeel();
jTable1.putClientProperty("Windows.Overrides",nb.getDefaults());
jTable1.putClientProperty("Windows.Overrides.InheritDefaults",false);
You can refer the below URL for all UI default values for nimbus look and feel
http://jasperpotts.com/blogfiles/nimbusdefaults/nimbus.html
Go to Table section and use all the those Table component specific UI default values in your application. That should do the trick for you.
If you would like to apply the Nimbus L&F to a button, then you simply need to figure out which class that is responsible for rendering Nimbus buttons. The process is just the same as if you want to apply your very own custom L&F, where you set your own UI class on the button.
One trick you could do is create a dummy application that uses the Nimbus look and feel, create a JTable, and do something like
System.out.println (myTable.getUI ().getClass ().getName ());
At that point you will know which UI object is used to render the JTable when using the Nimbus LAF. You can use this class name when calling setUI (TableUI) on your JTable:
myTable.setUI (new ui_manager_class_name ());
As others have said, this is hardly something we recommend though. LAF's are usually meant to be used as a whole package rather than a mix of 2-3 LAF's. Your other way out could be to use the MultiLookAndFeel, but I have never used it, so I'm not sure it does fulfill your needs. You should read the associated tutorial if you want to use it correctly.
I am currently working on a set of custom controls for a product of the company I'm working in. For this, I am extending a lot of Swing controls and also overriding a lot of paint methods.
In order to maintain a consistent color scheme, I receive the colors for my paint, setBackground etc. methods using UIManager.getColor.
This was perfectly fine until we noticed that the Nimbus LookAndFeel, which is shipped with current JRE versions, uses totally different color keys, thus many things looks totally out of place.
For instance, while all other stock LookAndFeels (Metal, Windows Classic, Windows, CDE/Motif, GTK) have defined the key "text" as a bright background for texts and "textText" as the corresponding foreground color, "text" in Nimbus is actually a black foreground color, and a standard text background color does not seem to exist.
"TextField.background" would work, but that, for instance, doesn't exist for the Windows LookAndFeels.
I suppose you get the problem by now. I don't want to have to maintain a set of color keys for each LAF, who knows what LAFs will be added in the future and which my company may decide to use.
A simple solution would be getting rid of Nimbus, of course, but understandably my boss doesn't like this idea at all, besides Nimbus is part of the JRE these days and should be supported.
So I wonder whether there is any standardized way to get LAF-dependent colors like, say, "text background / foreground", "selected text bg/ fg", etc.?
I'm not sure that there is a "standardized" way of getting these values.
As you noticed, Nimbus uses its own names for colors. Specifically, the properties textForeground and textBackground.
This oddness is likely because Nimbus uses a small selection of basic colors (listed as Primary in the chart), which have Secondary colors calculated from them, which in turn are used as the basis for all the remaining colors.
Yea, as #josefx implied, unfortunately this isn't how the UIs work. They're not a pool of generic portable properties, rather they're a set of actual components and specific implementations for each of those components. It's not really an extensible system that's friendly to custom components.
The level of abstraction IS the component, not something finer grained. If you try to ask for a ComponentUI for a component that the L&F does not know about, you're out of luck. And the ComponentUI is little more than a wrapper for a paint method, so it's not obligated to expose any meta data at all.
Simply put, you're stuck basically doing the JTextField (or some other appropriate component) "color scrape" technique that josefx suggests, or adding specific support in your code to handle the eccentricities of the property names of the L&F's that you wish to support well.
Another suggestion is to "pre-empt" the L&F change, and subclass the L&Fs you wish to support to make your components more of a first class citizen within those L&Fs. When the L&F changes to a L&F that you support, silently switch out their class name with your subclasses class name, and then implement ComponentUIs for your custom components, and extend the parent LookAndFeel.createUI method so that it "knows" about your new components.
None of these are pretty, but the Swing component system isn't designed to be extensible at run time to handle custom components. The entire component suite is done all at once when the L&F is created.
There is no way around it - you have to create your own abstraction layer for color names (and possibly other property names).
Basically you have stock LookAndFeels (Metal, Windows Classic, Windows, CDE/Motif, GTK) that use their own color names and Nimbus that uses different names.
Create a class e.g. LafProperties so that for each property/color you have method (e.g. "getTextColor"). This class returns properties for classic Laf styles. Then extend this class for Nimbus, and change only methods that differ in Nimbus.
If stock Lafs and Nimbus have most of the properties differently named, than use you might use an interface and two implementing classes.
Not a nice way but it should work for the basics:
Create a JTextField
call getForeground,getBackground,getSelectionColor to get the laf dependent values
Update:
The ComponentUI class and its subclasses which are the base classes for all look and feels only provide a method to initialise the laf dependent default values, they provide no direct way to access these values.
The java.awt.SystemColor class provides variables for a lot of the common attributes.
For text foreground/background use the member fields text/textText; for selected text, use textHighlight/textHighlightText.
Few things ppop into my mind reading your question, which is a tad spiced with underbelly frustration if I have sensed well:
dependancy on JRE standards/support versus independancy/freedom solutions
standards & conformity versus creativity & customisation
And thus ultimately:
practical approach of your boss versus programmers far future insights
Ok so ive got a swing app going using the "System" look and feel. Now, I want to change the background colour of the main panels to black. Too easy right?
UIManager.put("Panel.background", Color.BLACK);
Well yeah, except now the controls in the app look stupid, because their 'shadows', for want of a better word, are graduated to fade towards the old system default colour(gross windows grey). So there are light grey 'corners' on all the controls, especially the tabs on JTabbedPane.
I know it can be fixed, because if you change the windowsXP theme to one with a different default application colour, the controls take on this changed colour and their shadows 'fade' towards it.
But I have no idea what UIManager key it is, or even if you can do it with UIManger.
I dont really want to change the L&F engine, because apart from this it looks good.
You might try these:
control
controlDkShadow
controlHighlight
controlLtHighlight
controlShadow
(I just found them in this list: Swing [Archive] - UIManager: setting background and JScrollBar )
In general this is a little bit tricky. It depends on exact LaF you are using.
For example. JGoodies use own color scheme which redefine this stuff.
In general the property names are composed like
COMPONENT_NAME_WITHOUT_J + '.' + PROPERTY.
Unfortunately, property names can be only obtained from implementation classes of LaF. These aren't shared or something. Each component has its own. Or better, it depends on laziness of author which pairs he used. In general.
A lot of help makes redefine Panel.* and Button.. A lot of components use Button. properties.
Try, play, win :). I wish you luck :).
PS: It is a lot of properties to overwrite. But this is the way how LaFs works.
You can see what the default settings (and their keys) are by using UIManager.getDefaults();
You can then iterate over the resulting keySet (it is an instance of Map).
So something like this will show all the default keys:
for (Object key: UIManager.getDefaults().keySet())
{
System.out.println(key);
}
Some controls like JButton need to have setOpaque(false) called to allow the new background colors to fade through.
To list out all the possible options that we can set to UIManager to change LaF, run the code below ........
import java.util.*;
import javax.swing.UIManager;
public class UIManager_All_Put_Options
{
public static void main (String[] args)
{
Hashtable properties = UIManager.getDefaults();
Enumeration keys = properties.keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
Object value = properties.get (key);
System.out.printf("%-40s \t %-200s \n", key,value);
}
}
}
enjoy...