Java 有没有办法区分由用户引起的事件和由应用程序引起的事件?
这主要是重复的: 我想我有一个例子,告诉用户操作和编程操作之间的区别会很好。我正在尝试编写一个通用的案例线程安全JComboBox类。其思想是在试图从非AWT线程更新控件时隐藏所有invokeLater内容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
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);
}
}