我正在使用一个名为 Processing 的框架,它基本上是一个 Java applet。它具有执行关键事件的能力,因为 Applet 可以。您还可以将自己的各种回调滚动到父级中。我现在不这样做,也许这就是解决方案。现在,我正在寻找更 POJO 的解决方案。所以我写了一些例子来说明我的问题。
请忽略在命令行(控制台)上使用按键事件。当然,这将是一个非常干净的解决方案,但在命令行上是不可能的,而且我的实际应用程序不是命令行应用程序。事实上,按键事件对我来说是一个很好的解决方案,但我试图了解事件和轮询,而不仅仅是键盘特定问题。
这两个例子都翻转了一个 boolean 值。当 boolean 值翻转时,我想触发一次。我可以将 boolean 值包装在一个对象中,这样如果对象发生变化,我也可以触发一个事件。我只是不想不必要地使用 if() 语句进行轮询。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/*
* Example of checking a variable for changes.
* Uses dumb if() and polls continuously.
*/
public class NotAvoidingPolling {
public static void main(String[] args) {
boolean typedA = false;
String input = "";
System.out.println("Type 'a' please.");
while (true) {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
try {
input = br.readLine();
} catch (IOException ioException) {
System.out.println("IO Error.");
System.exit(1);
}
// contrived state change logic
if (input.equals("a")) {
typedA = true;
} else {
typedA = false;
}
// problem: this is polling.
if (typedA) System.out.println("Typed 'a'.");
}
}
}
运行这个输出:
Type 'a' please.
a
Typed 'a'.
在一些论坛上,人们建议使用 Observer。尽管这将事件处理程序与被观察的类分离,但我仍然有一个永远循环的 if()。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Observable;
import java.util.Observer;
/*
* Example of checking a variable for changes.
* This uses an observer to decouple the handler feedback
* out of the main() but still is polling.
*/
public class ObserverStillPolling {
boolean typedA = false;
public static void main(String[] args) {
// this
ObserverStillPolling o = new ObserverStillPolling();
final MyEvent myEvent = new MyEvent(o);
final MyHandler myHandler = new MyHandler();
myEvent.addObserver(myHandler); // subscribe
// watch for event forever
Thread thread = new Thread(myEvent);
thread.start();
System.out.println("Type 'a' please.");
String input = "";
while (true) {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
try {
input = br.readLine();
} catch (IOException ioException) {
System.out.println("IO Error.");
System.exit(1);
}
// contrived state change logic
// but it's decoupled now because there's no handler here.
if (input.equals("a")) {
o.typedA = true;
}
}
}
}
class MyEvent extends Observable implements Runnable {
// boolean typedA;
ObserverStillPolling o;
public MyEvent(ObserverStillPolling o) {
this.o = o;
}
public void run() {
// watch the main forever
while (true) {
// event fire
if (this.o.typedA) {
setChanged();
// in reality, you'd pass something more useful
notifyObservers("You just typed 'a'.");
// reset
this.o.typedA = false;
}
}
}
}
class MyHandler implements Observer {
public void update(Observable obj, Object arg) {
// handle event
if (arg instanceof String) {
System.out.println("We received:" + (String) arg);
}
}
}
运行这个输出:
Type 'a' please.
a
We received:You just typed 'a'.
如果 if() 是 CPU 上的 NOOP,我会没事的。但它确实是在比较每一次传球。我看到了真正的 CPU 负载。这和投票一样糟糕。我也许可以通过 sleep 来限制它,或者比较自上次更新以来耗时,但这不是事件驱动的。这只是较少的轮询。那么我怎样才能更聪明地做到这一点呢?如何在不进行轮询的情况下观察 POJO 的变化?
在 C# 中似乎有一些有趣的东西叫做属性。我不是 C# 专家,所以也许这并不像我想的那么神奇。
private void SendPropertyChanging(string property)
{
if (this.PropertyChanging != null) {
this.PropertyChanging(this, new PropertyChangingEventArgs(property));
}
}
最佳答案
是的,事件处理是您问题的关键。您显示的 C# 片段还使用事件处理来告知监听器属性已更改。 Java 也有这些用于大多数 Bean 的 PropertyChangeEvent。 (例如:Swing 组件使用它们)。
但是,您可以手动执行此操作:(尽管这不再是 POJO,而是更多的 Java Bean)
EventBean.java:
import java.util.LinkedList;
import java.util.List;
public class EventBean {
private final List<Listener> listeners = new LinkedList<Listener>();
protected final <T> void firePropertyChanged(final String property,
final T oldValue, final T newValue) {
assert(property != null);
if((oldValue != null && oldValue.equals(newValue))
|| (oldValue == null && newValue == null))
return;
for(final Listener listener : this.listeners) {
try {
if(listener.getProperties().contains(property))
listener.propertyChanged(property, oldValue, newValue);
} catch(Exception ex) {
// log these, to help debugging
ex.printStackTrace();
}
}
}
public final boolean addListener(final Listener x) {
if(x == null) return false;
return this.listeners.add(x);
}
public final boolean removeListener(final Listener x) {
return this.listeners.remove(x);
}
}
Listener.java:
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
// Must be in same package as EventBean!
public abstract class Listener {
private final Set<String> properties;
public Listener(String... properties) {
Collections.addAll(this.properties = new TreeSet<String>(), properties);
}
protected final Set<String> getProperties() {
return this.properties;
}
public abstract <T> void propertyChanged(final String property,
final T oldValue, final T newValue);
}
然后像这样实现你的类:
public class MyBean extends EventBean {
private boolean typedA;
public void setTypedA(final boolean newValue) {
// you can do validation on the newValue here
final boolean oldValue = typedA;
super.firePropertyChanged("typedA", oldValue, newValue);
this.typedA = newValue;
}
public boolean getTypedA() { return this.typedA; }
}
您可以用作:
MyBean x = new MyBean();
x.addListener(new Listener("typedA") {
public <T> void propertyChanged(final String p,
final T oldValue, final T newValue) {
System.out.println(p + " changed: " + oldValue + " to " + newValue);
// TODO
}
});
x.setTypedA(true);
x.setTypedA(false);
x.setTypedA(true);
x.setTypedA(true);
关于java - 在没有轮询的情况下观察变量的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2822901/
我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/
我有一个奇怪的问题:我在rvm上安装了rubyonrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(
这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
大家好!我想知道Ruby中未使用语法ClassName.method_name调用的方法是如何工作的。我头脑中的一些是puts、print、gets、chomp。可以在不使用点运算符的情况下调用这些方法。为什么是这样?他们来自哪里?我怎样才能看到这些方法的完整列表? 最佳答案 Kernel中的所有方法都可用于Object类的所有对象或从Object派生的任何类。您可以使用Kernel.instance_methods列出它们。 关于没有类的Ruby方法?,我们在StackOverflow