简体   繁体   English

Swing Java旋转JLabel但文本被删除

[英]Swing Java Rotate JLabel but text be erased

I'm using swing Java to try to do something with java. 我正在使用swing Java尝试用java做一些事情。 Now I want to rotate JLabel and I did that. 现在我想要旋转JLabel,我做到了。 But unfortunelately, a part of my text in JLabel is erased (as in the image below). 但不幸的是,我在JLabel中的部分文本被删除了(如下图所示)。 I have tried search but seem no one has problems as same as mine. 我试过搜索,但似乎没有人像我一样有问题。 I guess it's occured caused JLabels they overlaped. 我猜它发生了导致它们重叠的JLabel。

在此输入图像描述

and this is my code 这是我的代码

serviceName[j] = new JLabel(name){
    protected void paintComponent(Graphics g) {

        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        AffineTransform aT = g2.getTransform();
        Shape oldshape = g2.getClip();
        aT.rotate(Math.toRadians(300));
        g2.setTransform(aT);
        g2.setClip(oldshape);
        super.paintComponent(g);
    }
};

Can you give me the way to solved it 你能帮我解决一下吗?

You should restore original transform and clip after your painting. 您应该在绘画后恢复原始变换和剪辑。 Like this 像这样

protected void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    AffineTransform aT = g2.getTransform();
    Shape oldshape = g2.getClip();

    g2.rotate(Math.toRadians(300));
    super.paintComponent(g);

    g2.setTransform(aT);
    g2.setClip(oldshape);
}

You may find some hints from this small program. 您可以从这个小程序中找到一些提示。 Experiment on the values of setPrefferedSize to have more ideas. 试验setPrefferedSize的值以获得更多想法。 If you still can't solve the problem, please edit and add more codes in your question above. 如果仍然无法解决问题,请在上面的问题中修改并添加更多代码。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import javax.swing.*;

public class InclinedLabels extends JFrame{
    /** Creates a new instance of InclinedLabels */
    public InclinedLabels() {

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        JPanel jPanel1 = new JPanel();
        jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        add(jPanel1);

        JPanel jPanel2 = new JPanel();
        jPanel2.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jPanel2.setPreferredSize(new Dimension(10, 100));
        add(jPanel2, BorderLayout.NORTH);


        jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jPanel1.setPreferredSize(new java.awt.Dimension(200, 200));
        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-400)/2, (screenSize.height-352)/2, 300, 352);



        String str = "The quick brown fox jumps over the lazy dog";
        String[] word = str.split(" ");
        JLabel[] serviceName = new JLabel[str.length()];
        String name;
        for (int j=0; j<word.length; j++) {
            name = word[j];
            serviceName[j]  = new JLabel(name){
                protected void paintComponent(Graphics g) {

                    Graphics2D g2 = (Graphics2D)g;
                    g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
                    AffineTransform aT = g2.getTransform();
                    Shape oldshape = g2.getClip();
                    aT.rotate(Math.toRadians(300));
                    g2.setTransform(aT);
                    g2.setClip(oldshape);
                    super.paintComponent(g);
                }
            };
            serviceName[j].setPreferredSize(new Dimension(50,20));
            serviceName[j].setBorder(BorderFactory.createLineBorder(Color.RED));
            jPanel1.add(serviceName[j]);
        }

    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new InclinedLabels().setVisible(true);
            }
        });
    }
}

Update: I found a much closer hint that may solve this problem. 更新:我找到了一个更接近的提示,可以解决这个问题。 The big factor here is the component layout. 这里最重要的因素是组件布局。 The null layout allows overlapping of JLabel components so it is the most appropriate layout to be used here. null布局允许重叠JLabel组件,因此它是此处使用的最合适的布局。 Then you have to customize the location and size of the labels through the setBounds method. 然后,您必须通过setBounds方法自定义标签的位置和大小。 In the code below there is serviceName[j].setBounds(xOffset + j*20,180, 170, 15); 在下面的代码中有serviceName[j].setBounds(xOffset + j*20,180, 170, 15); So in every loop iteration, the x location of the label is increased by 20. The size of all labels is 170 by 15. I also placed temporary borders to the components to help in understanding the output. 因此,在每次循环迭代中,标签的x位置增加20.所有标签的大小为170 x 15.我还为组件放置了临时边框,以帮助理解输出。

import java.awt.*;
import java.awt.geom.AffineTransform;
import javax.swing.*;

public class InclinedLabels extends JFrame{

