Double-byte system locale causes Swing component resizing - java

I'm working on a Swing app for Solaris, and I have a problem that shows up only when the system LANG variable is set to a double-byte language such as Korean. The problem is that components are being resized and this is messing up the layout of the app:
1) LANG set to Korean
2) LANG set to English
Changing the Locale in the Java code itself does not affect the display (if LANG=English and Locale is set to Korean, everything is fine. If LANG=Korean and Locale is set to English, the issue happens).
Is this caused by the LayoutManager (I'm using BorderLayout)? Is there any way to prevent this from happening? So far the only workaround I can use is changing the system locale to english right before launching the app.
Here is some example code on what I'm doing:
Box container = Box.createVerticalBox();
container.add(label1);
container.add(label2);
container.add(label3);
container.add(label4);
container.add(label5);
Border border1 = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
TitledBorder titledBorder = BorderFactory.createTitledBorder(border1, LocalizationTools.getString("STR_1"));
Dimension lDim = new Dimension(550, 100);
mypanel = new JPanel(new BorderLayout());
mypanel.setPreferredSize(lDim);
mypanel.setMaximumSize(lDim);
mypanel.setMinimumSize(lDim);
mypanel.setBorder(titledBorder);
mypanel.add(container);
Here are some strings used in the example:
1) "\ud648 \ub514\ub809\ud1a0\ub9ac"
2) "\ubcc0\uacbd \uc2dc\uac04"
3) "\ub9c8\uc9c0\ub9c9 \uc791\uc5c5"

Here are a few things to try:
Ensure that you are calling pack() on the parent Window and not interfering with any component's preferred size.
Use a compound border, adding an EmptyBorder to your TitledBorder.
While debugging, add padding to the BorderLayout and use color for highlight.
Edit your question to include an sscce that exhibits the problem; a native user may see the problem (text cut-off at bottom) more clearly.

Related

How do I set the minimum size of a JFrame and get it to adjust for frame thickness?

I am building a program and working on it on multiple operating systems. Windows 10 and Windows 7. When I set the minimum size correctly for one either Windows 10 or Windows 7 it works for that OS but messes up the other OS. Is there a way to get the setMinimumSize to adjust for border thickness? Or is there a way to get the thickness of the border on that OS? Or is there a way to get set the minimum size of the JFrame to the size it is when it opens? Any help is appreciated. Thanks.
Don't set the minimum size. It is the job of the layout manager to determine the size of a component. The layout manager will do its job on all OS.
All you need to do is add the components to your panel/frame and then use:
frame.pack();
frame.setVisible();
The pack() method invokes the layout manager so all the components will be sized properly.
Read the section from the Swing tutorial on Layout Managers for more information and working examples. I suggest you bookmark the tutorial for tutorial all the Swing basics.
i don't want the user to be able to set the size of the frame below a certain size.
It is extremely annoying when an application tells me how small (large) I can make the frame. The desktop is my space, if I want to make it smaller (larger) then you should not care. I can then make the frame larger (smaller) later if I am missing information. Your frame design should be flexible to allow resizing.
In any case you can set the minimum by doing something like:
frame.pack();
frame.setVisible();
frame.setMinimumSize( frame.getSize() );
add this method in your constructor
this.setMinimumSize(new Dimension(width,height));
I just ran into a problem like this on macOS using Java 8. I wanted the user to be able to resize the window but obey the minimum size computed by the layout manager. Unfortunately, the AWT code that controls the window size only looks at the minimum size if it has been explicitly set.
Here is the solution I came up with. I override the doLayout() method on the frame:
#Override
public void doLayout()
{
super.doLayout();
LayoutManager m = getLayout();
if (m != null) {
Dimension d = m.minimumLayoutSize(this);
setMinimumSize(d);
}
}
Now, every time the layout is recomputed, the new minimum size is cached as an explicitly set value, so that AWT will pay attention to it.

Using Java can I force the Dialog font to default to Arial

