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

Java Swing:为什么鼠标光标没有为第一个油漆更新?

顾宏朗
2023-03-14

我编写了一些Java Swing代码,收集一些输入,进行一些计算,然后显示结果。

预期结果:

  1. 对于每个用户输入:
  2. 用户转到文件->新建->输入一些数据。
  3. 在计算过程中鼠标光标变为旋转器。
  4. 显示结果。
  5. 鼠标光标返回默认值。
    null

请注意,我对此示例进行了大量删减,以消除实际程序中的大量U/I流,但此示例确实如所描述的那样中断。我无法进一步简化示例代码。

简化代码

package ca.pringle.maze.ui;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.Set;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;

import ca.pringle.maze.logic.Edge;
import ca.pringle.maze.logic.MazeConfig;
import ca.pringle.maze.logic.MazeMaker;
import ca.pringle.maze.logic.PathFinder;
import ca.pringle.maze.util.Pair;

public final class MazeDrawer extends JFrame {

    private final MazePanel mazePanel;

    public MazeDrawer() {
        mazePanel = new MazePanel();
    }

    public void init() {
        final JScrollPane scrollPane = new JScrollPane(mazePanel);
        final JMenuBar menuBar = createMenuBar((actionEvent) -> generateNewMaze());
        setJMenuBar(menuBar);

        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(scrollPane, BorderLayout.CENTER);

        setSize(100, 100);
        setVisible(true);
        repaint();
    }

    void generateNewMaze() {
        // if I comment out  this line below, then the spinner appears on the first run as expected.
        // if I leave this line in, then the spinner does not appear on the first run, only on subsequent runs
        JOptionPane.showConfirmDialog(null, null, "Enter new maze parameters", JOptionPane.OK_CANCEL_OPTION);

        final MazeConfig mazeConfig = new MazeConfig(1000, 1000, 1);

        final MazeMaker mazeMaker = new MazeMaker(mazeConfig);
        final PanelDimensions panelDimensions = new PanelDimensions(mazeConfig.getRows(), mazeConfig.getColumns(), 15, 15);

        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

        // the two lines below can take a long time depending on the inputs. I tried removing
        // them and replacing with a sleep to simulate and simplify the problem, but no luck,
        // so I left them in, even if I did not include the code.
        final Set<Edge> edges = mazeMaker.generateUndirectedMazeEdges();
        final Pair<Integer, Integer> startAndEndNodes = new PathFinder().findLongestPath(edges, mazeConfig);
        mazePanel.update(edges, startAndEndNodes, panelDimensions);
        mazePanel.setPreferredSize(new Dimension(panelDimensions.panelWidth, panelDimensions.panelHeight));
        mazePanel.repaint();

        setSize(Math.min(1200, panelDimensions.panelWidth + 11), Math.min(700, panelDimensions.panelHeight + 53));
        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    }

    private JMenuBar createMenuBar(final ActionListener menuListener) {

        final JMenuBar bar = new JMenuBar();

        final JMenu fileMenu = new JMenu("File");
        fileMenu.setMnemonic(KeyEvent.VK_F);

        final JMenuItem newMenuItem = new JMenuItem("New", KeyEvent.VK_N);
        newMenuItem.addActionListener(menuListener);
        fileMenu.add(newMenuItem);
        bar.add(fileMenu);

        return bar;
    }
}

感谢任何帮助。请假设我是一个完全的挥杆爱好者,所以一个更具体的回答/解释比一个假设我对挥杆有所了解的高水平回答/解释更有帮助。当然,我会阅读任何建议的文档。

如果有任何问题或澄清需要,请让我知道,我很高兴更新的帖子,如需要多次。

共有1个答案

沃驰
2023-03-14

我怀疑您的init()generateNewMaze()是从另一个线程调用的,并产生不可预测的结果。您不应该从EventDispachThread外部调用swing代码或操作swing对象。如果实际上不是从另一个线程调用,则不需要外部invokelater包装器。

这里有一个更好的方法来完成你想要做的事情:

void generateNewMaze() {
    SwingUtilities.invokeLater(() -> {
        JOptionPane.showConfirmDialog(null, null, "Enter new maze parameters", JOptionPane.OK_CANCEL_OPTION);

        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        mazePanel.setEnabled(false);

        new Thread(() -> {
            try {
                // Do the long running maze task; this sleep is to simulate that task
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            SwingUtilities.invokeLater(() -> {
                setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                mazePanel.setEnabled(true);
            });
        }).start();
    });
}

您还可以考虑使用玻璃窗格:等待光标并禁用java应用程序

 类似资料:
  • 我试图编写一个小迷宫运行程序,遇到了一些与绘图组件()相关的麻烦。我已经完成了调试,出于某种原因,我的绘图组件()从未被调用,即使是由我的计时器调用的重新绘制()。 这些是我的frame和jpanel init方法。 这是我的paintComponent,图像确实已缓冲并已存储。 这就是我的ActionExecuted,它是用我的计时器调用的,默认设置为5秒的间隔。 } 如果你感兴趣,这是我的完整

  • 本章介绍Canvas组件,用它来生成简单的二维(2D)图形,目标是创建一个PaintPot(油漆桶)应用,让用户在手机屏幕上绘制图画,并让用户用手机给自己拍照,然后在自己的照片上绘图。回顾历史,早在20世纪70年代,PaintPot是最早运行在个人电脑上的应用之一,目的是为了证明个人电脑的潜力。那时候,开发这样一款简单的绘图应用是一项极其复杂的工作,而且绘图效果也略显粗糙。但现在,使用App In

  • 问题内容: 如何为网页中的鼠标光标分配颜色? 谁能建议我使用HTML,CSS,JavaScript等任何技术来做到这一点的方法? 问题答案: 将图片与CSS 属性一起使用,我看不到需要JavaScript继承人… 如前所述,我只使用了其中的一种,只是以防万一您的图像无法加载,就像我们声明了多个字体系列一样。

  • 问题内容: 我在JList中有一个单词列表。每次将鼠标光标指向一个单词时,我都希望光标变为手形光标。现在我的问题是该怎么做? 有人可以帮我解决这个问题吗? 问题答案: 在JList上使用MouseMotionListener来检测鼠标何时输入,然后调用将其转换为。 样例代码:

  • 我有一个子类JPanel的PointPanel,我想在其中实现以下行为:如果鼠标悬停在实例上,按下shift键,鼠标光标变为手光标;如果松开shift键,鼠标光标将变回默认光标。 为了实现这一点,我尝试在构造函数中添加一个: 这种方法不起作用。 包含此面板的窗口应该具有焦点,因为它是应用程序的唯一可见窗口。 我错过了什么?

  • 我想安装Primeng7.0.0到我的Angular项目,但首先我需要更新我的JHipster到最后一个版本。 当我将此命令写入terminal时,我得到以下错误