gpt4 book ai didi

java - 为什么 JPopupMenu 在渲染之前要经过 2 遍 UIThread?

转载 作者:行者123 更新时间:2023-12-02 12:35:50 24 4
gpt4 key购买 nike

第一遍似乎要么使可绘制区域无效,要么绘制背景。第二遍渲染菜单。如果有任何延迟(如下面的示例所示),则会出现灰色方 block 闪烁效果。

这是 Linux 上的 JDK8。

enter image description here

如何停止这种闪烁效果?

public class MenuTester {

public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setBounds(100, 100, 300, 200);


final JButton button = new JButton("Show Menu");
button.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
final JPopupMenu popupMenu = new JPopupMenu();
popupMenu.add(new JMenuItem("aaaa"));
popupMenu.add(new JMenuItem("bbbb"));
popupMenu.add(new JMenuItem("cccc"));
popupMenu.setLocation(100, 100);
popupMenu.setVisible(true);
try {
Thread.sleep(2000); // Leave enough time to clearly see the ?invalidated/background? area.
} catch (InterruptedException ex) {
// Nothing to do
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// Hide after 1 second
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
// Nothing to do
}
popupMenu.setVisible(false);
}
});
}
});

frame.add(button);
frame.setVisible(true);
}
}

最佳答案

据我所知,Swing 在显示窗口时存在“延迟”,这可能与操作系统实现帧与 native 消息和事件队列的连接之间的时间有关,但这纯粹是观察

我拿了你的代码,只需将框架的创建包装到 EventQueue.invokeLater 中就能够获得类似的行为

Delayed Startup

根据系统的启动和配置,您将在不同的系统上获得不同的结果

What is the event that causes the window to be rendered in the first pass?

我所做的就是获取您的代码并将 UI 的创建包装在 EventQueue.invokeLater 中,例如...

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class MenuTester {

public static void main(String[] args) {
new MenuTester();
}

public MenuTester() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

final JFrame frame = new JFrame();
frame.setBounds(100, 100, 300, 200);

final JButton button = new JButton("Show Menu");
button.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
final JPopupMenu popupMenu = new JPopupMenu();
popupMenu.add(new JMenuItem("aaaa"));
popupMenu.add(new JMenuItem("bbbb"));
popupMenu.add(new JMenuItem("cccc"));
popupMenu.setLocation(100, 100);
popupMenu.setVisible(true);
// try {
// Thread.sleep(2000); // Leave enough time to clearly see the ?invalidated/background? area.
// } catch (InterruptedException ex) {
// // Nothing to do
// }
// SwingUtilities.invokeLater(new Runnable() {
// @Override
// public void run() {
// // Hide after 1 second
// try {
// Thread.sleep(1000);
// } catch (InterruptedException ex) {
// // Nothing to do
// }
// popupMenu.setVisible(false);
// }
// });
}
});
frame.add(button);
frame.setVisible(true);
}
});
}
}

And is there a way to render the window as transparent during that first pass and opaque during the 2nd?

这不是一个新问题,自从我在 Java 1.3 中开始使用 Swing 以来,这一直是这种情况。您所问的意味着您知道油漆 channel 何时完成并完成。 Swing 并不完全愚蠢,它可以做出一些明智的决定来优化渲染过程(例如不绘制可见的组件)

另一个问题是,对于 JPopupMenu,您实际上并不知道它是否已显示在窗口中(或者只是作为组件显示在玻璃 Pane 上),因此整个事情非常复杂

关于java - 为什么 JPopupMenu 在渲染之前要经过 2 遍 UIThread?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45155842/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com