I have an application which uses the default, metal, look and feel in Unix. For Solaris 10 this means the Dialog font is being translated as Arial. For Solaris 11 the font files have moved, so my font has changed. I cannot change any files except those in my application so changing fontconfig.properties is not an option.
1) Is there any way to say Dialog=Arial (and Dialog.Bold = Arial.Bold) in the beginning of the application?
2) Since I couldn't find a way to do the above I have been using the UIManager.put("Menu.font", new Font("Arial, Font.BOLD, 12)) commands.
This seems to work (hopefully I don't miss a widget type) however my JTree, which is not using the Label.font when I use the defaults, is picking up my Label.font value when I call UIManager.put("Label.font", new Font("Arial, Font.BOLD, 12)). This happens even when I also have UIManager.put("Tree.font", new Font("Arial, Font.PLAIN, 12)).
Using the defaults my labels are bold and my tree is not. Do you have any suggestions about what could be happening with this and how I can separate the two fonts so that I can force them to be Arial but the Labels bold and the JTree plain?
Setting up the UI manager is the first thing that the application does.
Some of the values in combo boxes or on buttons are being truncated, since the font is now larger.
Surely truncated text is an abomination, but adjusting Font sizes is not a solution. Instead, use a suitable layout and pack() the enclosing Window, which "Causes this Window to be sized to fit the preferred size and layouts of its subcomponents." This example compares the same program on several platforms, each of which has different physical fonts mapped to the default font families.
As this approach is rather general in nature, it may help to edit your question to include an sscce that exhibits the particular problem you are having.
See also Should I avoid the use of set[Preferred|Maximum|Minimum]Size methods in Java Swing?

Java: remove margin / padding on a JTabbedPane

I'd like to know how to remove the margins between my JtabbedPane and my JFrame content pane and between my JTabbedPane and its internal JPanel.
I circled the margins I want to remove.
the green line is here to show the gap between the jpanel inside the jtabbedpane.
I tried to look at some method named setMargin but it doesn't exist on a JTabbedPane. I also checked the Hgap and Vgap (both = 0) on the different layout (root content pane, my jpanel, etc).
So any suggestions are welcome.
Thanks.
.
I can't post images yet.
It is up to the look and feel to decide how much space is around components inside a tabbed pane - generally it will do this based on whatever is the default for your desktop. JTabbedPane does not have methods for setting the insets around internal components.
You can set this globally for all tabbed panes (caveat: Works on MetalLookAndFeel, will probably work for Windows L&F as well, probably won't work for GTK or Nimbus look and feel which are not based on BasicLookAndFeel). This will change the appearance of all tabbed panes in the VM:
UIManager.getDefaults().put("TabbedPane.contentBorderInsets", new Insets(0,0,0,0));
UIManager.getDefaults().put("TabbedPane.tabsOverlapBorder", true);
You probably also want to make sure your JTabbedPane has an EmptyBorder(0,0,0,0) and so do the components you put in it.
If this doesn't work on your target desktop, the alternatives are
if you don't care about your tabbed panes looking different from native application tabbed panes, the (unpleasant) alternative is to write your own TabbedPaneUI
set the UI delegate for the single JTabbedPane you want to look like this to MetalTabbedPaneUI or some other UI delegate that does respond to these properties
I just struck the same problem, and nothing anyone else said seemed to be a complete solution, so I came up with this:
import javax.swing.plaf.basic.BasicTabbedPaneUI;
tabbedPane.setUI(new BasicTabbedPaneUI() {
private final Insets borderInsets = new Insets(0, 0, 0, 0);
#Override
protected void paintContentBorder(Graphics g, int tabPlacement, int selectedIndex) {
}
#Override
protected Insets getContentBorderInsets(int tabPlacement) {
return borderInsets;
}
});
It works the same without overriding the paintContentBorder method, however doing so probably makes the UI slightly more efficient during resizes or similar, as the standard one seems to delegate out to a number of other methods.
Tested on Oracle Java 6 u43 for Linux in WindowMaker, Mac OS X 10.6.7 with Mac Java 6 u37 and Windows 7 with Java 7 u07, hopefully this helps someone :-)
Margins are added by setting borders on UI elements. Have a look at the settings of the border of your JTabbedPane.

What is the best way to put spaces between objects? Can a Swing JSeparator object be an invisible separator?

I'm trying to put two buttons inside a panel using Swing widgets. Inside the NetBeans IDE, my JSeparator border property is set to (No border) in the properties pane.
Nevertheless a line appears. This is not what I would expect from a separator object. Am I doing something wrong? Coming from a background in Delphi, and C# WinForms, I expect to find some oddities in Swing. But how exactly do you make a transparent gap of a particular size, between two buttons in a panel? Do I have to play with layouts and avoid the JSeparator?
Update: It should be trivial to do this with a layout and without any separator object. So how do you do that? I am looking into the NetBeans layout customizer and properties inspector and finding no way to do it. (Answer: Layouts with Insets, instead of separators.)
You should take a look at the static utility methods on the Box class. They can be used to manufacture fixed struts that act as invisible separators; e.g.
JPanel pnl = new JPanel(new FlowLayout());
pnl.add(new JButton("Hello"));
pnl.add(Box.createHorizontalStrut(10)); // Fixed width invisible separator.
pnl.add(new JButton("Goodbye");
This produces more compact code than creating / configuring a JPanel yourself with appropriate minimum, maximum and preferred dimensions.
JSeparator is meant to be a visible separator between components.
From the javadoc for JSeparator:
JSeparator provides a general purpose component for implementing divider lines - most commonly used as a divider between menu items that breaks them up into logical groupings.
If you want to put a component in between two components that is invisible just use an JPanel instead. Then set the size of the panel with setPreferedSize() and setMin/MaxSize().
You don't need JSeparator. Most layouts allow you to set gap (space) between compoponents. And Box class can be particularly useful.
Using addSeparator with a value of 1 for height makes it invisible for me, for example:
MyJToolBar.addSeparator(new Dimension(20, 1));

Undecorate JInternalFrame on MacOS

I am trying to undecorate a JInternalFrame, i.e. remove the default titlebar using the following code;
BasicInternalFrameUI ui = (BasicInternalFrameUI)internalFrame.getUI();
ui.getNorthPane().setPrefrredSize(new Dimension(0,0));
I works on windows but the second line throws a NullPointerException on MacOS
Any ideas why and how to get round it?
On Mac, the JInternalFrame doesn't have a north pane. Only execute the code on none Mac OS platforms;
// only remove the northpanel for none Mac OS
if(!(System.getProperty("os.name").startsWith("Mac OS"))){
BasicInternalFrameUI ui = (BasicInternalFrameUI) getUI();
ui.getNorthPane().setPrefrredSize(new Dimension(0,0));
}
So much about cross platform :-(
I don't use a Mac so I don't know what is causing the problem.
A JInternalFrame without the title bar loses its ability to be dragged. You should be able to accomplish the same goal by just adding a JPanel to the desktop. You would need to set the bounds of the panel. You might also want to use one of the internal frame custom borders on the panel:
UIManager.getBorder("InternalFrame.paletteBorder");
UIManager.getBorder("InternalFrame.optionDialogBorder");
Or maybe another option is to use:
internalFrame.putClientProperty("JInternalFrame.isPalette", Boolean.TRUE);
This will replace the title bar with a small palette that can be used to drag the internal frame without the buttons or title.

Categories