8

When used in a Windows 7 JToolBar, a JToggleButton sometimes truncates its label text.

See an example in the code below. A toggle button that begins with an upper-case 'W' will be truncated; one that begins with a space (or even lower-case 'w') will not.

Does this happen only under Windows? Can someone explain why this happens?

// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6386636

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

/////////////////////// new class

public class Truncation_Example extends JToolBar {

   private static final long serialVersionUID = 1L;

   /////////////////////// object attributes

   JToggleButton toggle_Good;
   JToggleButton toggle_Bad;

   /////////////////////// constructors

   public Truncation_Example() {
      toggle_Good = new JToggleButton(new Action_Good());
      toggle_Bad = new JToggleButton(new Action_Bad());

      this.add(toggle_Good);
      this.add(toggle_Bad);
   }

   /////////////////////// inner classes

   public class Action_Good extends AbstractAction {
      private static final long serialVersionUID = 1L;
      public Action_Good() {
         putValue(Action.NAME, " Wrap Good "); // note added space to prevent truncation
      }
      @Override
         public void actionPerformed(ActionEvent e) {
            System.out.println("Toggle: " + toggle_Good.getText());
      }
   }

   public class Action_Bad extends AbstractAction {
      private static final long serialVersionUID = 1L;
      public Action_Bad() {
         putValue(Action.NAME, "Wrap Bad"); // label will be truncated if it begins with 'W'
      }
      @Override
         public void actionPerformed(ActionEvent e) {
            System.out.println("Toggle: " + toggle_Bad.getText());
      }
   }

   /////////////////////// main

   public static void main(String[] args) {
      UIManager.put("ToggleButton.select", Color.GREEN);

      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            JFrame frame = new JFrame("Truncation_Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JToolBar toolBar = new Truncation_Example();
            frame.add(toolBar, BorderLayout.NORTH);
            frame.setSize(500, 400);
            frame.setVisible(true);
         }
      });
   }
}
ctype.h
  • 1,470
  • 4
  • 20
  • 34
  • 3
    This doesn't answer your question exactly, but does using `setMinimumSize()` / `setPreferredSize()` on the `JToggleButton` help protect against the text truncation? – sampson-chen Oct 31 '12 at 16:32
  • 2
    @sampson-chen using any of the setXXSize is ... wrong, always - [some reasons](http://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi/7229519#7229519) – kleopatra Oct 31 '12 at 17:04
  • @Dennis O'Neill I can't simulating your issue, whats happened by this.doLayout();, f.i. I remember correctly, dirty hack is add space before and after String for ButtonComponents, same as is demonstrated in your code example, not about lover or camel case or to enlagre the Insets – mKorbel Oct 31 '12 at 18:09
  • Without looking in depth and with a debugger, it seems that there is a problem in this method: `javax.swing.plaf.basic.BasicGraphicsUtils.getPreferredButtonSize(AbstractButton, int)` – Guillaume Polet Oct 31 '12 at 18:33
  • @sampson-chen: No, changing minimum size, preferred size, or changing insets have no effect. – Dennis O'Neill Oct 31 '12 at 18:34
  • @mKorbel: Yes, if you add a space before the 'W', the label renders correctly. A trailing space is not required but helps center the text. – Dennis O'Neill Oct 31 '12 at 18:37
  • @Dennis O'Neill is there some special reason to use JToolBar, use JMenuBar uinstead, advantage is that could be dragable only inside containers bounds – mKorbel Oct 31 '12 at 18:52
  • 2
    No problem on Mac OS X; don't neglect to `pack()` the frame before `setSize()`. – trashgod Oct 31 '12 at 19:09
  • @trashgod: Thanks for checking on the Mac. Calling `pack()` has no effect. – Dennis O'Neill Oct 31 '12 at 19:58
  • @trashgod I tried the `pack()` trick too on my Windows 7 and it didn't change a thing. I think there might be a real problem in Oracle's JVM here. – Guillaume Polet Oct 31 '12 at 20:28
  • 1
    @GuillaumePolet: Very likely; I'm also wary of Windows OS support for font metrics. – trashgod Oct 31 '12 at 20:37
  • JPopup (chameleon one time contaimer, second JComponent) and JToolbars are heavyweight, then have to pack separatelly, I think that docking by using JFrames BorderLayout can to create mess, [or together Win7 / Font / Theme ???](http://stackoverflow.com/questions/11309861/bug-or-feature-swing-default-gui-font-incorrect-for-win6) – mKorbel Nov 01 '12 at 08:16

1 Answers1

1

This problem is LookAndFeel-dependant, let me explain why...

This example indeed truncates text if MetalLookAndFeel is installed (it is by default). With any other L&F (Basic, Windows, Nimbus, even on my own L&F) i don't see this problem. Seems that MetalLookAndFeel has some kind of bug in the MetalButtonUI or in the L&F constants that forces incorrect button text rendering.

I am not sure what it could be - you can simply debug MetalButtonUI class to see what happens in the sizes calculations. Anyway, i doubt you will change anything even if you find the root of this problem.

Mikle Garin
  • 10,083
  • 37
  • 59
  • 1
    It's interesting to me that truncation occurs only when the beginning character (index = 0) is a `W`. I haven't seen it happen with any other character, or at any other index. – Dennis O'Neill Nov 01 '12 at 15:55
  • @DennisO'Neill well, it might also be some specific font size calcualtion issue since fonts are usually also different in different L&Fs. – Mikle Garin Nov 01 '12 at 16:26