【问题标题】:Java frame not displaying properly during a while loopJava 框架在 while 循环期间无法正确显示
【发布时间】:2017-06-23 22:49:24
【问题描述】:

这是我在使用 jFrame 时遇到的一个严重问题。我有一个“主框架”,一切都是从那里完成的,但是我有另一个框架,里面有一个 gif 图像(正在加载,那个圆圈转来转去),它用作启动画面,上面写着“正在处理,请稍候” ,但是当我拉过那个框架并且我的 while 循环运行时,框架变为空白,直到循环之后才显示任何内容。

我假设这是由于 while 循环消耗计算机资源并“阻止”任何其他进程运行。

请告诉我应该怎么做。

声明新框架的代码是标准的,但我还是会在下面发布。

Processing nc = new Processing();
nc.setVisible(true);

这是我的完整代码,因此您可以看到我试图实现的目标:

第 1 帧的代码(Excel 提取器):

Processing nc = new Processing();
    nc.setVisible(true);

    JFileChooser chooser = new JFileChooser();
    chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    int option = chooser.showOpenDialog(this); // parentComponent must a component like JFrame, JDialog...
    if (option == JFileChooser.APPROVE_OPTION) {
    File selectedFile = chooser.getSelectedFile();
     directory = selectedFile.getAbsolutePath();
     System.out.println(directory);

    }


   //create a input stream for your excel file from which data will be read. 
   DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd");
   SimpleDateFormat sdf = new SimpleDateFormat("HHmmss");
   String curdate = dateFormat.format(new Date());
   Calendar cal = Calendar.getInstance();
   cal.getTime();
   String curtime = sdf.format(cal.getTime());
try{

FileInputStream excelSheetInput = new FileInputStream(path);
//POIFSFileSystem myFileSystem = new POIFSFileSystem(excelSheetInput);
    XSSFWorkbook myWorkBook = new XSSFWorkbook(excelSheetInput);
    //get first work sheet in your excel file.
    Sheet sheet = myWorkBook.getSheetAt(0);
    //we will read data in first rows(0) second column(1)
    Iterator<Row> rowIterator = sheet.iterator();
    Row myRow1 = sheet.getRow(0);
    Cell myCell1 = myRow1.getCell(0);
    String header="";
    Iterator<Cell> cellIterator1 = myRow1.cellIterator();
    int rowCount = 0;

    while(cellIterator1.hasNext()) {

                            Cell cell1 = cellIterator1.next();

                            switch(cell1.getCellType()) {
                                case Cell.CELL_TYPE_BOOLEAN:
                                    header = header + "\""+cell1.getBooleanCellValue()+"\"" + ",";
                                    break;
                                case Cell.CELL_TYPE_NUMERIC:
                                    cell1.setCellType(Cell.CELL_TYPE_STRING);
                                     header = header + "\""+cell1.getStringCellValue()+"\""+",";
                                    //System.out.print(cell.getStringCellValue() + "\t\t");
                                    break;
                                case Cell.CELL_TYPE_STRING:
                                    header = header + "\""+cell1.getStringCellValue()+"\""+",";
                                    //System.out.print(cell.getStringCellValue() + "\t\t");
                                    break;
                            }
    }

    Row myRow = sheet.getRow(1);
    Cell myCell= myRow.getCell(0);
    Iterator<Cell> cellIterator;
    String firstCell = myCell.getStringCellValue();
    int count =1;
    String nextCell;
    String Matter = "Matter Number: "+firstCell;
    String num = firstCell;
    System.out.println(Matter);
    fWriter = new FileWriter(new File(directory, num+"_"+curdate+"_"+curtime+".csv"));
    writer = new BufferedWriter(fWriter);
    writer.write(Matter);
    writer.newLine();
    writer.write(header);
    writer.newLine();
    String temp;
    while(rowIterator.hasNext())
    {


        //temp = "" + rowCount;
        //jLabel5.setText(temp);
        myRow = sheet.getRow(count);
        cellIterator = myRow.cellIterator();
        Cell myCell2 = myRow.getCell(0);
        nextCell= myCell2.getStringCellValue();


        if(nextCell.equals(firstCell))
        {

            while(cellIterator.hasNext()) {

                            Cell cell = cellIterator.next();

                            switch(cell.getCellType()) {
                                case Cell.CELL_TYPE_BOOLEAN:
                                    System.out.print(cell.getBooleanCellValue() + "\t\t");
                                    break;
                                case Cell.CELL_TYPE_NUMERIC:
                                    cell.setCellType(Cell.CELL_TYPE_STRING);

                                     System.out.print(cell.getStringCellValue()+",");

                                    //System.out.print(cell.getStringCellValue() + "\t\t");
                                    writer.write(cell.getStringCellValue()+",");
                                    break;
                                case Cell.CELL_TYPE_STRING:
                                    System.out.print(cell.getStringCellValue()+",");
                                    //System.out.print(cell.getStringCellValue() + "\t\t");
                                    writer.write(cell.getStringCellValue()+",");
                                    break;
                            }
                        }
            System.out.println();
            writer.newLine();
            count++;
            rowCount++;



        }
        else
        {          

            writer.close();
            myRow = sheet.getRow(count);
            myCell2= myRow.getCell(0);
            nextCell=myCell2.getStringCellValue();
            firstCell=nextCell;
            Matter = "Matter Number: "+firstCell;
            num = firstCell;
            System.out.println(Matter);
            fWriter = new FileWriter(new File(directory, num+"_"+curdate+"_"+curtime+".csv"));
            writer = new BufferedWriter(fWriter);
            writer.write(Matter);
            writer.newLine();
            writer.write(header);
            writer.newLine();
        }


    }
}
catch (Exception e)
{
}

  try {
    nc.dispose();
    writer.close();
} catch (IOException ex) {
    Logger.getLogger(FileChooser.class.getName()).log(Level.SEVERE, null, ex);
}
}

