I have an ImageIcon that I used for a button to open this skillsFrame. This size of the image is 100x100px. As you can see in the screenshot if I just put the image it is too large(which is expected).
My question is about how to scale the image to 16x16(or whatever the default size is) so that I don't need to manually create a smaller sized version(for multiple reasons).
In case they make windows bigger in the future
Multiple operating system support
I'm sure I don't need to go on naming more...
skillsFrame = new JInternalFrame("Skills", true, true, false, false);
skillsFrame.setFrameIcon(new ImageIcon("images/gui/button_skills.png"));
And now for the image... the bar at the tops is the buttons to click to open the various JInternalFrames.
how to scale the image to 16x16(or whatever the default size is)
you have look at Image getScaledInstance(int width, int height, int hints)
Related
I have a Button with text and an ImageView as icon. The image might be of any resolution. Currently, the button will adapt its size to fit the image, e.g. if the image is 400x400, the button will be huge and the text will be tiny next to it.
What I want though, is the image to fit into the button. It should always be as tall as the text is.
ImageView img = new ImageView(image);
button = new Button("Some text", img);
button.setStyle("-fx-background-radius: 6em;");
Wouldn't have thought the solution to this is so easy:
img.setPreserveRatio(true);
img.setFitHeight(button.getFont().getSize());
does the trick for me. JavaFX is weirdly unintuitive sometimes. If the font size may change (e.g. via CSS styling), use a binding instead:
img.fitHeightProperty().bind(Bindings.createDoubleBinding(() -> button.getFont().getSize(), button.fontProperty()));
You can set your image height via
image_view.getLayoutParams().height = YOURHEIGHT
as discussed here.
I would suggest setting your text size to an appropriate value and use the above command to scale the image to the same height.
Test around whether you can size the image with em, otherwise use cm/inch.
If there a problems with image distortion when setting height, refer to this thread.
We've a Java application with a trayicon (SystemTray) and a popup menu (PopupMenu) that worked nicely on all platforms.
On a new Surface 4 Pro we've a problem as the size of the menu is amazingly small. Looks as not noticing it's a 'retina'/high definition display.
Is there an easy way to fix this ?
Looks like you may have to resort to setting the menu UI.
See : https://docs.oracle.com/javase/8/docs/api/javax/swing/JPopupMenu.html#setUI-javax.swing.plaf.PopupMenuUI-
Of course that means you need some way to determine that you're running on the Surface Pro in the first place.
You could try figuring out the current font size and dimensions used by the menu UI and compare that with the screen dimensions from Toolkit.getDefaultToolkit().getScreenSize()
As a general solution, which is not tied up to specific devices, you could detect screen resolution in dots-per-inch via:
java.awt.Toolkit.getDefaultToolkit().getScreenResolution()
This will return screen resolution in DPI (dots-per-inch). The bigger this value - the smaller the textual fonts will get for a specific font size.
Use the DPI to set an acceptable (or maximal) DPI settings and calculate the adjustment ratio.
You can adjust either by replacing the UI delegates fonts (for an application-wide effect)
OR, if the issue is specific for the system-tray, by deriving a larger font only for SystemTray's MenuItems:
java.awt.Font defaultFont = java.awt.Font.decode(null); // default font
float adjustmentRatio = 1.0f; // Calculate this based on your metrics
float newFontSize = defaultFont.getSize() * adjustmentRatio ;
java.awt.Font derivedFont = defaultFont.deriveFont(newFontSize);
// PopupMenu with the adjusted font size:
MenuItem item = new MenuItem("Menu Item");
item.setFont(derivedFont);
popupMenu.add(item);
I'm really confused by this and I can't tell if its a bug or not.
In my SWT app I'm creating a System Tray icon. It shows up just fine, but the transparency is being ignored. The icon is stored as a PNG and viewing it in Preview on OSX shows that the transparency is there, however when it appears on the tray, it has a white background.
The icon is 2 colors, #00000 for background and the alpha is set on that, and then #010101 for the actual icon.
Here is an example of the icon:
Here is how it appears on the bar:
I've had other icons with actual color in them work and have proper transparency, so I can't help but wonder, is this some kind of rendering bug or some oddity with how Mac handles system tray icons?
Update: Channels and layers: http://i.imgur.com/YZNUnXt.png
Update 2:
scratch that
I figured it out, it was a face palm moment, sort of.
All logos were loaded from a loader class I made. There is a method which allows the size of the logo to be specified and then scaled down. I was scaling the logo initially, but after I created the new logo it didn't need to be scaled but I forgot to update that method call.
Here's some code to show what was going on.
public static Image getLogo(LogoType type, Display display, int width, int height) {
ClassLoader loader = AppLogo.class.getClassLoader();
InputStream stream = loader.getResourceAsStream(type.getFileName());
Image img;
if(width > 0 && height > 0) {
Image orig = new Image(display, stream);
img = new Image(display, width, height);
GC gc = new GC(img);
gc.drawImage(orig, 0, 0, orig.getBounds().width, orig.getBounds().height, 0, 0, width, height);
gc.dispose();
orig.dispose();
}
else {
img = new Image(display, stream);
}
return img;
}
It seems that using GC to scale the image causes the alpha values to be ignored. I also tried setting a transparency color on the ImageData but that still doesn't work. I've seen some examples where people use an algorithm to go in and scale and in that case they can actually set the pixels and it works. But drawImage doesn't.
I need to implement font size switching in my app. But when I increase font's size RadioButtons remain same size and on small screen with high resolution my customer just can't hit it easily. Is there a way to resize RadioButton's round thing programmatically without diging into L&F and redrawing Icons manually (it's complicated since app targets multiple platforms with different UIs and each of them must have 7 icons).
Perfect solution could look like this:
Extraction of native UI icon.
Resizing it
Setting resized icon as component's icon.
How to implement step 1? Is it possible?
EDIT: this is what i tried so far
public class IconImageSaver extends JFrame{
public IconImageSaver() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBounds(0,0,100,100);
setVisible(true);
JRadioButton rad1 = new JRadioButton();
rad1.setBounds(10,10,40,40);
add(rad1);
Icon icon = UIManager.getIcon("RadioButton.icon");//(1) trying to get icon
int w = icon.getIconWidth(),h = icon.getIconHeight();
Image i = rad1.createImage(w, h);
Image i2 = rad1.createImage(w,h);
Graphics g = i.getGraphics();
Graphics g2 = i2.getGraphics();
g.setColor(Color.CYAN);
g.fillRect(0, 0, w, h);
rad1.setIcon(new ImageIcon(i));//setting icons
g2.setColor(Color.RED);
g2.fillRect(0, 0, w, h);
rad1.setPressedIcon(new ImageIcon(i2));//setting icons
}
public static void main(String[] args) {
new IconImageSaver();
}
}
At position (1) i'm trying to get icon image, but it returns only background color.
Can't understand why.
Setting icons for various states works as intended.
Some L&Fs (e.g. Nimbus, Aqua) support a large JComponent.sizeVariant, as discussed in Resizing a Component and Using Client Properties.
Addendum: I must use pure native L&F.
The rendering of a JRadioButton is determined by its associated ButtonUI delegate. The internals of delegates supplied by the native L&F are generally inaccessible and rely on host platform APIs. You have to use the available feature(s) of the user's chosen L&F or supply your own. If you can explain more about the underlying problem, it may help to suggest better alternatives.
Addendum: Absent developing a complete L&F, it may be possible to work with the radio button's parent, JToggleButton. Such buttons work well in a ButtonGroup, as shown here, and they can be decorated arbitrarily, as outlined here.
is very L&F sensitive, by default you can
use proper L&F (only Nimbus has implemented auto_whatever) but we talking about Custom L&F
to override keys in UIManager, but these keys can, could (be presented or with value) or missing in compare with another L&F
create own (J)Component, to overide important methods and
a) put to the UIManger (one def. valid for whole JVM instace)
b) add to the selected, desired or part of (J)Components, e.i. .... in the visible GUI
notice for (I need to implement font size switching in my app) there is very important to test if is required to change (we'll talking about) Font or FontUIResources, part of implemented methods for part of (J)Components to pretty ignore Font and required FontUIResources, now not sure if vice versa too
IMPORTANT NOTE: This was only tested with the default 'Metal' look and feel. I do not guarantee that this will work for any other look and feel. Also I am not entirely sure how it works because it is admittedly a bit of a hack.
I was able to solve this a little bit differently.
I Was scaling my font globally using the UIManager defaults and so I wanted my radio buttons to scale with the font.
I found I could do this by extracting the Icon for the radio button from the UIManager, buffering them, re-sizing them and then deriving a new icon from the graphics of the buffered icons.
I ended up with this function:
public static void scaleRadioButtonIcon(JRadioButton rb){
boolean previousState = rb.isSelected();
rb.setSelected(false);
FontMetrics boxFontMetrics = rb.getFontMetrics(rb.getFont());
Icon radioIcon = UIManager.getIcon("RadioButton.icon");
BufferedImage radioImage = new BufferedImage(
radioIcon.getIconWidth(), radioIcon.getIconHeight(),BufferedImage.TYPE_INT_ARGB
);
Graphics graphics = radioImage.createGraphics();
try{
radioIcon.paintIcon(rb, graphics, 0, 0);
}finally{
graphics.dispose();
}
ImageIcon newRadioImage = new ImageIcon(radioImage);
Image finalRadioImage = newRadioImage.getImage().getScaledInstance(
boxFontMetrics.getHeight(), boxFontMetrics.getHeight(), Image.SCALE_SMOOTH
);
rb.setSelected(true);
Icon selectedRadioIcon = UIManager.getIcon("RadioButton.icon");
BufferedImage selectedRadioImage = new BufferedImage(
selectedRadioIcon.getIconWidth(), selectedRadioIcon.getIconHeight(),BufferedImage.TYPE_INT_ARGB
);
Graphics selectedGraphics = selectedRadioImage.createGraphics();
try{
selectedRadioIcon.paintIcon(rb, selectedGraphics, 0, 0);
}finally{
selectedGraphics.dispose();
}
ImageIcon newSelectedRadioImage = new ImageIcon(selectedRadioImage);
Image selectedFinalRadioImage = newSelectedRadioImage.getImage().getScaledInstance(
boxFontMetrics.getHeight(), boxFontMetrics.getHeight(), Image.SCALE_SMOOTH
);
rb.setSelected(previousState);
rb.setIcon(new ImageIcon(finalRadioImage));
rb.setSelectedIcon(new ImageIcon(selectedFinalRadioImage));
}
What it does is get the size of the font from the radiobuttons's font metrics. Using those metrics, it derives a new icon based on the icon found in the 'Look and Feel' and sizing it to the font's height.
One thing that I am not able to explain is how the icon for the radiobutton coming out of the UIManager changes to the 'selected' icon when I am accessing the same property to get both icons.
I start by saving the state of the control so I can restore it at the end. This is done because in order for the icons to be set properly, the state needs to be unchecked when you first request the icon from the UIManager and then it will need to be checked when you request the icon the second time to get the 'selected' icon.
Again, I am not entirely sure how the UIManager works or why the icon changes when we call the same property just by setting the 'selected' value of a single radiobutton, but that is what is required in order to get both the necessary icons.
If you did not want to use the font to size the controls, you could easily just pass in the height and width as parameters and use them instead of the font's height when setting the buffered image size.
I might mention that this same methodology works with checkboxes
I'm trying to have an icon be added and displayed to the system tray using Java. However the icon is always either too small, or its cut off in areas.
Its the second one from left in case you couldn't tell.
What am I doing wrong here? How can I get this icon to be displayed fully? What's the standard icon size to be used for system tray?
Edit: I am using AWT SystemTray and TrayIcon
After you've retrieved the actual image resource from disk, you can resize it to the size you need by creating a "fake" one on-the-fly and taking its width.
I found that this was better than using the setImageAutoSize(true) method, as that method does not scale the image smoothly at all.
BufferedImage trayIconImage = ImageIO.read(getClass().getResource("/path/to/icon.png"));
int trayIconWidth = new TrayIcon(trayIconImage).getSize().width;
TrayIcon trayIcon = new TrayIcon(trayIconImage.getScaledInstance(trayIconWidth, -1, Image.SCALE_SMOOTH));
To display the icon at an optimal size, you will need to manually resize it to the correct size. This correct size can differ between operating systems and preferences, so Java provides a method to acquire the task bar icon dimensions, which are 16x16 in the case of your example image.
if (SystemTray.isSupported()) {
SystemTray tray = SystemTray.getSystemTray();
Dimension trayIconSize = tray.getTrayIconSize();
// resize icon image to trayIconSize
// create your tray icon off of the resized image
}
According to TrayIcon.setImageAutoSize(boolean).
Sets the auto-size property. Auto-size determines whether the tray image is automatically sized to fit the space allocated for the image on the tray. By default, the auto-size property is set to false.
If auto-size is false, and the image size doesn't match the tray icon space, the image is painted as-is inside that space — if larger than the allocated space, it will be cropped.
I've ended up combining some of these answers to make the code I'm using.
This is producing a good looking icon in my system tray from a png that starts at 100x100.
It's worth noting that on a retina MacBook the icon looks worse scaled down. So I do a check elsewhere to see if it's running on a mac and don't apply this if it is.
public Image imageForTray(SystemTray theTray){
Image trayImage = Toolkit.getDefaultToolkit().getImage("my100x100icon.png");
Dimension trayIconSize = theTray.getTrayIconSize();
trayImage = trayImage.getScaledInstance(trayIconSize.width, trayIconSize.height, Image.SCALE_SMOOTH);
return trayImage;
}