    /** Creates a new instance of InclinedLabels */
    public InclinedLabels() {

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-360)/2, (screenSize.height-352)/2, 360, 352);

        JPanel jPanel1 = new JPanel();
        jPanel1.setBorder(BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jPanel1.setLayout(null);  // null layout allows overlapping of components
        add(jPanel1);

        JPanel jPanel2 = new JPanel();
        jPanel2.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jPanel2.setPreferredSize(new Dimension(10, 100));
        add(jPanel2, BorderLayout.NORTH);


        String str = "The quick brown fox jumpsssssssssssss123456 over the lazy dogssssssssssssss123456";
        String[] word = str.split(" ");
        JLabel[] serviceName = new JLabel[str.length()];
        String name;
        int xOffset = 30;
        for (int j=0; j<word.length; j++) {
            name = word[j];
            serviceName[j]  = new JLabel(name){
                protected void paintComponent(Graphics g) {
                    Graphics2D g2 = (Graphics2D)g;
                    g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
                    AffineTransform aT = g2.getTransform();
                    Shape oldshape = g2.getClip();
                    aT.rotate(Math.toRadians(300));
                    g2.setTransform(aT);
                    g2.setClip(oldshape);
                    super.paintComponent(g2);

                }
            };

            serviceName[j].setBounds(xOffset + j*20,180, 170, 15); // experiment here
            serviceName[j].setBorder(BorderFactory.createLineBorder(Color.RED));

            jPanel1.add(serviceName[j]);
        }

    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new InclinedLabels().setVisible(true);
            }
        });
    }

}

The limitation that I found in the code above is the width of the parent panel. 我在上面的代码中找到的限制是父面板的宽度。 In the example, the label having the text dogssssssssssssss123456 was not printed in whole. 在该示例中,具有文本dogssssssssssssss123456的标签未完整打印。 This can be overcome by increasing the width of the frame which in turn increases the width of jPanel1 . 这可以通过增加框架的宽度来克服,这又增加了jPanel1的宽度。

Your JLabel subclass should also override getPreferredSize() to report the size it will be when it is rotated; 您的JLabel子类还应覆盖getPreferredSize()以报告旋转时的大小; otherwise the any layout manager that uses asks your component for its preferred size will use JLabel's version, which assumes the text is drawn horizontally. 否则,任何使用询问组件的首选大小的布局管理器都将使用JLabel的版本,该版本假定文本是水平绘制的。

Instead of attempting to rotate the component, another approach would be to create a Text Icon and add the Icon to a JLabel. 另一种方法是创建文本图标并将图标添加到JLabel,而不是尝试旋转组件。

Once you have created the TextIcon you can then create a Rotated Icon to add to the label. 创建TextIcon您可以创建一个旋转图标以添加到标签。 The RotatedIcon will calculate the proper size of the Icon so therefore the size of the label will also be correct and no custom painting is required. RotatedIcon将计算Icon的正确大小,因此标签的大小也是正确的,不需要自定义绘画。

So the basic code would be something like: 所以基本代码是这样的:

JLabel label = new JLabel();
TextIcon textlIcon = new TextIcon(label, "Rotated Text");
label.setIcon( new RotatedIcon(textIcon, 300) );

Edit: 编辑:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.border.*;
import javax.swing.table.*;
import java.io.*;

public class SSCCE extends JPanel
{
    public SSCCE()
    {
        OverlapLayout layout = new OverlapLayout(new Point(20, 0));
        setLayout( layout );

        addLabel("one");
        addLabel("two");
        addLabel("three or more");
        addLabel("four");
    }

    private void addLabel(String text)
    {
        JLabel label = new JLabel();
        TextIcon textIcon = new TextIcon(label, text);
        label.setIcon( new RotatedIcon(textIcon, 300) );
        label.setVerticalAlignment(JLabel.BOTTOM);
        add(label);
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new SSCCE());
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}

This example also uses the Overlap Layout so the labels can be painted over top of one another. 此示例还使用“ 重叠布局”,以便可以将标签涂在彼此之上。

import java.awt.Color; 
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;

public class Test {
    public static void main(String[] args) {
        // Create the first label, which will be rotated later.
        Test.RotateLabel one = new Test.RotateLabel( "Rotated", 100, 100 );
        one.setRotation( 270 );
        JLayeredPane pane = new JLayeredPane();
        pane.setLayer( one, JLayeredPane.DEFAULT_LAYER );
        pane.add( one );
        pane.setBorder(new javax.swing.border.LineBorder(Color.BLACK,1));
        // Put the container pane in a frame and show the frame.
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.add( pane );
        frame.setSize( 500, 500 );
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );
    }

    static class RotateLabel extends JLabel {
        private static final long serialVersionUID = 1L;
        private int angle = 0;
        public RotateLabel( String text, int x, int y ) {
        super( text );
        setBorder( new javax.swing.border.CompoundBorder( 
            new javax.swing.border.LineBorder( Color.red, 1), getBorder() ) );
        int width = getPreferredSize().width;
        int height = getPreferredSize().height;
        setBounds(x, y, width, height);
    }

    @Override
    public void paintComponent( Graphics g ) {
        Graphics2D gx = (Graphics2D) g;
        Shape old = gx.getClip();
        gx.rotate(-Math.toRadians(45), getWidth() / 2, getHeight() / 2);
        gx.setClip(old);
        super.paintComponent(gx);
    }

    public void setRotation( int angle ) { this.angle = angle; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM