0

如果我尝试通过不同的线程选择 JComboBox 的元素,则会导致非常奇怪的行为,并且几乎每次都会选择列表的最后一个元素。这是一个错误还是一个愚蠢的错误?

package com.test;

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class Test3 extends JFrame {
    private static final long serialVersionUID = 1L;
    private JPanel contentPane;

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                Test3 frame = new Test3();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

public Test3() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 200, 80);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(new BorderLayout(0, 0));
    String[] select = { "0", "1", "2", "3", "4" };
    final JComboBox<String> jb = new JComboBox<String>(select);
    contentPane.add(jb, BorderLayout.NORTH);

    new Thread() {
        int i = 0;

        public void run() {
            while (true) {
                i++;
                if (i > 4)
                    i = 0;
                jb.setSelectedIndex(i);
                System.out.println("SELECT " + i);
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }.start();

    setContentPane(contentPane);
}}

此示例显示了一个简单的 JComboBox,其中包含由 String-Array 给出的 5 个元素。每 3 秒,定义的线程在

jb.setSelectedIndex(i);

控制台也会打印选择。运行该代码显示了上述奇怪的行为:控制台每三秒计数一次 0-4,JComboBox 大部分时间选择列表中的最后一个..

4

2 回答 2

0

感谢您的帮助,我找到的最简单的解决方法是让 Swing 处理这个问题:

package com.test;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.lang.reflect.InvocationTargetException;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

public class Test3 extends JFrame {
    private static final long serialVersionUID = 1L;
    private JPanel contentPane;
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                Test3 frame = new Test3();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

public Test3() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 200, 80);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(new BorderLayout(0, 0));
    String[] select = { "0", "1", "2", "3", "4" };
    final JComboBox<String> jb = new JComboBox<String>(select);
    contentPane.add(jb, BorderLayout.NORTH);

    new Thread() {
        int i = 0;

        public void run() {
            while (true) {
                i++;
                if (i > 4)
                    i = 0;
                System.out.println("SELECT " + i);
                try {
                    Thread.sleep(3000);
                    try {
                        SwingUtilities.invokeAndWait(new Runnable() {
                            public void run() {
                                jb.setSelectedIndex(i);
                            }
                        });
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }.start();
    setContentPane(contentPane);
   }
}
于 2013-06-27T13:31:02.423 回答
0

您需要使用 invokeLater()将JCombobox更新放入事件调度线程中:

public Test3() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 200, 80);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(new BorderLayout(0, 0));
    String[] select = { "0", "1", "2", "3", "4" };
    final JComboBox<String> jb = new JComboBox<String>(select);
    contentPane.add(jb, BorderLayout.NORTH);

    new Thread() {
        int i = 0;

        @Override
        public void run() {
            while (true) {
                i++;
                if (i > 4)
                    i = 0;

                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        jb.setSelectedIndex(i);

                    }
                });

                System.out.println("SELECT " + i);
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }.start();

    setContentPane(contentPane);
}}
于 2013-06-27T13:34:04.027 回答