2013-04-15 18 views
6

私のアプリケーションでは、フォントサイズが200以上のラベルがあります。このラベルには大きな上下の(不規則な)ギャップが含まれています。どうすれば削除できますか?大きなサイズのJava swingラベルのギャップを削除するには

これは私のコードです:

package Core; 

import java.awt.Font; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 

import javax.swing.BorderFactory; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 

public class LabelDemo extends JPanel { 
    public LabelDemo() { 
     super(new GridBagLayout()); 
     JLabel label2; 
     GridBagConstraints c = new GridBagConstraints(); 
     c.gridx = 0; 
     c.gridy = 0; 
     // Create the other labels. 
     label2 = new JLabel("Text-Only Label"); 
     label2.setBorder(BorderFactory.createTitledBorder("aaaaaaaa")); 
     label2.setFont(new Font("Verdana", Font.PLAIN, (int) 220)); 
     // label2.setBorder(new EmptyBorder(-50, 0, 0, 0)); 

     // Add the labels. 
     add(label2, c); 
    } 

    /** 
    * Create the GUI and show it. For thread safety, this method should be invoked from the event dispatch thread. 
    */ 
    private static void createAndShowGUI() { 
     // Create and set up the window. 
     JFrame frame = new JFrame("LabelDemo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     // Add content to the window. 
     frame.add(new LabelDemo()); 

     // Display the window. 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     // Schedule a job for the event dispatch thread: 
     // creating and showing this application's GUI. 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       // Turn off metal's use of bold fonts 
       UIManager.put("swing.boldMetal", Boolean.FALSE); 

       createAndShowGUI(); 
      } 
     }); 
    } 
} 

また、私は私の最後のポストを試してみてください:How to change gap in swing labelと実験インセットを持つが、これは、Linuxに違って見えるとWindows

このギャップを削除する方法をいくつか良い方法はあります?

+0

あなたはすべての文字が先頭に整列されたいことを意味しますか? –

+0

ギャップボットが存在しないことを意味する場合は – hudi

+1

'JLabel.getPreferredSize()'をオーバーライドしてより低い高さを返し、 'JLabel.setVerticalAlignment(JLabel.BOTTOM);'を使用することができます。これはどうにかして 'LabelUI'をだまし、それを上にずっと近づけさせます。もう1つの解決策は、自分の好みのサイズを返すことができ、あなたが好きな場所にテキストをペイントすることができる独自のコンポーネントを作成することです。 –

答えて

9

JDigitはあなたにいくつかのアイデアを与えることがあります。

  • それは、高解像度BufferedImageをダウンサンプリングし、ジオメトリを制御するためのpaintComponent()をオーバーライドします。

  • setBorderPainted(false)を使用してborderPaintedプロパティを設定します。

  • カスタムハイライトにはFocusHandlerが使用されます。

image

補遺:hereを述べたように、根本的な問題は、フォントの高さに含まれるものとしてFontMetricsで定義され、フォントの主要あります。 @ Guillaume Poletのコメントで示唆されているように、自分の好きなところにテキストをレンダリングすることができますJComponentTextLayouthereを参照)を使用して、以下に示すように境界を計算することができる。

長所:配置を

  • 絶対コントロール。

  • TexteLayoutに基づく境界FontMetricsに基づくジオメトリ。

短所:

  • ませんIconサポート。

  • HTMLはサポートされていません。 JComponent著者は「あなたがJPanelに部品を入れて、JPanel上の境界線を設定することをお勧めします。」という

注意

Unleaded image

import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Rectangle; 
import java.awt.font.FontRenderContext; 
import java.awt.font.TextLayout; 
import javax.swing.BorderFactory; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

/** 
* @see https://stackoverflow.com/a/16014525/230513 
*/ 
public class UnleadedTest { 

    private static class Unleaded extends JComponent { 

     private Font font = new Font("Verdana", Font.PLAIN, 144); 
     private FontRenderContext frc = new FontRenderContext(null, true, true); 
     private String text; 
     private TextLayout layout; 
     private Rectangle r; 

     public Unleaded(String text) { 
      this.text = text; 
      calcBounds(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(r.width, r.height); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g; 
      calcBounds(); 
      layout.draw(g2d, -r.x, -r.y); 
     } 

     private void calcBounds() { 
      layout = new TextLayout(text, font, frc); 
      r = layout.getPixelBounds(null, 0, 0); 
     } 
    } 

    private void display() { 
     JFrame f = new JFrame("Unleaded"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     Unleaded label = new Unleaded("Unleaded"); 

     JPanel panel = new JPanel(); 
     panel.setBorder(BorderFactory.createTitledBorder("Title")); 
     panel.add(label); 
     f.add(panel); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new UnleadedTest().display(); 
      } 
     }); 
    } 
} 
+0

