JRuby和Swing事件分派线程



Java Swing教程使用swingutility。invokeLater来创建GUI(像这里)。这里解释了为什么这样做——大多数Swing对象都不是线程安全的。另一方面,我见过的大多数JRuby Swing示例只是在脚本中设置了可见的顶部框架(就像这里-存档中的"guis"目录)。

问题是,在JRuby脚本中创建应用程序顶部框架时,我应该遵循使用swingutility . invokelater()的Java模式吗?

我有两个JRuby脚本,一个使用swingutility . invokelater(),另一个不使用:

java_import javax.swing.JFrame
java_import javax.swing.SwingUtilities
java_import java.awt.Dimension
java_import javax.swing.JButton
JavaThread = java.lang.Thread
class TopFrame < JFrame
  def initialize
    super
    init_components()
    pack()
    set_visible(true)
    puts '----------------------------------------'
    puts 'In JFrame constructor:'
    puts "Thread name: #{JavaThread.current_thread.name}"
    puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
    JavaThread.current_thread.thread_group.list
  end
  def init_components()
    set_default_close_operation(JFrame::EXIT_ON_CLOSE)
    set_preferred_size(Dimension.new(400, 300))
    button = JButton.new('Button')
    button.add_action_listener do |event|
      puts '----------------------------------------'
      puts 'In action listener:'
      puts "Thread name: #{JavaThread.current_thread.name}"
      puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
      JavaThread.current_thread.thread_group.list
    end
    get_content_pane.add(button)
  end
end
puts '----------------------------------------'
puts 'Before SwingUtilties.invokeLater():'
puts "Thread name: #{JavaThread.current_thread.name}"
puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
JavaThread.current_thread.thread_group.list
SwingUtilities.invoke_later do
  TopFrame.new
end
puts '----------------------------------------'
puts 'After SwingUtilities.invokeLater():'
puts "Thread name: #{JavaThread.current_thread.name}"
puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
JavaThread.current_thread.thread_group.list

输出为:

----------------------------------------
Before SwingUtilties.invokeLater():
Thread name: main
Is event dispatch thread: false
java.lang.ThreadGroup[name=main,maxpri=10]
    Thread[main,5,main]
    Thread[Ruby-0-JIT-1,1,main]
    java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]
----------------------------------------
After SwingUtilities.invokeLater():
Thread name: main
Is event dispatch thread: false
java.lang.ThreadGroup[name=main,maxpri=10]
    Thread[main,5,main]
    Thread[Ruby-0-JIT-1,1,main]
    Thread[AWT-EventQueue-0,6,main]
    java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]
----------------------------------------
In JFrame constructor:
Thread name: AWT-EventQueue-0
Is event dispatch thread: true
java.lang.ThreadGroup[name=main,maxpri=10]
    Thread[AWT-EventQueue-0,6,main]
    Thread[DestroyJavaVM,5,main]
    java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]
----------------------------------------
In action listener:
Thread name: AWT-EventQueue-0
Is event dispatch thread: true
java.lang.ThreadGroup[name=main,maxpri=10]
    Thread[AWT-EventQueue-0,6,main]
    Thread[DestroyJavaVM,5,main]
    java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]

在swingutility . invokelater()被调用之前,EDT不存在。在swingutility . invokelater()之后,EDT存在并且它与当前线程不同。在JFrame构造函数和JButton动作事件监听器中,EDT是当前线程。

另一个脚本没有使用swinguutilities . invokelater ():

java_import javax.swing.JFrame
java_import javax.swing.SwingUtilities
java_import java.awt.Dimension
java_import javax.swing.JButton
JavaThread = java.lang.Thread
puts '----------------------------------------'
puts 'Before JFrame.new():'
puts "Thread name: #{JavaThread.current_thread.name}"
puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
JavaThread.current_thread.thread_group.list
frame = JFrame.new()
frame.set_default_close_operation(JFrame::EXIT_ON_CLOSE)
frame.set_preferred_size(Dimension.new(400, 300))
button = JButton.new('Button')
button.add_action_listener do |event|
  puts '----------------------------------------'
  puts 'In action listener:'
  puts "Thread name: #{JavaThread.current_thread.name}"
  puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
  JavaThread.current_thread.thread_group.list
end
frame.get_content_pane.add(button)
frame.pack()
puts '----------------------------------------'
puts 'Before JFrame.setVisible():'
puts "Thread name: #{JavaThread.current_thread.name}"
puts "Is event dispatch thread: #{SwingUtilities.event_dispatch_thread?}"
JavaThread.current_thread.thread_group.list
frame.set_visible(true)

输出为:

----------------------------------------
Before JFrame.new():
Thread name: main
Is event dispatch thread: false
java.lang.ThreadGroup[name=main,maxpri=10]
    Thread[main,5,main]
    Thread[Ruby-0-JIT-1,1,main]
    java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]
----------------------------------------
Before JFrame.setVisible():
Thread name: main
Is event dispatch thread: false
java.lang.ThreadGroup[name=main,maxpri=10]
    Thread[main,5,main]
    Thread[Ruby-0-JIT-1,1,main]
    Thread[AWT-EventQueue-0,6,main]
    java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]
----------------------------------------
In action listener:
Thread name: AWT-EventQueue-0
Is event dispatch thread: true
java.lang.ThreadGroup[name=main,maxpri=10]
    Thread[AWT-EventQueue-0,6,main]
    Thread[DestroyJavaVM,5,main]
    java.lang.ThreadGroup[name=Ruby Threads#11483240,maxpri=10]
在JFrame构造函数不是当前线程之后创建

EDT。在JButton事件监听器中,EDT是当前线程

考虑JRuby和其他JVM语言一样…没有特别注意内置的Swing/AWT约定——只有一个用于编写Swing GUI的"新"语法。就像在Java中一样,我也关心EDT。

最新更新