【问题标题】:Updating JLabel with thread使用线程更新 JLabel
【发布时间】:2015-07-04 13:44:44
【问题描述】:

我正在尝试让一个线程在单击按钮时为 swing 应用程序运行,但该值没有更新。 它应该获取我正在搜索的计算机名称,但为了更新值,我必须启动一个新的 GUI 实例。 我创建了一个线程,但由于某种原因它不起作用。任何帮助表示赞赏。

(t.start 在代码块的末尾)

searchComputerButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
              Thread t = new Thread("my non EDT thread") {
                    public void run() {
                        //my work
                        testLabel.setText(CN);
                    }

                };

            String line;
            BufferedWriter bw = null;
            BufferedWriter writer = null;
            try {
                writer = new BufferedWriter(new FileWriter(tempFile));
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            // String lineToRemove = "OU=Workstations";

            String s = null;

            Process p = null;
            /*
             * try { // p = Runtime.getRuntime().exec(
             * "cmd /c start c:\\computerQuery.bat computerName"); } catch
             * (IOException e1) { // TODO Auto-generated catch block
             * e1.printStackTrace(); }
             */
            try {

                p = Runtime.getRuntime().exec("c:\\computerQuery.bat");

            } catch (IOException e1) {

                // TODO Auto-generated catch block

                e1.printStackTrace();

            }
            StringBuffer sbuffer = new StringBuffer();
            BufferedReader in = new BufferedReader(new InputStreamReader(p
                    .getInputStream()));

            try {

                while ((line = in.readLine()) != null) {

                    System.out.println(line);

                    // textArea.append(line);

                    String dn = "CN=FDCD111304,OU=Workstations,OU=SIM,OU=Accounts,DC=FL,DC=NET";
                    LdapName ldapName = new LdapName(dn);
                    String commonName = (String) ldapName.getRdn(
                            ldapName.size() - 1).getValue();

                }
                ComputerQuery.sendParam();

            } catch (IOException e1) {

                // TODO Auto-generated catch block

                e1.printStackTrace();

            } catch (InvalidNameException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } finally

            {
                try {
                    fw.close();

                }

                catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }

            try {

                in.close();

            } catch (IOException e1) {

                // TODO Auto-generated catch block

                e1.printStackTrace();

            }

            ComputerQuery.sendParam();
            t.start();
        }
    });

更新

private void threadStart() {
          SwingUtilities.invokeLater(new Runnable() {
            public void run() {

              testLabel.setText(CN);
            }
          });

我把方法放在这里

JButton searchComputerButton = new JButton("Search");
        searchComputerButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                threadStart();
                String line;

【问题讨论】:

  • 所有 GUI 更新都应在 EDT 上完成。
  • 我以前听过这个,但我不是很明白。你有没有机会给我一个我应该做什么的工作示例?
  • “你有没有机会给我一个工作的例子..” 你有没有机会意识到 SO 不是一个代码生成机器,并实际投入一些靠自己努力?碰巧,我有一个围绕这些部分的示例,它使用 Swing Timer 定期建立 SwingWorker 并重复执行长时间运行的任务。搜索一下,你可能会找到它。

标签: java swing concurrency jlabel event-dispatch-thread


【解决方案1】:

注意摆动线程https://docs.oracle.com/javase/tutorial/uiswin/concurrency/

看看这里: http://www.javamex.com/tutorials/threads/invokelater.shtml

您必须使用 Method 将您的 JLabel 更新方法调用加入队列 SwingUtilities.invokeLater(???)。 下面的例子就可以了

我认为这与 .batch 文件调用有关。看看这里:How do I run a batch file from my Java Application? 可运行任务 = new UpdateJob("查询:" + i); SwingUtilities.invokeLater(task);


为了更容易理解。

Swing 在一个线程中管理所有绘制操作。 它提供了一个队列。如果您从该队列外部调用方法,则行为是完全不可预测的.. NullPointer... RuntimeExc .... 但是如果您调用 SwingUtilities.invokeLater(...) 您的方法将被排入 Swing-Queue 并尽快调用!

由于评论而更新:

检查你的主线程(GUI) 检查你的线程。 当子线程(例如 ActionListener)想要调用 JLabel::setText 它必须使用方法 SwingUtils::InvokeLater("...");

这意味着invokeLater() 必须在不直接属于主线程的所有线程中调用。

由于问题而更新

在我看来,您当前的代码根本不需要 SwingUtilities.invok..。 您是否更改了分配给您的问题的代码。

【讨论】:

  • 我使用invokelater更新了我的代码,但它仍然不会更新。你能告诉我我做错了什么吗?请参阅上面的更新代码
  • 我认为问题在于 Runtime.getRuntime(... 调用。所以 SwingUtililties.invokerLater 必须在该函数之外进行,
  • 我认为更新不是您问题的真正根源!
  • 从应用程序外部初始化的线程在哪里?
  • 如果你指的是这个线程 t = new Thread("my non EDT thread") { 我删除它并尝试调用稍后的代码。这是更新的完整课程代码pastebin.com/D25Tki2J 你是说我应该把它留在这里吗?因为我稍后不会在调用中调用线程。我应该吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-22
相关资源
最近更新 更多