Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 有没有办法区分由用户引起的事件和由应用程序引起的事件?_Java_Multithreading_Swing_Events_Combobox - Fatal编程技术网

Java 有没有办法区分由用户引起的事件和由应用程序引起的事件?

Java 有没有办法区分由用户引起的事件和由应用程序引起的事件?,java,multithreading,swing,events,combobox,Java,Multithreading,Swing,Events,Combobox,这主要是重复的: 我想我有一个例子,告诉用户操作和编程操作之间的区别会很好。我正在尝试编写一个通用的案例线程安全JComboBox类。其思想是在试图从非AWT线程更新控件时隐藏所有invokeLater内容 public class JComboBoxThreadSafe extends JComboBox { private int m_iSelected = -1; private Object m_oSelected = null; priv

这主要是重复的:

我想我有一个例子,告诉用户操作和编程操作之间的区别会很好。我正在尝试编写一个通用的案例线程安全JComboBox类。其思想是在试图从非AWT线程更新控件时隐藏所有invokeLater内容

public class    JComboBoxThreadSafe
extends         JComboBox {

    private int m_iSelected = -1;
    private Object m_oSelected = null;
    private boolean m_bVisible = true;

    public JComboBoxThreadSafe(){

        super();

    }

    public JComboBoxThreadSafe(ComboBoxModel arg0){

        super(arg0);

    }

    public JComboBoxThreadSafe(Object[] items){

        super(items);

    }

    public JComboBoxThreadSafe(Vector<?> items){

        super(items);

    }

    @Override
    public void setSelectedIndex(final int iIndex){

        m_iSelected = iIndex;
        m_oSelected = getItemAt(iIndex);

        if (SwingUtilities.isEventDispatchThread()){

            super.setSelectedIndex(iIndex);

        }else{

            SwingUtilities.invokeLater(new Runnable(){

                @Override
                public void run() {

                    JComboBoxThreadSafe.super.setSelectedIndex(iIndex);

                }

            });


        }

    }

    @Override
    public void setSelectedItem(final Object oSelect){

        m_oSelected = oSelect;
        m_iSelected = FindItemIndex(oSelect);

        if (SwingUtilities.isEventDispatchThread()){

            super.setSelectedItem(oSelect);

        }else{

            SwingUtilities.invokeLater(new Runnable(){

                @Override
                public void run() {

                    JComboBoxThreadSafe.super.setSelectedItem(oSelect);

                }

            });

        }

    }

    @Override
    public void setVisible(final boolean bVisible){

        m_bVisible = bVisible;

        if (SwingUtilities.isEventDispatchThread()){

            super.setVisible(bVisible);

        }else{

            SwingUtilities.invokeLater(new Runnable(){

                @Override
                public void run() {

                    JComboBoxThreadSafe.super.setVisible(bVisible);

                }

            });

        }

    }

    @Override
    public Object getSelectedItem(){

        return m_oSelected;

    }

    @Override
    public int getSelectedIndex(){

        return m_iSelected;

    }

    @Override
    public boolean isVisible(){

        return m_bVisible;

    }

    private int FindItemIndex(Object oItem){

        int iReturn = -1;

        int iCount = getItemCount();

        for (int iIndex = 0; (iReturn == -1) && (iIndex < iCount); iIndex++){

            if (getItemAt(iIndex).equals(oItem)) iReturn = iIndex;

        }

        return iReturn;

    }

}
我可以想出一些骇人的解决方案:

侦听鼠标事件而不是模型更改 尝试过滤掉编程更改后的下一个事件 如果能过滤掉所有编程更改,那就太好了。能做到吗

谢谢

编辑:

下面是一个测试类,它表明仅修改模型是不可行的。当我在最新的JDK 1.7u51上运行此程序,并单击“选择随机”按钮时,ComBox无法正确渲染。如果将鼠标移到它上面,它将再次开始工作,直到通过下拉菜单进行新选择,然后再次单击“选择随机”按钮。因此,我编写了jcmoboxthreadsafe,希望不必每次更新组合框时都编写调用程序代码

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class    CBTest
implements  ActionListener,
        Runnable {

    private static JComboBox<String> ms_cbTest = null;

    public void actionPerformed(ActionEvent aeEvent){

        Thread tThread = new Thread(this);

        tThread.start();

    }

    public void run(){

        ms_cbTest.getModel().setSelectedItem((int)(ms_cbTest.getItemCount() * Math.random()));

    }

    public static void main(String[] asArgs){

        try {

            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

        } catch (Exception e){
        }

        JFrame fFrame = new JFrame();
        JPanel pPanel = new JPanel();

        fFrame.getContentPane().add(pPanel);

        ms_cbTest = new JComboBox<String>();

        for (int iNum = 0; iNum < 100; iNum++){

            ms_cbTest.addItem("" + iNum);

        }

        pPanel.add(ms_cbTest);

        JButton bSelect = new JButton("Select Random");

        bSelect.addActionListener(new CBTest());

        pPanel.add(bSelect);

        fFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        fFrame.pack();

        fFrame.setLocationRelativeTo(null);

        fFrame.setResizable(false);

        fFrame.setVisible(true);

    }

}

说真的,把重点放在模型上,如果必须的话,让它线程安全。组合框本身不太可能在EDT之外的任何地方被修改……通常有两种方法1使用您提到的标志,我认为它甚至可以在多线程中工作。你需要在那里组织同步。2在API调用之前删除侦听器,并在API调用之后重新添加它。@mad程序员:我想我没有解释我试图使用JComboxThreadSafe类做什么。关键是,我只需在EDT上修改它,就可以抽象出调用器的内容。关键是,模型是唯一应该改变的。应该不需要修改EDT外部combobox的状态,如果需要修改,则说明设计不好…@MadProgrammer我添加了一些代码,表明仅访问模型仍然会导致JComboBox出现问题。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class    CBTest
implements  ActionListener,
        Runnable {

    private static JComboBox<String> ms_cbTest = null;

    public void actionPerformed(ActionEvent aeEvent){

        Thread tThread = new Thread(this);

        tThread.start();

    }

    public void run(){

        ms_cbTest.getModel().setSelectedItem((int)(ms_cbTest.getItemCount() * Math.random()));

    }

    public static void main(String[] asArgs){

        try {

            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

        } catch (Exception e){
        }

        JFrame fFrame = new JFrame();
        JPanel pPanel = new JPanel();

        fFrame.getContentPane().add(pPanel);

        ms_cbTest = new JComboBox<String>();

        for (int iNum = 0; iNum < 100; iNum++){

            ms_cbTest.addItem("" + iNum);

        }

        pPanel.add(ms_cbTest);

        JButton bSelect = new JButton("Select Random");

        bSelect.addActionListener(new CBTest());

        pPanel.add(bSelect);

        fFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        fFrame.pack();

        fFrame.setLocationRelativeTo(null);

        fFrame.setResizable(false);

        fFrame.setVisible(true);

    }

}