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);
}}

この例は、内部の String-Array によって指定された 5 つの要素を持つ単純な JComboBox を示しています。3 秒ごとに、定義されたスレッドが次の項目を選択します。

jb.setSelectedIndex(i);

コンソールにも選択内容が出力されます。そのコードを実行すると、前述の奇妙な動作が示されます。コンソールは 3 秒ごとに 0 ~ 4 をカウントし、JComboBox はほとんどの場合、リストの最後のものを選択します。

4

2 に答える 2

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 に答える
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 に答える