Java:第二个窗口是空白的
我有一个奇怪的问题......我是一个相对较新的“爱好者”Java 程序员(在之前的职业生涯中,我曾经靠破解 Perl 为生),正在开发我的第一个半真实应用程序。 “Main-Class”是 MyApp
类,它创建一个 UserInputDialog
实例。
UserInputDialog
是我编写的一个扩展
的JFrame
类,实现了ActionListener
和KeyListener
,使用 FlowLayout
,并向用户呈现 JLabel
、JTextField
和取消/确定 JButton
。当JTextField
生成KeyEvent
(其中keyReleased() == KeyEvent.VK_ENTER
)时,或者当“OK”JButton
时> 生成一个 ActionEvent
,UserInputDialog
进行一些输入验证,调用 setVisible(false)
,然后调用 MyApp.doSomething( JTextFieldInstance.getText() )
。
这一切都很完美。但现在我尝试向 MyApp
添加一个进度窗口,因为 doSomething()
有时可能需要相当长的时间才能完成。
我创建了 ProgressWindow
类,它扩展了 JFrame
,使用 BorderLayout
,并在 .中添加了
和 .JProgressBar
NORTHCENTER
中的 JScrollPane
(包裹 JTextArea
)。当从 ProgressWindowTester
实例化并馈送测试数据时,ProgressWindow
可以完美地工作。如果我将循环测试从 ProgressWindowTester
复制并粘贴到 MyApp
中并且没有 MyApp
实例化 ,它也可以正常工作UserInputDialog
(即,MyApp
中没有任何固有导致此行为;这似乎是我不理解的某种交互, UserInputDialog
和 ProgressWindow
)。
但是,当我尝试按预期在 MyApp
中使用 ProgressWindow
时,即 ProgressWindow
setVisible(true),我得到一个空白的 Swing 窗口(大小合适,标题栏设置正确)。 JProgressBar
和 JScrollPane / JTextArea
组件不会出现。 MyApp
正确调用 ProgressWindow
方法(System.err.println()
消息显示正确的交互),一切似乎都工作正常,只是,应该在 ProgressWindow
中可见的组件...却不是。
我可以发布代码片段,但它有点复杂,而且我可能只是错过了一些明显的东西......
我通常熟悉分离 UI 和业务逻辑的概念(例如,我使用 HTML::Template构建 Perl 应用程序时的
和 Class::DBI
和 CGI::Application
),但我不确定我在 Java 中“做得正确” ...
提前致谢!
哦,我在尝试过代码的两个环境中得到了完全相同的行为:Mac OS X 10.6.8(“Snow Leopard”)上的 javac 1.6.0_29;以及 Fedora 15 Linux 发行版、内核 2.6.31.10-3、LXDE 桌面环境上的 javac 1.7.0_02[1]。
[1]直接从oracle.com下载;我没有使用 OpenJDK(我知道 JDK 7 基于 OpenJDK)或 gcj 或类似的东西
I have a weird issue... I'm a relatively new "enthusiast" Java programmer (I used to make my living hacking Perl, in a previous career), working on my first semi-real application. "Main-Class" is the MyApp
class, which creates a UserInputDialog
instance.
UserInputDialog
is a class I wrote that extend
s JFrame
, implements ActionListener
and KeyListener
, uses FlowLayout
, and presents the user with a JLabel
, JTextField
, and Cancel/OK JButton
s. When the JTextField
generates a KeyEvent
where keyReleased() == KeyEvent.VK_ENTER
, or when the "OK" JButton
generates an ActionEvent
, UserInputDialog
does some input validation, calls setVisible(false)
, and then calls MyApp.doSomething( JTextFieldInstance.getText() )
.
That all works perfectly. But now I'm trying to add a progress window to MyApp
, as doSomething()
can occasionally take a fair amount of time to complete.
I created the ProgressWindow
class, which extends JFrame
, uses BorderLayout
, and tosses a JProgressBar
in .NORTH
and a JScrollPane
(wrapping a JTextArea
) in .CENTER
. ProgressWindow
works perfectly when instantiated from ProgressWindowTester
and fed test data. It also works fine if I copy-and-paste the test for loops from ProgressWindowTester
into MyApp
and don't have MyApp
instantiate UserInputDialog
(i.e., there's nothing inherent in MyApp
that's causing this behavior; it seems to be some sort of interaction I'm not understanding, between UserInputDialog
and ProgressWindow
).
But when I try to use ProgressWindow
in MyApp
as intended, i.e., ProgressWindow
setVisible(true), I get a blank Swing window (of the proper size, and with the title bar set properly). The JProgressBar
and JScrollPane / JTextArea
components don't appear. The ProgressWindow
methods are being called by MyApp
properly (System.err.println()
messages show proper interaction), everything appears to be working fine, just, the components that should be visible in ProgressWindow
... aren't.
I can post code snippets, but it's kind of convoluted, and I'm probably just missing something obvious...
I'm familiar with the concept of separating UI and business logic generally (e.g., I used HTML::Template
and Class::DBI
and CGI::Application
when building Perl applications), but I'm not sure I'm "doing it right" in Java...
Thanks in advance!
Oh, I get exactly the same behavior on the two environments I've tried the code in: javac 1.6.0_29 on Mac OS X 10.6.8 ("Snow Leopard"); and javac 1.7.0_02[1] on the Fedora 15 Linux distribution, kernel 2.6.31.10-3, LXDE desktop environment.
[1] Downloaded directly from oracle.com; I;m not using OpenJDK (I know JDK 7 is based on OpenJDK) or gcj or anything like that
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您在 Swing 问题中遇到了并发问题,您尝试在 Swing 事件线程或 EDT 上执行长时间运行的进程。由于该线程负责绘制所有组件并处理用户输入,因此如果它受到长时间运行的进程的束缚,则您的 GUI 将被有效冻结,直到该进程完成。关键是使用后台线程,例如 SwingWorker 为长时间运行的进程提供的后台线程,这样事件线程就不会被锁定。有关详细信息,请查看 Swing 中的并发。另请查看 JProgressBar 教程,了解有关如何使用的其他见解带有后台线程的进度条。
另外,您不会想使用 JFrame,因为对话框(例如 JDialog)更合适。此外,您还需要避免在 Swing 中使用 KeyListener。更好的方法是简单地将 ActionListener 添加到 JTextField,因为它的默认行为是响应按键的按下。
哦,欢迎来到 StackOverflow.com!
You've got a concurrency in Swing issue where you're trying to do a long running process on the Swing event thread or EDT. Since this thread is responsible for drawing all components and for processing user input, if it is tied down by your long-running process, your GUI will be effectively frozen until the process is complete. The key is to use a background thread such as that provided by a SwingWorker for long-running processes, so the event thread doesn't get locked. Check out Concurrency in Swing for more information on this. Also check out the JProgressBar Tutorial for other insights on how to use progress bars with background threads.
Also, you'll not want to use a JFrame where a dialog, such as a JDialog, is much more appropriate. Also, you'll want to avoid use of KeyListeners with Swing. Much better would be to simply add an ActionListener to your JTextField since its default behavior is to respond to presses of the key.
Oh, and welcome to StackOverflow.com!