'TextLayout'を使って関連する[example](http://stackoverflow.com/a/8282330/230513)も参照してください。 – trashgod

+0

JDigitはボタンではないので、これは私には役に立たないと思います – hudi

+0

@hudi undecorated JButtonはJLabelやJPanelよりも優れています – mKorbel

3

"BasicLabelUI" を拡張し、 "保護された文字列layoutCL()" メソッドをオーバーライドすることですこれを行うには "正しい方法"。これは、ラベル内のすべてをレイアウトするためのメソッドであり、JLabelのgetPreferredSize()が呼び出されたときに呼び出されます。したがって、このメソッドはコンポーネントの高さを決定します。

あなたが深く十分にあなたは高さがSwingUtilitiesに次の行によって決定されることがわかりますドリルダウンする場合:1021クラス(layoutCLで使用されている):

textR.height = fm.getHeight(); 

ので、ラベルが原因とされていません空白はフォントである。ラベルは、FontMetricsオブジェクトがそのサイズのフォントの最大高さと言うことにちょうど一致します。

最も簡単な方法はおそらく不正行為だと思われます。サイズ計算に強制しないでください。以下は、あなたが試すことができるカスタムのLabelUIコンポーネントの例です。たとえば、変数を 'dy'に強制して '-40'にすると、テキストは一番上に表示されます。より耐久性のあるものにしたい場合は、ラベルの文字列内のすべてのラベルをチェックし、その最大高さを測定し、layoutCLメソッドでそれを使用することができます。しかし、それは明らかにもっとうまくいく。境界線を変更

package Core; 

import sun.swing.SwingUtilities2; 
import javax.swing.*; 
import javax.swing.plaf.LabelUI; 
import javax.swing.plaf.basic.BasicLabelUI; 
import javax.swing.text.View; 
import java.awt.*; 

public class LabelDemo extends JPanel { 

    public LabelDemo() { 
     super(new GridBagLayout()); 
     JLabel label2; 
     GridBagConstraints c = new GridBagConstraints(); 
     c.gridx = 0; 
     c.gridy = 0; 
     // Create the other labels. 
     label2 = new JLabel("Text-Only Label"); 
     label2.setVerticalAlignment(SwingUtilities.TOP); 
     label2.setVerticalTextPosition(SwingUtilities.TOP); 
     label2.setUI(SkinnyLabelUI.createUI(label2)); 
     label2.setBorder(BorderFactory.createTitledBorder("aaaaaaaa")); 
     label2.setFont(new Font("Verdana", Font.PLAIN, (int) 220)); 
     // label2.setBorder(new EmptyBorder(-50, 0, 0, 0)); 

     // Add the labels. 
     add(label2, c); 
    } 

    /** 
    * Create the GUI and show it. For thread safety, this method should be 
    * invoked from the event dispatch thread. 
    */ 
    private static void createAndShowGUI() { 
     // Create and set up the window. 
     JFrame frame = new JFrame("LabelDemo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     // Add content to the window. 
     frame.add(new LabelDemo()); 

     // Display the window. 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     // Schedule a job for the event dispatch thread: 
     // creating and showing this application's GUI. 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       // Turn off metal's use of bold fonts 
       UIManager.put("swing.boldMetal", Boolean.FALSE); 

       createAndShowGUI(); 
      } 
     }); 
    } 

    private static class SkinnyLabelUI extends BasicLabelUI { 

     private static final SkinnyLabelUI labelUI = new SkinnyLabelUI(); 

     public static LabelUI createUI(JComponent c) { 
      return labelUI; 
     } 

     protected String layoutCL(
      JLabel label, 
      FontMetrics fm, 
      String text, 
      Icon icon, 
      Rectangle viewR, 
      Rectangle iconR, 
      Rectangle textR) { 
      int verticalAlignment = label.getVerticalAlignment(); 
      int horizontalAlignment = label.getHorizontalAlignment(); 
      int verticalTextPosition = label.getVerticalTextPosition(); 
      int horizontalTextPosition = label.getHorizontalTextPosition(); 

      if (icon != null) { 
       iconR.width = icon.getIconWidth(); 
       iconR.height = icon.getIconHeight(); 
      } else { 
       iconR.width = iconR.height = 0; 
      } 

      /* Initialize the text bounds rectangle textR. If a null 
      * or and empty String was specified we substitute "" here 
      * and use 0,0,0,0 for textR. 
      */ 

      boolean textIsEmpty = (text == null) || text.equals(""); 
      int lsb = 0; 
      int rsb = 0; 
      /* Unless both text and icon are non-null, we effectively ignore 
      * the value of textIconGap. 
      */ 
      int gap; 

      View v; 
      if (textIsEmpty) { 
       textR.width = textR.height = 0; 
       text = ""; 
       gap = 0; 
      } else { 
       int availTextWidth; 
       gap = (icon == null) ? 0 : label.getIconTextGap(); 

       if (horizontalTextPosition == SwingUtilities.CENTER) { 
        availTextWidth = viewR.width; 
       } else { 
        availTextWidth = viewR.width - (iconR.width + gap); 
       } 
       v = (label != null) ? (View) label.getClientProperty("html") : null; 
       if (v != null) { 
        textR.width = Math.min(availTextWidth, 
         (int) v.getPreferredSpan(View.X_AXIS)); 
        textR.height = (int) v.getPreferredSpan(View.Y_AXIS); 
       } else { 
        textR.width = SwingUtilities2.stringWidth(label, fm, text); 
        lsb = SwingUtilities2.getLeftSideBearing(label, fm, text); 
        if (lsb < 0) { 
         // If lsb is negative, add it to the width and later 
         // adjust the x location. This gives more space than is 
         // actually needed. 
         // This is done like this for two reasons: 
         // 1. If we set the width to the actual bounds all 
         // callers would have to account for negative lsb 
         // (pref size calculations ONLY look at width of 
         // textR) 
         // 2. You can do a drawString at the returned location 
         // and the text won't be clipped. 
         textR.width -= lsb; 
        } 
        if (textR.width > availTextWidth) { 
         text = SwingUtilities2.clipString(label, fm, text, 
          availTextWidth); 
         textR.width = SwingUtilities2.stringWidth(label, fm, text); 
        } 
        textR.height = fm.getHeight(); 
        System.out.println("font height: " + textR.height); 
       } 
      } 


      /* Compute textR.x,y given the verticalTextPosition and 
      * horizontalTextPosition properties 
      */ 

      if (verticalTextPosition == SwingUtilities.TOP) { 
       if (horizontalTextPosition != SwingUtilities.CENTER) { 
        textR.y = 0; 
       } else { 
        textR.y = -(textR.height + gap); 
       } 
      } else if (verticalTextPosition == SwingUtilities.CENTER) { 
       textR.y = (iconR.height/2) - (textR.height/2); 
      } else { // (verticalTextPosition == BOTTOM) 
       if (horizontalTextPosition != SwingUtilities.CENTER) { 
        textR.y = iconR.height - textR.height; 
       } else { 
        textR.y = (iconR.height + gap); 
       } 
      } 

      if (horizontalTextPosition == SwingUtilities.LEFT) { 
       textR.x = -(textR.width + gap); 
      } else if (horizontalTextPosition == SwingUtilities.CENTER) { 
       textR.x = (iconR.width/2) - (textR.width/2); 
      } else { // (horizontalTextPosition == RIGHT) 
       textR.x = (iconR.width + gap); 
      } 

      // WARNING: DefaultTreeCellEditor uses a shortened version of 
      // this algorithm to position it's Icon. If you change how this 
      // is calculated, be sure and update DefaultTreeCellEditor too. 

      /* labelR is the rectangle that contains iconR and textR. 
      * Move it to its proper position given the labelAlignment 
      * properties. 
      * 
      * To avoid actually allocating a Rectangle, Rectangle.union 
      * has been inlined below. 
      */ 
      int labelR_x = Math.min(iconR.x, textR.x); 
      int labelR_width = Math.max(iconR.x + iconR.width, 
       textR.x + textR.width) - labelR_x; 
      int labelR_y = Math.min(iconR.y, textR.y); 
      int labelR_height = Math.max(iconR.y + iconR.height, 
       textR.y + textR.height) - labelR_y; 

      int dx, dy; 

      if (verticalAlignment == SwingUtilities.TOP) { 
       dy = viewR.y - labelR_y; 
      } else if (verticalAlignment == SwingUtilities.CENTER) { 
       dy = (viewR.y + (viewR.height/2)) - (labelR_y + (labelR_height/2)); 
      } else { // (verticalAlignment == BOTTOM) 
       dy = (viewR.y + viewR.height) - (labelR_y + labelR_height); 
      } 

      if (horizontalAlignment == SwingUtilities.LEFT) { 
       dx = viewR.x - labelR_x; 
      } else if (horizontalAlignment == SwingUtilities.RIGHT) { 
       dx = (viewR.x + viewR.width) - (labelR_x + labelR_width); 
      } else { // (horizontalAlignment == CENTER) 
       dx = (viewR.x + (viewR.width/2)) 
        - (labelR_x + (labelR_width/2)); 
      } 

      /* Translate textR and glypyR by dx,dy. 
      */ 

      textR.x += dx; 
      textR.y += dy; 

      iconR.x += dx; 
      iconR.y += dy; 

      if (lsb < 0) { 
       // lsb is negative. Shift the x location so that the text is 
       // visually drawn at the right location. 
       textR.x -= lsb; 

       textR.width += lsb; 
      } 
      if (rsb > 0) { 
       textR.width -= rsb; 
      } 

      return text; 
     } 
    } 
} 
+0

+1このアプローチは 'JLabel'の機能を保持します。関連する例が見られる[ここ](http://stackoverflow.com/a/3597688/230513)。 – trashgod

0

は役立つかもしれないオフセット:

int OFFSET_TOP=50,OFFSET_BOTTOM=50; 
label.setBorder(new TitledBorder(TITLE){ 
    @Override 
    public Insets getBorderInsets(Component c, Insets insets){ 
     return new Insets(insets.top - OFFSET_TOP, insets.left, insets.bottom - OFFSET_BOTTOM, insets.right); 
    } 
}); 
+0

この質問に引用された同じトピックに関するhudiの前回の質問に対するこの[回答](http://stackoverflow.com/a/10158028/230513)では、同様のアプローチが提案されました。残念ながら、定数はプラットフォーム固有のフォントメトリックに依存します。 – trashgod

関連する問題