当前位置: 首页 > 知识库问答 >
问题:

JRuby和Swing事件调度线程

嵇丰
2023-03-14

Java Swing教程使用SwingUtilities。invokeLater创建GUI(如这里所示)。这里解释了为什么要这样做——大多数Swing对象都不是线程安全的。另一方面,我所看到的大多数JRubySwing示例只是设置了脚本中可见的顶部框架(如这里所示——归档中的“gui”目录)。

问题是,在 JRuby 脚本中创建应用程序顶部帧时,我是否应该遵循使用 SwingUtilities.invokeLater() 的 Java 模式?

我有两个JRuby脚本,一个使用SwingUtilities.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]

在调用SwingUtilities.invokeLater()之前,EDT不存在在swing utilities . invoke later()EDT存在之后,它与当前线程不同。在JFrame构造函数和JButton动作事件监听器EDT中是当前线程。

另一个脚本不使用SwingUtilities.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]

EDT是在JFrame构造函数不是当前线程之后创建的。在JButton事件侦听器中,EDT是当前线程。

共有1个答案

逑阳泽
2023-03-14

将 JRuby 视为任何其他 JVM 语言...没有特别关心内置的 Swing/AWT 约定 - 只有用于编写 Swing GUI 的“新”语法。因此,请像在Java中一样关心EDT。

 类似资料:
  • 问题内容: 我最近开始学习和探索Java中GUI编程的基础知识。 经过一段时间的编程,我只完成了后端工作或其他工作,因此,我最接近用户界面的是命令控制台(令人尴尬的是,我知道)。 我正在使用Swing,据我所知,通过扩展,我也正在使用AWT。 我的问题基于以下代码: 我已经研究了一段时间,因为我想完全理解这段奇怪的代码,并且多次遇到“事件分派线程”一词。如果我错了,请纠正我,但据我了解;它与使用多

  • 问题内容: 我知道“线程”的含义,并且如果我将事件分发线程(EDT)理解为“只是一个线程”,它可以解释很多,但是显然,它并不能解释所有内容。 我不了解此线程有什么特别之处。例如,我不明白为什么要在EDT中启动GUI?为什么“主”线程是GUI的床?好吧,如果我们只是不想占用主线程,为什么为什么不能仅在“另一个线程”中启动GUI,为什么它应该是一些称为“ EDT”的“特殊”线程呢? 那我不明白为什么我

  • 问题内容: 我一直在将Substance外观整合到我的应用程序中,并且遇到有关内部EDT(事件调度线程)检查例程的一些问题。物质绝对拒绝在EDT之外构造UI类。我已经做了很多Swing / AWT,并且我了解有关EDT的大多数规则。我使用SwingWorker,SwingUtilties.invokeLater修改组件。我总是尽管可以在EDT之外构造这些组件,但是必须在EDT上实现和操纵这些组件。

  • 当一个组织中有N名员工时,我们会得到N个日期偏移范围。类似于 1-4(即员工将在第一、第二、第三和第四天来) 2-6 8-9 ... 1-14 我们必须在最少的天数上组织一次活动,以便每个员工至少可以参加两次活动。请建议算法(可能是贪婪的)来做到这一点。 PS:事件是一天的事件。

  • 问题内容: 我了解了swing是不是线程安全的。深入研究,我发现必须对事件分发线程进行任何对swing组件的修改,以防止与多线程相关的各种问题。但是,这些信息似乎完全到此为止。似乎没有一个很好的教程可以解释如何在Internet上可以访问的任何地方进行此操作。 从与其他问题有关的已发布代码中收集信息,似乎我将不得不在程序中的每个单独的swing修改周围放置一个不整洁的代码块(例如本例中的代码):

  • 问题内容: 我正在使用一个称为类的类,该类可实现处理项目中的正常异常。 据我了解,此类无法捕获EDT异常,因此我尝试在该方法中使用此类来处理EDT异常: 但是直到现在,它仍无法正常工作。例如,在初始化JFrame时,我从构造器中的捆绑文件中加载其标签,如下所示: 我从捆绑文件中删除了密钥以测试异常处理程序,但是它没有用!异常通常打印在日志中。 我在这里做错什么了吗? 问题答案: EDT异常处理程序