从单独的线程中更新标签

时间:2014-07-28 12:27:21

标签: java multithreading label

我最近刚拿起Java而且我一直在研究一个时间保持应用程序(这些天我们都有可怕的时间表填写......)。

我一直在取得良好的进展,并且在Eclipse中找到Window Builder非常棒,但我完全被我的待办事项列表中的最后一件事难住了。我正在尝试使用我根据开始时间戳减去每秒计算的当前时间戳计算的时间字符串更新UI上的标签。这将表示当前任务所花费的时间。

到目前为止,这是我的代码,其他所有内容都与更新UI上的标签有关。它是代码底部的20(ish)行。

import java.io.FileWriter;
import java.io.IOException;

import javax.swing.*;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.wb.swt.SWTResourceManager;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.widgets.Table;

public class mainDisplay {
private static Text txtTask;
static boolean timerRunning = false;
static long timePassed = 0;
static long startTime = 0;
static long currTime = 0;
static String timeString = "";

/**
 * Launch the application.
 * @param args
 */

public static String timeString(long timePassed) {
    if(timePassed < 10) {
        timeString = "00:00:0"+String.valueOf(timePassed);
    }
    else if(timePassed < 60 && timePassed >= 10){
        timeString = "00:00:"+String.valueOf(timePassed);
    }
    else if(timePassed >= 60 && timePassed < 600){
        timeString = "00:0" + String.valueOf(timePassed/60) + ":";
        if(timePassed % 60 < 10){
            timeString = timeString + "0"+String.valueOf(timePassed%60);
        }
        else{
            timeString = timeString + String.valueOf(timePassed%60);
        }
    }
    else if(timePassed >= 600 && timePassed < 3600){
        timeString = "00:" + String.valueOf(timePassed/60) + ":";
        if(timePassed % 60 < 10){
            timeString = timeString + "0"+String.valueOf(timePassed%60);
        }
        else{
            timeString = timeString + String.valueOf(timePassed%60);
        }
    }
    else if(timePassed >= 3600 && timePassed < 36000){
        // Hours
        timeString = "0" + String.valueOf(timePassed/3600) + ":";
        // Mins
        if((timePassed%3600)/60 < 10){
            timeString = timeString + "0" + String.valueOf((timePassed%3600)/60) + ":";
        }
        else if((timePassed%3600)/60 >= 10){
            timeString = timeString + String.valueOf((timePassed%3600)/60) + ":";
        }
        // Secs
        if((timePassed%3600)%60 < 10){
            timeString = timeString + "0" + String.valueOf((timePassed%3600)%60);
        }
        else if((timePassed%3600)%60 >= 10){
            timeString = timeString + String.valueOf((timePassed%3600)%60);
        }
    }
    return timeString;
}

public static void main(final String[] args) {
    Display display = Display.getDefault();
    final Shell shlSot = new Shell();
    shlSot.setBackground(SWTResourceManager.getColor(SWT.COLOR_TITLE_BACKGROUND));
    shlSot.setSize(455, 299);
    shlSot.setText("SOT 1.0");

    txtTask = new Text(shlSot, SWT.BORDER);
    txtTask.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseUp(MouseEvent e) {
            txtTask.setText("");
        }
    });
    txtTask.setFont(SWTResourceManager.getFont("Segoe UI", 11, SWT.NORMAL));
    txtTask.setText("Add a task...");
    txtTask.setBounds(10, 62, 198, 27);

    Label lblTitle = new Label(shlSot, SWT.NONE);
    lblTitle.setFont(SWTResourceManager.getFont("Script MT Bold", 22, SWT.BOLD));
    lblTitle.setBackground(SWTResourceManager.getColor(SWT.COLOR_TITLE_BACKGROUND));
    lblTitle.setBounds(45, 15, 175, 37);
    lblTitle.setText("Sands of Time");

    final Table tblTasks = new Table(shlSot, SWT.BORDER | SWT.FULL_SELECTION);
    tblTasks.setBounds(10, 107, 417, 144);
    tblTasks.setHeaderVisible(true);
    tblTasks.setLinesVisible(true);

    TableColumn clmTask = new TableColumn(tblTasks, SWT.NONE);
    clmTask.setText("Task");
    TableColumn clmTime = new TableColumn(tblTasks, SWT.NONE);
    clmTime.setText("Time");

    tblTasks.getColumn(0).pack();
    tblTasks.getColumn(1).pack();

    Label lblHourGlass = new Label(shlSot, SWT.NONE);
    lblHourGlass.setBackground(SWTResourceManager.getColor(SWT.COLOR_TITLE_BACKGROUND));
    lblHourGlass.setFont(SWTResourceManager.getFont("Wingdings", 30, SWT.NORMAL));
    lblHourGlass.setBounds(14, 11, 32, 46);
    lblHourGlass.setText("6");

    final Label lblTimer = new Label(shlSot, SWT.NONE);
    lblTimer.setAlignment(SWT.CENTER);
    lblTimer.setFont(SWTResourceManager.getFont("Segoe UI", 19, SWT.NORMAL));
    lblTimer.setBackground(SWTResourceManager.getColor(SWT.COLOR_TITLE_BACKGROUND));
    lblTimer.setBounds(268, 17, 113, 32);
    lblTimer.setText("00:00:00");

    final Button btnExport = new Button(shlSot, SWT.NONE);
    final Button btnClear = new Button(shlSot, SWT.NONE);
    final Button btnStart = new Button(shlSot, SWT.NONE);
    final Button btnStop = new Button(shlSot, SWT.NONE);

    btnClear.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
            int dialogButton = 0;
            // Prompt the user whether to go ahead or not
            int dialogResult = JOptionPane.showConfirmDialog (null, "Are you sure you want to clear all progress?","Warning",dialogButton);
            if(dialogResult == JOptionPane.YES_OPTION){
                // Stop the timer
                timerRunning = false;

                // Clear the timer on the UI
                lblTimer.setText("00:00:00");

                // Enable/Disable buttons and reset text
                btnStop.setEnabled(false);
                btnExport.setEnabled(true);
                btnStart.setEnabled(true);
                txtTask.setEnabled(true);
                txtTask.setText("Add a task...");

                // Empty the list on the UI
                tblTasks.removeAll();
            }
        }
    });
    btnClear.setBounds(370, 63, 57, 25);
    btnClear.setText("Clear");


    btnExport.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
            // Export the contents of the list to CSV
            try{
                FileWriter writer = new FileWriter("sotExport.csv");

                writer.append("Task");
                writer.append(',');
                writer.append("Time");
                writer.append('\n');

                TableItem [] items = tblTasks.getItems ();
                for(int i=0; i<items.length; i++) {                     
                    writer.append(items[i].getText(0));
                    writer.append(',');
                    writer.append(items[i].getText(1));
                    writer.append('\n');
                }

                writer.flush();
                writer.close();
            }
            catch(IOException e1){
                 e1.printStackTrace();
            }
        }
    });
    btnExport.setBounds(319, 63, 46, 25);
    btnExport.setText("Export");

    btnStop.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
            // Stop button stuff

            // Add contents of txtTask to list
            //lstTasks.add(txtTask.getText());
            TableItem item = new TableItem(tblTasks, SWT.NONE);
            item.setText(0, txtTask.getText());
            item.setText(1, timeString);
            tblTasks.getColumn(0).pack();
            tblTasks.getColumn(1).pack();

            btnStop.setEnabled(false);
            btnClear.setEnabled(true);
            btnExport.setEnabled(true);
            btnStart.setEnabled(true);
            txtTask.setEnabled(true);
            timerRunning = false;
        }
    });
    btnStop.setBounds(267, 63, 46, 25);
    btnStop.setText("Stop");
    btnStop.setEnabled(false);


    btnStart.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
            // Update UI options
            btnStop.setEnabled(true);
            btnStart.setEnabled(false);
            txtTask.setEnabled(false);
            btnClear.setEnabled(false);
            btnExport.setEnabled(false);

            // Start timer and update lblTimer
            timerRunning = true;
            startTime = (System.currentTimeMillis() / 1000L);
            System.out.println(startTime);

            new Thread(new Runnable(){ 
                public void run(){ 
                    while (timerRunning){ 
                        // Get current time and calculate timer                     
                        currTime = System.currentTimeMillis() / 1000L;
                        timePassed = currTime - startTime;
                        timeString = timeString(timePassed);

                        try {
                            // Why do you not work?!!?!? >:(
                            lblTimer.setText(timeString);

                            Thread.sleep(1000);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
                    } 
                } 
            }).start();
        }
    });
    btnStart.setBounds(214, 63, 46, 25);
    btnStart.setText("Start");

    shlSot.open();
    shlSot.layout();
    while (!shlSot.isDisposed()) {
        if (!display.readAndDispatch()) {
            display.sleep();
        }
    }
}
}

当我点击开始时,我收到以下例外;

Exception in thread "Thread-0" org.eclipse.swt.SWTException: Invalid thread access
    at org.eclipse.swt.SWT.error(SWT.java:4397)
    at org.eclipse.swt.SWT.error(SWT.java:4312)
    at org.eclipse.swt.SWT.error(SWT.java:4283)
    at org.eclipse.swt.widgets.Widget.error(Widget.java:472)
    at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:363)
    at org.eclipse.swt.widgets.Label.setText(Label.java:386)
    at mainDisplay$5$1.run(mainDisplay.java:246)
    at java.lang.Thread.run(Unknown Source)

不确定为什么它会在第一轮中断异常,但确实如此。

这是线程问题吗?我是否可以从新线程中访问显示线程以更新标签?知道如何绕过它?

由于

史蒂夫

1 个答案:

答案 0 :(得分:1)

想出来......

我刚换了;

lblTimer.setText(timeString);

用;

display.asyncExec(new Runnable() {
   public void run() {
      lblTimer.setText(timeString);
   }
});

如果有人仍想提供一个很受欢迎的好解释。