绘制两个重叠的JLabel

时间:2018-06-17 00:46:59

标签: java swing awt

我想把JLabel画在另一个上面。 我重写paint(),以便在调用super.paint()之后绘制第二个JLabel。 然而,第二个JLabel根本没有画(因为它没有显示,我认为)。 我怎样才能达到这个效果?

public class OverlaidJLabel extends JLabel {

    private String upperText;

    public OverlaidJLabel(){

    }

    public void setUpperText(String upperText){
        this.upperText = upperText;
    }

    @Override
    public void paint(Graphics g){
        super.paint(g);
        JLabel upperLabel = new JLabel(upperText);
        upperLabel.paint(g);
    }
}

1 个答案:

答案 0 :(得分:3)

这里有一些大问题:

  1. 您不希望在这种情况下覆盖绘画,而是paintComponent
  2. 您永远不想在绘画方法中创建组件。这些方法应该只用于绘画和绘画,因为你将多次创建组件(因为绘制方法可以多次调用 - 完全不受你的控制),只需创建一次,而你不想要因为这会阻碍你对GUI的敏感性,所以会慢慢减少绘画速度。
  3. 创建一个从未添加到GUI的组件(例如upperLabel)是没有意义的。调用它的paint方法绝对没有任何意义(正如你所发现的那样)。
  4. 一般来说,你会希望使用合成而不是继承。
  5. 好多了:

    • 如果要在文本顶部放置文本,可以创建两个JLabel(单独),并使用适当的布局管理器或使用JLayeredPane将它们放在彼此的顶部。
    • 或者您可以将您的绘画和绘画覆盖在一个组件中,可能是paintComponent覆盖JPanel。

    例如,一个可能过度可以使用包含两个JLabel的JLayeredPane。下面的一个简单示例使用仅包含文本的JLabel,尽管您也可以使用ImageIcons实现,并允许更改每个JLabel的字体,前景色等...

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.GridBagLayout;
    import java.awt.event.ComponentAdapter;
    import java.awt.event.ComponentEvent;
    
    import javax.swing.JLabel;
    import javax.swing.JLayeredPane;
    import javax.swing.JPanel;
    
    @SuppressWarnings("serial")
    public class MyLabel extends JLayeredPane {
        // labels to hold texts. label1 is the lower label
        private JLabel label1 = new JLabel();
        private JLabel label2 = new JLabel();
    
        public MyLabel(String text1, String text2) {
    
            // just so I can see the text separately:
            label2.setForeground(Color.RED);
    
            // set text
            label1.setText(text1);
            label2.setText(text2);
    
            // JPanels to hold the labels. GridBagLayout will center the labels
            JPanel baseComponent1 = new JPanel(new GridBagLayout());
            JPanel baseComponent2 = new JPanel(new GridBagLayout());
    
            // add labels to the JPanels
            baseComponent1.add(label1);
            baseComponent2.add(label2);
    
            // have to be able to see through the JPanels
            baseComponent1.setOpaque(false);
            baseComponent2.setOpaque(false);
    
            // add to the JLayeredPane label2 above label1
            add(baseComponent1, JLayeredPane.DEFAULT_LAYER);
            add(baseComponent2, JLayeredPane.PALETTE_LAYER);
    
            // If the overall component resizes, resize the 
            // container base JPanels
            addComponentListener(new ComponentAdapter() {
                @Override
                public void componentResized(ComponentEvent e) {
                    baseComponent1.setSize(MyLabel.this.getSize());
                    baseComponent2.setSize(MyLabel.this.getSize());
                    repaint();
                }
            });
        }
    
        // preferred size depends on the largest dimensions
        // of the two JLabels
        @Override
        public Dimension getPreferredSize() {
            Dimension size1 = label1.getPreferredSize();
            Dimension size2 = label2.getPreferredSize();
            int w = Math.max(size1.width, size2.width);
            int h = Math.max(size1.height, size2.height);
            return new Dimension(w, h);
        }
    }
    

    它可以像这样进行测试:

    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    @SuppressWarnings("serial")
    public class MyLabelTest extends JPanel {
        public MyLabelTest() {
            add(new MyLabel("Test .............................. String 1", "Number 2"));
        }
    
        private static void createAndShowGui() {
            MyLabelTest mainPanel = new MyLabelTest();
    
            JFrame frame = new JFrame("MyLabelTest");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }
    

    我的下一次迭代是将更改方法添加到MyLabel以允许更改字体,文本和前景:

        public void setFont1(Font font) {
            label1.setFont(font);
        }
    
        public void setFont2(Font font) {
            label2.setFont(font);
        }
    
        public void setText1(String text) {
            label1.setText(text);
        }
    
        public void setText2(String text) {
            label2.setText(text);
        }
    
        public void setForeground1(Color fg) {
            label1.setForeground(fg);
        }
    
        public void setForeground2(Color fg) {
            label2.setForeground(fg);
        }