标签数组的最后一个标签定位错误

Last label of labels array is positioning wrong

我正在尝试使用 swing 在 Java 中创建一个二进制时钟。 我一开始就遇到了一个问题,标签数组的最后一个元素总是出现在 0 x 轴位置和 y 轴的中间。

我不想使用任何布局管理器,因为我想在我的面板上放置一些圆形图像。

到目前为止,这是我的代码:

import javax.swing.*;

@SuppressWarnings("serial")
public class MainFrame extends JFrame {

public MainFrame()
{
    setLayout(null);
    JFrame frame = new JFrame("Binary Clock");
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
    frame.setVisible(true);
    frame.setSize(600,400);
    frame.setResizable(false);

    JLabel label[] = new JLabel[5];
    for(int i = 0; i < 5; i++)
    {
        label[i] = new JLabel();
        label[i].setLocation(i * 10, i * 10);
        label[i].setSize(30, 10);
        label[i].setText("TEST");
        frame.add(label[i]);
    }       
}

public static void main(String[] args)
{
    new MainFrame();
}
}

我在这里发现了类似的问题:

setLocation of Label

但没有答案如何在没有布局管理器的情况下做到这一点。

我试过调整大小和其他东西,但只有 setText() 可以做任何改变,除此之外没有任何效果。

谢谢!

我不是 Swing 专家,所以我不知道 null 布局管理器会给你带来什么后果,但据我所知,这没什么用,所以请考虑使用适当的布局管理器而不是 null .
无论如何,您的问题似乎是由于您将 null 布局设置为当前由构造函数初始化的 this 实例,而不是来自 form regerence 的实例。

所以

setLayout(null);// represents this.setLayout(..), not frame.setLayout(..)
JFrame frame = new JFrame("Binary Clock");

使用

JFrame frame = new JFrame("Binary Clock");
frame.setLayout(null);

我也不确定为什么您的 class 扩展了 JFrame。您的代码实际上看起来并不需要 JFrame 的任何继承功能。

Pshemo 的回答提供了为什么你在添加最后一个标签时会出现奇怪行为的答案,但我也用一些增强功能标记了代码。

  1. 删除 extends JFrame,这很少是个好主意,您已经明白为什么在 class 中使用 JFrame 的实例 JFrame 可能导致...

  2. 将您最初拥有的框架实例的布局设置为空(而不是 this 的布局)。注意:使用布局管理器是创建 Swing UI 的首选方法,通常不鼓励将其设置为 null

  3. 你不需要标签数组(除非你打算稍后使用它们),你可以使用循环添加你想要的。

  4. 使框架最后可见

那么你有:

import javax.swing.*;

@SuppressWarnings("serial")
public class MainFrame {

    public MainFrame()
    {
        JFrame frame = new JFrame("Binary Clock");
        frame.setLayout(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600,400);
        frame.setResizable(false);

        for(int i = 0; i < 5; i++)
        {
            JLabel label = new JLabel();
            label.setLocation(i * 10, i * 10);
            label.setSize(30, 10);
            label.setText("TEST");
            frame.add(label);
        }

        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        new MainFrame();
    }
}

I don't want to use any layout menager since i want few circle images on my Panel.

Swing 的核心设计是使用布局管理器,它的更新过程如何工作以及它如何处理跨多个平台的渲染管道的差异。当然,您可以尝试不使用它,但最后,您只是在尝试时重新发明轮子,并补偿在尝试不使用它时产生的所有小问题。

下面简单地使用了一个 GridBagLayout,它使我能够为组件提供 gridx/y 个位置(以及其他好东西)

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class BinaryClock {

    public static void main(String[] args) {
        new BinaryClock();
    }

    public BinaryClock() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();
            // Hour column
            gbc.gridx = 0;
            addColumn(2, gbc);
            gbc.gridx = 1;
            addColumn(4, gbc);
            // Minute column
            gbc.gridx = 3;
            addColumn(3, gbc);
            gbc.gridx = 4;
            addColumn(4, gbc);
            // Minute column
            gbc.gridx = 6;
            addColumn(3, gbc);
            gbc.gridx = 7;
            addColumn(4, gbc);

            gbc.gridx = 2;
            gbc.gridy = 0;
            gbc.fill = GridBagConstraints.VERTICAL;
            gbc.gridheight = GridBagConstraints.REMAINDER;
            add(new JSeparator(JSeparator.VERTICAL), gbc);

            gbc.gridx = 5;
            add(new JSeparator(JSeparator.VERTICAL), gbc);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void addColumn(int count, GridBagConstraints gbc) {
            for (int index = 0; index < count; index++) {
                gbc.gridy = 3 - index;
                add(new Dot(), gbc);
            }
        }

    }

    public class Dot extends JPanel {

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(100, 100);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
            g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
            g2d.setColor(Color.DARK_GRAY);
            g2d.fillOval(0, 0, getWidth() - 1, getHeight() - 1);
            g2d.dispose();
        }

    }

}

现在您无需担心如何进行时钟更新,而无需不断尝试和修复布局中的问题