第二帧代码(处理):

private void initComponents() {

    jLabel1 = new javax.swing.JLabel();
    jLabel2 = new javax.swing.JLabel();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    jLabel1.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
    jLabel1.setText("Processing, Please Wait...");

    jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
    jLabel2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/loading.gif"))); // NOI18N

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jLabel1)
            .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jLabel1)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jLabel2)
            .addContainerGap())
    );

    pack();
}

【问题讨论】:

  • while 循环在哪个线程上运行?如果您的 while 循环在 Event Dispatch Thread 上运行,则事件处理将被阻塞,直到 while 循环完成。
  • 基本上我关注的是处理 nc = new processing();
  • 没有代码更好,为了获得更好的帮助,请尽快发布SSCCE,简短,可运行,可编译,更多可以在@MadProgrammer 的回答中看到

标签: java swing netbeans concurrency jframe


【解决方案1】:

在不完全了解您要做什么的情况下,您不可能完全得到准确的答案。

从您尝试在事件调度线程的上下文中运行长时间运行的任务的声音来看。该线程负责处理重绘请求等。

阻塞这个线程,防止 Swing 重新绘制自己。

据我所知,您想使用SwingWorker。这将允许您在后台线程中执行您的工作,同时将更新重新同步回 EDT

更新示例

我知道你说过“不想”使用SwingWorker,但老实说,它只是更简单、更安全......

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class LongRunningTask {

    public static void main(String[] args) {
        new LongRunningTask();
    }

    public LongRunningTask() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                new BackgroundWorker().start();

            }
        });
    }

    public class BackgroundWorker extends SwingWorker<Object, Object> {

        private JFrame frame;

        public BackgroundWorker() {
        }

        // Cause exeute is final :P
        public void start() {
            ImageIcon icon = new ImageIcon(getClass().getResource("/spinner.gif"));
            JLabel label = new JLabel("This might take some time");
            label.setIcon(icon);

            frame = new JFrame("Testing");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(new GridBagLayout());
            frame.add(label);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);

            execute();
        }

        @Override
        protected Object doInBackground() throws Exception {

            System.out.println("Working hard...");
            Thread.sleep(1000 + (((int)Math.round(Math.random() * 5)) * 1000));
            System.out.println("Or hardly working...");

            return null;

        }

        @Override
        protected void done() {
            frame.dispose();
        }

    }
}

【讨论】:

  • MadProgrammer 感谢您的回复,它们总是非常有用。但是在这种情况下,我不确定我是否会调用 SwingWorker?第二帧在用户选择了输出路径之后在 while 循环之外运行,所以这肯定是一个过程吗?
  • while 循环仍然会阻塞 UI。如果您打算通过此循环与 UI 交互,SwingWorker 是您的最佳选择,否则您将需要某种线程,但是您会遇到回调问题并稍后将它们重新同步回 UI,SwingWorker 会解决这个问题给你
  • 我无意与框架交互,它就像一个加载窗格,但只是告诉用户应用程序正在处理请求,仅此而已。
  • 您唯一需要做的就是能够判断循环何时完成。看看 SwingUtililites.invokeLater
  • invokeLater 方法似乎对我不起作用,直到循环完成 gif 图像仍然不显示,但是现在显示文本
【解决方案2】:

您使用 java.util 包中的 Timer 类并安排 timertask 在大约 2 分钟或任务完成后关闭启动屏幕。

 final Processing nc = new Processing();
 nc.setVisible(true);
 Timer timer = new Timer():
 TimerTask task = new TimerTask() {
      public void run() { 
          nc.setVisible( false );
          // to do disposing nc
      }
 };
 timer.schedule( task, 1000 * 3 ); // dispose the processing frame after 3 minutes

【讨论】:

  • 不,你不应该。使用 java.util.Timer 不会执行 Event Dispatching Thread 的 run 方法,这违反了 Swing 的线程规则。你可以改用 javax.swing.Timer
  • 我从过去的经验中知道 java.util.time 永远不会正常工作,事实上如果我正确的话它会阻止 EDT?如果使用时间,则使用的是 javax.swing.timer ......我可能完全错了,但我很确定这就是我读到的内容,但在这种情况下,定时器不会帮助它需要运行一段时间循环运行
  • java.util.Timer 在调度程序为其创建的线程的上下文中执行,这很可能不是 EDT,因为它与 Swing 或 AWT 无关。 Swing 计时器保证 actionPerformed 方法在 EDT 内执行,因此如果您要在计时器内与 UI 交互,那么您需要一个 Swing 计时器
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多