JFXPanel第二次冻结AWT线程

时间:2018-10-16 09:58:53

标签: java swing javafx

我正在为正在开发的游戏添加成就,因此决定将嵌入式JavaFX用于某些徽章设计(主要应用程序基于Swing)。

我创建了一个AchievementMedal类,作为JFXPanel的扩展:

public AchievementMedal(int angle, Color color) 
{
    setSize(200, 200);

    this.finalAngle = angle;
    this.color = color;

    Path p = drawPartialRing(finalAngle);
    Scene scene = new Scene(new Group(p), 180, 180);
    scene.setFill(Color.TRANSPARENT);

    setScene(scene);
}

为简洁起见,这里没有包括'drawPartialRing'方法,但下面的我将其完整包含在我的SSCE中。它只是通过ArcTo,LineTo和MoveTo调用构建路径。

然后,我将其中几个添加到常规JPanel中,并将其添加到应用程序的主JFrame中进行显示。当您离开并再次返回到Achievements时,将删除并重新添加此JPanel。但是,在导航到 second 时,AWT线程挂起,并带有以下堆栈:

Thread [AWT-EventQueue-0] (Suspended)
    Unsafe.park(boolean, long) line: not available [native method]
    LockSupport.park(Object) line: not available
    CountDownLatch$Sync(AbstractQueuedSynchronizer).parkAndCheckInterrupt()
    CountDownLatch$Sync(AbstractQueuedSynchronizer).doAcquireSharedInterruptibly(int)
    CountDownLatch$Sync(AbstractQueuedSynchronizer).acquireShareInterruptibly(int)
    CountDownLatch.await()
    AchievementMedal(JFXPanel).setScene(Scene) line: 311
    AchievementMedal.<init>(int, Color) line: 20
    AchievementPanel.<init>() line: 32
    JfxSSCE.actionPerformed(ActionEvent) line: 37
    JButton(AbstractButton).fireActionPerformed(ActionEvent)

我设法创建了一个SSCE来复制它。最奇怪的部分是,如果您仅删除成就奖章之一,那绝对没问题。因此,看起来6可以正常工作,但是以某种方式7是极限!我尝试将Java版本(从jre1.8.0_111升级到jre1.8.0_181)无济于事。这是我的SSCE(使用简单的圆圈),由3个类组成:

public class AchievementMedal extends JFXPanel
{
    public AchievementMedal(Color color) 
    {
        setSize(200, 200);

        Circle c = new Circle(90, 90, 85, color);
        Scene scene = new Scene(new Group(c), 180, 180);
        scene.setFill(Color.TRANSPARENT);

        setScene(scene);
    }
}

要交换的AchievementPanel,包含7个AchievementMedals(只需删除任何'panelGeneral.add ...'子句即可使其神奇地工作):

public class AchievementPanel extends JPanel
{
    public AchievementPanel()
    {
        setPreferredSize(new Dimension(800, 610));
        setLayout(new BorderLayout(0, 0));
        JTabbedPane tabbedPane = new JTabbedPane(SwingConstants.TOP);
        add(tabbedPane, BorderLayout.CENTER);


        tabbedPane.addTab("General", null, panelGeneral, null);

        panelGeneral.add(gray);
        panelGeneral.add(red);
        panelGeneral.add(orange);
        panelGeneral.add(yellow);
        panelGeneral.add(green);
        panelGeneral.add(cyan);
        panelGeneral.add(hotpink);
    }

    private final JPanel panelGeneral = new JPanel();
    private final AchievementMedal gray = new AchievementMedal(Color.GRAY);
    private final AchievementMedal red = new AchievementMedal(Color.RED);
    private final AchievementMedal orange = new AchievementMedal(Color.ORANGE);
    private final AchievementMedal yellow = new AchievementMedal(Color.YELLOW);
    private final AchievementMedal green = new AchievementMedal(Color.LIGHTGREEN);
    private final AchievementMedal cyan = new AchievementMedal(Color.CYAN);
    private final AchievementMedal hotpink = new AchievementMedal(Color.DEEPPINK);
}

使用一些基本按钮模仿换入/换入行为的小型JFrame:

public class JfxSSCE extends JFrame
                 implements ActionListener
{
public JfxSSCE() 
{
    setSize(800, 600);

    JPanel panel = new JPanel();
    getContentPane().add(panel, BorderLayout.SOUTH);

    panel.add(btnAddPanel);
    panel.add(btnRemovePanel);

    btnRemovePanel.setVisible(false);

    btnAddPanel.addActionListener(this);
    btnRemovePanel.addActionListener(this);
}

private final JButton btnAddPanel = new JButton("Add Panel");
private final JButton btnRemovePanel = new JButton("Remove Panel");
private JPanel panelCenter = new JPanel();

@Override
public void actionPerformed(ActionEvent e)
{
    if (e.getSource() == btnAddPanel)
    {
        panelCenter = new AchievementPanel();
        getContentPane().add(panelCenter, BorderLayout.CENTER);

        btnAddPanel.setVisible(false);
        btnRemovePanel.setVisible(true);
    }
    else
    {
        getContentPane().remove(panelCenter);
        repaint();

        btnAddPanel.setVisible(true);
        btnRemovePanel.setVisible(false);
    }
}


public static void main(String[] args)
{
    JfxSSCE frame = new JfxSSCE();
    frame.setVisible(true);
}
}

我对这里发生的事情一无所知!

0 个答案:

没有答案