- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我使用在应用程序启动时启动的JDialog
来多次显示消息。有时,对话框及其控件是不可见的,但可以单击。
JDialog
仅实例化一次,并在每次应显示消息时设置为可见“true”,然后设置为可见“false”,直到应显示下一条消息。
为了排除多线程相关问题,当线程创建消息并显示对话框时,我总是使用 SwingUtilities.invokeLater(...)
进行 ui 调用。
因为它是一个巨大的项目,而且我的问题与任何特定代码无关,所以我不发布代码,而是描述问题。这些问题似乎无法重现,但有时会发生,因此尽管在 EDT
上运行每个相关调用,但它可能是线程问题。
我做错了什么?
public class MessageHandler {
private volatile static MessageHandler messageHandler = null;
private List<Message>messages = null;
private volatile WeakReference<MessagesPanelControl> view = null;
private final Object viewSynchronizationObject = new Object();
private MessageHandler() {
messages = new ArrayList<Message>();
}
public static MessageHandler getInstance() {
MessageHandler result = messageHandler;
if (result == null) {
synchronized (MessageHandler.class) {
result = messageHandler;
if (result == null)
messageHandler = result = new MessageHandler();
}
}
return result;
}
public void registerView(MessagesPanelControl view) {
this.view = new WeakReference<MessagesPanelControl>(view);
}
public void addMessage(final Message message) {
synchronized (viewSynchronizationObject) {
messages.add(message);
Collections.sort(messages);
updateView();
}
}
private void updateView() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
synchronized (viewSynchronizationObject) {
if (view == null) {
return;
}
MessagesPanelControl mpc = view.get();
if (mpc != null) {
mpc.updateView();
}
}
}
});
}
}
在 MainFrame 类中,我在启动时进行一次初始化:
MessagesPanelControl mp = new MessagesPanelControl();
MessageHandler.getInstance().registerView(mp);
LockPane messageBasicPane = new LockPane(this, mp);
然后在不同的线程中调用它以通过 MessageHandler
Singleton 显示消息:
MessageHandler.getInstance().addMessage(Message.getSimpleMessage("Error", "Fatal error occured", Message.MessageIcon.ERROR));
我没有发布所有细节,但发布了理解整个问题的所有必要部分,希望它能让它更容易理解。
MessagePanelControl
(mpc) 是一个扩展 JPanel
的类。它的 updateView() 方法根据 MessageHandler 的
消息列表(如按钮、标签和图标)创建消息控件。最后,该方法向主框架发送类似 Delegate
的命令,以显示包含 MessagePanelControl
的 JDialog
。总结一下:
MessageHandler
中列表中的每条消息创建消息面板MessagePanelControl
显示 JDialogmessageList.size()<=0:使用 MessagePanelControl
隐藏 JDialog
公共(public)无效updateView(){ 同步(viewMPCSynchronizationObject){ Utils.throwExceptionWhenNotOnEDT();
JPanel messagesListPanel = new JPanel();
scrollPane.setViewportView(messagesListPanel);
scrollPane.setBorder(null);
messagesListPanel.setLayout(new BoxLayout(messagesListPanel, BoxLayout.Y_AXIS));
if (MessageHandler.getInstance().getMessages() != null && MessageHandler.getInstance().getMessages().size() > 0) {
[...]
//Create buttons, text icons... for each message
[...]
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainFrame().showMessageBoard();
}
});
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainFrame().closeMessageBoard();
}
});
}
repaint();
}
}
主机:
//Show Messageboard
public void showMessageBoard() {
if (messageBasicPane != null) {
messageBasicPane.setVisible(true);
messageBasicPane.repaint();
}
}
[...]
//Close Messageboard
public void closeMessageBoard() {
if (messageBasicPane != null) {
messageBasicPane.setVisible(false);
}
}
这一行创建了JDialog
,详细信息:
[...]
public LockPane(JFrame parentFrame, JComponent componentToShow, Dimension paneSize, float opacity, ModalityType modality) {
super(parentFrame, true);
Utils.throwExceptionWhenNotOnEDT();
createDialog(paneSize, opacity, modality);
if (componentToShow != null) {
add(componentToShow);
}
pack();
}
private void createDialog(Dimension paneSize, float opacity, ModalityType modality) {
Utils.throwExceptionWhenNotOnEDT();
setUndecorated(true);
setModalityType(modality);
if (opacity < 1 && opacity >= 0)
com.sun.awt.AWTUtilities.setWindowOpacity(this, opacity);
setSize(paneSize);
setPreferredSize(paneSize);
setMaximumSize(paneSize);
setBounds(0, 0, paneSize.width, paneSize.height);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
}
[...]
Java VisualVM 的一个新观察结果是,AWT-EventQueue 没有被阻塞,只是有时会有一小段时间的“等待”,但没有任何阻塞。另一个奇怪的事情是,有时我的 JDialog
是完全透明的(不可见),有时它是白色的,具有所需的不透明度。
最佳答案
在此函数中,您实际上是在尝试等待传递给 SwingUtilities.invokeLater
的 Runnable
,invokeLater
会提交给 EDT 以获取被执行。如果您在 viewSynchronizationObject
上持有的锁被其他应用程序线程锁定,则它会阻止 EDT,这实际上从您的代码中可以明显看出,因为您在其他几个地方使用了此变量。
private void updateView() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
synchronized (viewSynchronizationObject) {
if (view == null) {
return;
}
MessagesPanelControl mpc = view.get();
if (mpc != null) {
mpc.updateView();
}
}
}
},false);
}
我们永远不应该阻止 EDT 执行它的任务,否则我们的应用程序会卡住。请阅读我的posted answer here for details关于 EDT 和 EventQueue 如何执行 Swing 事件和渲染任务。
虽然我们不知道您的应用程序逻辑,但您可以从 invokeLater
中删除 synchronized (viewSynchronizationObject) {}
,而是将 SwingUtilities.此同步块(synchronized block)内的 invokeLater(new Runnable() {}
:
synchronized (viewSynchronizationObject)
{
SwingUtilities.invokeLater(new Runnable() { /* your code */ } );
}
关于java - JDialog不可见,组件可点击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20465456/
如何在另一个 JDialog 中添加 JDialog? 最佳答案 JDialog secondDialog = new JDialog(this); // ("this" is the first J
我有一个 JDialog,其中有一个可打开新窗口的按钮。我想要做的是每当其他窗口打开时阻止此 JDialog。当我说阻止时,我的意思是用户无法操纵它,无法移动它或最大化或任何东西。 顺便问一下,对于带
我有一个从 JFrame 上的按钮打开的父 JDialog。父 JDialog 本身有一个从父对话框上的按钮打开的子 JDialog。当我关闭父对话框并使用框架上的按钮再次打开它时,我不希望子对话框也
抱歉这个奇怪的标题,但这是解释。所以我有一个带有学生列表的 StudentRepository 类,这些学生是在 GUI 上选择的(通过 TableModel)。学生对象的属性是: int stude
我有一个未修饰的模态 JDialog,当用户在模态对话框外单击时,我想将其设置为 setVisible(false)。 这在 Swing 中可能吗? 我正在做的是为日期选择器之类的文本字段弹出一个自定
我有一个模式设置对话框,它是一个 JDialog。在这个设置窗口中,我放置了一些组件,包括一个按钮到另一个模态设置对话框,它也是一个 JDialog。我制作了它们 JDialogs,因为这是我所知道的
我只想在单击 JDialog 之外时关闭 JDialog import javax.swing.JDialog; import javax.swing.JLabel; public class Dia
我正在尝试重现我在多个应用程序中看到的功能:我有一个带有多个 JDialog 的 GUI 应用程序。我想轻松地将它们紧密地组织在屏幕上:当我移动一个 JDialog,并且它的一个边界变得“接近”(例如
对 Java 相当陌生,并且遇到了 z 顺序问题。我有一个旧版 Java 应用程序,它有一个主窗口 A,它会弹出一个模式 JDialog B。单击 B 上的按钮后,会弹出一个模式对话框 C。 对于从
我的应用程序中有多个 JDialogs 存储在 map 中。这些JDialogs都有 setModel(false); 当这些对话框失去焦点并且我想将特定的 JDialog 带到前面时,所有 JDia
我有一个扩展 JDialog 的类。当 JDialog 显示时,我单击其启动 Jframe 的显示按钮,但在关闭 JDialog 之前我无法访问 JFrame。当屏幕上存在 JDialog 时,如何访
场景是这样的我的 JFrame 有一个按钮,单击它会打开一个 JDialog,它是一个模型对话框。JDialog 有另一个按钮,我想打开另一个 JFrmae 点击它打开。 结果:另一个 Jframe
我有一个带有主 JFrame 的小型应用程序,它以模态方式打开 JDialog。在这个 JDialog 中,我启动了一个 javax.swing.Timer,它应该在 JDialog 关闭时停止。 p
如何将用户凭据传回到包含的 JFrame,以便 JFrame 知道特定用户? JFrame 有一个 main 方法。 包含的 JFrame 能否以某种方式从 Dialog 中获取用户? 当jbtOk
我基本上创建的是一个 JDialog,它在表单上有一个关键事件。因此,当例如按下空间时,它会做一些事情。在我在同一个对话框上创建一个可编辑的 JTextArea 之前,这种方法工作得很好。当我这样做时
这个问题不太可能对任何 future 的访客有帮助;它只与一个较小的地理区域、一个特定的时间点或一个非常狭窄的情况相关,通常不适用于全世界的互联网受众。如需帮助使此问题更广泛适用,visit the
我正在构建我的第一个 gui,到目前为止一切正常,除了 JDialog 的故障。 .它在第一次使用时相应地接受名称和进程列表。但是当我把它拉回来输入新的输入时,它仍然没有响应。我认为这不是线程问题,因
如何创建一个 Modal JDialog,在任务正在处理时显示“正在加载”,并在超过 3 秒后显示? 最佳答案 为了扩展 Paul 的回答,SwingWorker 可以很好地运行您的后台任务。然后您可
该程序大部分运行正常,但没有打开任何窗口。它应该在桌面右下角显示一个小对话框。但是对于另一个人来说,编译相同的代码没有问题。我们有相同的 Java 运行时 (1.8_u40)。我该如何解决这个问题?
我正在使用 Eclipse 的 Window Builder 插件。 当我执行以下代码时,它正确显示JDialog。我原本希望 JDialog 也能显示在设计选项卡中(在设计时),但它不会。 pack
我是一名优秀的程序员,十分优秀!