【问题标题】:Label not updating in same instance of GUI标签未在同一 GUI 实例中更新
【发布时间】:2015-07-03 12:59:07
【问题描述】:

我有一个标签在同一个 GUI 实例中没有更新。 如果我单击应该更新 jLabel 上的值的 jButton(代码块中的“testLabel”),我必须再次运行 java 程序才能看到更改出现。我怎样才能让它出现在同一个实例中的按钮点击上? 我知道invokelater,我一直在尝试让它实时更新,但没有运气。我已经坚持了一段时间了,所以感谢您的帮助。 使用下面列出的代码块,我仍然需要运行一个新的 GUI 实例来获取要更新的值。

相关代码:

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                MISControlPanel window = new MISControlPanel();
                window.frame.setVisible(true);
                // testLabel.setText(CN);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

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

            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();

        }
    });

    try (BufferedReader br = new BufferedReader(new FileReader(
            "resultofbatch.txt"))) {

        final Pattern PATTERN = Pattern.compile("CN=([^,]+).*");
        try {
            while ((sCurrentLine = br.readLine()) != null) {

                String[] tokens = PATTERN.split(","); // This will return
                                                        // you a array,
                                                        // containing the
                                                        // string array
                                                        // splitted by what
                                                        // you write inside
                                                        // it.
                // should be in your case the split, since they are
                // seperated by ","
                // System.out.println(sCurrentLine);
                CN = sCurrentLine.split("CN=", -1)[1].split(",", -1)[0];

                System.out.println(CN);
                testLabel.setText(CN);
            }

全类代码 http://pastebin.com/havyqMxP

计算机查询类(小班) http://pastebin.com/Q89BCjya

【问题讨论】:

  • 您好 user6680...我不知道您打算在执行流程的哪个部分执行此操作,我看到您正在使用 LDAP。这意味着您正在连接到 LDAP服务器并可能执行一个长时间运行的任务...您是否尝试在任何类型的组件侦听器的回调中执行此操作(因此在事件调度线程中)?或者您正在另一个线程上执行此操作? Swing.invokelater 对此无济于事......我建议开始阅读 SwingWorker 并在 UI 上划分表示的操作(处理摆动组件的代码)
  • 我认为我需要它在不同的线程上运行,以便值将在 GUI 的同一实例中更新。我查看了您提供的教程链接,但我很困惑。它使用了在 done 方法中加载图像的示例,但我不确定如何将其实现到我的代码中。我一直在努力让它工作一个多星期。您是否有机会向我展示我正在努力完成的工作示例?
  • 我现在正在工作.. 但是当我有时间时,我会尝试详细说明一些代码以帮助您... 我的意思是,一个非常基本的窗口示例,在后台执行请求(通过 Web 获取一些数据.. 应该类似于通过 LDAP 服务器执行查询的操作)并更新组件以反映状态.....所有这些都使用SwingWorker 类。

标签: java swing concurrency swingworker


【解决方案1】:

正如所承诺的...这里是一个简单的示例,它使用 swing worker 获取 URL 内容,以将获取内容的任务(长期运行的任务)与更新 swing 组件的任务分离。这将显示一个示例,说明您应该如何处理此问题...

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingWorker;

/* FrameDemo.java requires no other files. */
public class MainWindow extends JFrame {
  private static final Logger LOOGER = Logger.getLogger(MainWindow.class.getName());

  /**
   * Create the GUI and show it.  For thread safety,
   * this method should be invoked from the
   * event-dispatching thread.
   */

  private JLabel statusLabel = new JLabel("Status");
  private JButton actionButton = new JButton("Push me");

  public MainWindow() {
    super("FrameDemo");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    statusLabel = new JLabel("Status");
    actionButton = new JButton("Push me");

    statusLabel.setPreferredSize(new Dimension(400, 50));
    actionButton.setPreferredSize(new Dimension(100, 50));
    getContentPane().setLayout(new BorderLayout());
    getContentPane().add(statusLabel, BorderLayout.NORTH);
    getContentPane().add(actionButton, BorderLayout.CENTER);

    actionButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        // THIS METHOD IS INVOKED WITHIN THE EVENT DISPATCH THREAD!!.. SO IS CRUCIAL TO NOT PERFORM
        // HERE LONG TIME RUNNING TASKS...
        actionButton.setEnabled(false); // let's disable this button, in order to avoid invoking
        // multiple times the same task and messing up the entire app...
        UrlFechterSwingWorker urlFechterSwingWorker = new UrlFechterSwingWorker();
        urlFechterSwingWorker.execute();
      }
    });
  }

  public void display() {
    pack();
    setVisible(true);
  }

  private class UrlFechterSwingWorker extends SwingWorker<String, String> {
    @Override
    public String doInBackground() { // this method is executed under a worker thread

      BufferedReader in;
      StringBuilder sb = new StringBuilder();
      try {
        URL url = new URL("http://www.stackoverflow.com");
        in = new BufferedReader(new InputStreamReader(url.openStream()));
        String line = in.readLine();
        while (line != null) {
          sb.append(line);
          publish(line); // publish partial results....
          line = in.readLine();
        }
        in.close();
      } catch (Exception e) {
        LOOGER.log(Level.SEVERE, "", e);
      }
      return sb.toString();
    }

    @Override
    protected void process(List<String> readedLines) { // this method in the Event dispatch Thread
      // do what you want to do with the readedLines....
      statusLabel.setText("The doInBackground read... " + readedLines.size() + " lines");
    }

    @Override
    public void done() { // this method in the Event dispatch Thread
      // do what you want when the process finish
      actionButton.setEnabled(true); // well.. at least i would like to enable the button again...
    }
  }

  public static void main(String[] args) {
    MainWindow mainWindow = new MainWindow();
    mainWindow.display();
  }
}

这里有更多提示:

  1. 在您了解(或多或少)上面示例中的工作原理之后.. 您将必须实现一个正确的 doInBackground 方法来执行所有 LDAP 内容,为此您必须使您的介意构想一种将进度通知给最终用户的方式...我的意思是,看我的示例,在进度进度方面非常差..我要说的所有事情是,我们从给定的网址。您应该考虑什么是通知您的任务进度的最佳方式。除了对底层域模型的理解之外,没有任何模板。

  2. 请记住,摇摆工人有两种方式来告知进度。

    • 一种是结合使用publishprocess 方法。 (如上例)
    • 其他是修改doInBackground方法内部的内部属性(进度和状态),并将PropertyChangeListener附加到swing worker。这个 propertyChangeListener 对象有一个签名为public void propertyChange(PropertyChangeEvent evt) 的方法(在我看来有点复杂..)
  3. 耐心等待,祝你好运!

【讨论】:

  • actionButton.setEnabled(false); == JButton.setMultiClickThreshhold 或 Swing 动作 - AbstractAction.setEnabled(false)
  • 加一个表示完全正确的描述,不要将镜头修改为黑暗(SwingWorker),也不要将其单独的监听器删除此建议
  • 感谢@mKorbel 的建议,我没有使用JButton.setMultiClickThreshhold ...感谢分享。关于“单独的听众”……您的意思是PropertyChangeListener?....请随意编辑我的帖子并实施您的建议
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多