JLabel绘制点。

8
import java.awt.Graphics;
import javax.swing.*;

public class Demo
{
    JFrame jf;
    JLabel[] labels;
    JPanel panel;

    public Demo()
    {
        jf = new JFrame();
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        labels = new JLabel[10];
        Box vbox = Box.createVerticalBox();
        for (int i = 0; i < 10; i++)
        {
            labels[i] = new JLabel();
            vbox.add(labels[i]);
        }
        panel = new JPanel();
        panel.add(vbox);
        jf.add(panel);
        jf.setSize(300, 250);
        jf.setVisible(true);
    }
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new DemoRunnable());
    }
    public void updateState()
    {
        for (JLabel l : labels)
        {
            if (Math.random() > 0.5)
                l.setText("777777777777777777777777777777777777");
            else
                l.setText("10000000000000000000000000000000000000");
        }
    }
}
class DemoRunnable implements Runnable
{
    Demo demo;

    DemoRunnable()
    {
        this.demo = new Demo();
    }
    @Override
    public void run()
    {
        Thread t = new Thread(new Runnable()
        {

            @Override
            public void run()
            {
                while (true)
                {
                    try
                    {
                        Thread.sleep(0);
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    demo.updateState();
                }
            }
        });
        t.start();

    }
}

当执行该程序时,我看到了这种效果。是否有可能消除它(将零替换为点)?

2
这基本上是由于您的文本超出了 JLabel 的边界。 - ring bearer
+1 for sscce - trashgod
2个回答

4

使用pack()而不是setSize(),以利用组件精心计算的首选大小。您还需要初始化标签:

labels[i] = new JLabel("10000000000000000000000000000000000000");

考虑使用javax.swing.Timer而非单独的线程。

补充说明:方便地,每个Swing Timer共享一个通用的后台线程,并且actionPerformed()在事件派发线程上被调用。另一种选择是SwingWorker,见此处


请参考Swing中的并发性 - trashgod
我需要另一种解决方案,因为我的问题需要定期调用 setText()(我的代码仅为示例)。 - eXXXXXXXXXXX2

3
我的回答中的代码仅为示例,
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.*;

public class Demo {

    private JFrame jf;
    private JLabel[] labels;
    private JPanel panel;

    public Demo() {
        labels = new JLabel[10];
        Box vbox = Box.createVerticalBox();
        for (int i = 0; i < 10; i++) {
            labels[i] = new JLabel();
            labels[i].setText("10000000000000000000000000000000000000");
            vbox.add(labels[i]);
        }
        panel = new JPanel();
        panel.setLayout(new GridLayout());
        panel.add(vbox);
        jf = new JFrame();
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.add(panel);
        jf.pack();
        jf.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new DemoRunnable());
    }

    public void updateState() {
        for (final JLabel l : labels) {
            if (Math.random() > 0.5) {
                EventQueue.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        l.setText("777777777777777777777777777777777777");
                    }
                });
            } else {
                EventQueue.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        l.setText("10000000000000000000000000000000000000");
                    }
                });
            }
        }
    }
}

class DemoRunnable implements Runnable {

    private Demo demo;

    DemoRunnable() {
        this.demo = new Demo();
    }

    @Override
    public void run() {
        Thread t = new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(250);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    demo.updateState();
                }
            }
        });
        t.start();
    }
}

+1 是为了 invokeLater(),而 javax.swing.Timer 之所以方便的好例子。 - trashgod
@trashgod同意了+1,但我认为OP不理解FlowLayout的工作原理。 - mKorbel
@mKorbel,“invokeLater” 对我的问题不合适(显然在这种情况下,“setText” 调用在 EDT 队列中累积。如果使用 “invokeLater”,延迟很短,程序会挂起(使用“invokeAndWait”可解决)。 - eXXXXXXXXXXX2
@mKorbel 我使用 Box,它具有固定宽度(最宽组件的宽度),因此 JPanel 使用 FlowLayout 不会改变其大小,因为它具有 "10000000000000000000000000000000000000" 的 JLabel 宽度。 - eXXXXXXXXXXX2
2
@eXXXXXXXXXXX 如果字符串不是"...777",则应该计算FlowLayout的另一个像素比率,就像对于0000一样。这个问题与FontMetrics有关。 - mKorbel
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接