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);
Related
I use FontImage.setMaterialImage(...) or sometimes FontImage.createMaterialImage(...).
How can I ensure the material image size increases or its minimum size is 48x48 px.
Lukman Jaji
I suggest not thinking in pixels but thinking in millimeters as this make far more sense with varying screen sizes.
When you invoke code such as:
FontImage.setMaterialIcon(label, FontImage.MATERIAL_3D_ROTATION);
The image will get the size of the font assigned to the given label. So if the label is styled with a standard medium font (the default) the size will be system specific. To customize this do:
label.setUIID("MyFontUIID");
Then in the designer theme:
Add MyFontUIID
Select the Font tab and select any native font.
Select the size to be in millimeters or pixels to determine a fixed size to the icon. I would recommend millimeters for portability.
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;
}
How to change the size of JFrame icon?
JFrame f = new JFrame("Test");
Image icon = Toolkit.getDefaultToolkit().getImage("icons/logo.png");
// icon.setPreferredWidth()...
f.setIconImage(icon);
Frame icons are set according to a size decided by the OS.
If you supply icons of various sizes, Windows will use the smaller one for the frame icon, and the larger one as the image to include in the window shown when the user types alt tab to change between apps.
OS X shows no frame icon at all.
See also: Sizes of frame icons used in Swing.
Top Level Containers came from Native OS, from current used theme, then not possible to increase numbers of available pixels,
some dirty hack are possible to wrote in case that you setSystemLookAndFeel, including caption, Font type&size or background, simple don't do that this way,
possible only by implements Custom Look and Feel especially some of Substance's themes can do that
I have made an Android application, but it must work on different types of screen, and I have done that too. But it is 1 thing - for creating scaling screen I use layout_weight and dp instead px. But how can I scale my fonts in .xml files? Thank you.
use android:textSize = "10sp" , sp will scale fonts similar to dp.
You can use sp : scale independent pixels
sp :Scale-independent Pixels - this is like the dp unit, but it is also scaled
by the user's font size preference. It is recommend you use this unit when
specifying font sizes, so they will be adjusted for both the screen density and
the user's preference.