摆动:将光标更改为等待光标



参见Java Swing GUI沙漏。但是,提供的答案似乎不起作用。

我有以下代码:

private void loadFileMenuItemActionPerformed(java.awt.event.ActionEvent evt) {                                                
    int returnVal = fileChoser.showOpenDialog(this);
    if (returnVal == JFileChooser.APPROVE_OPTION) {
        try {
            this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
            // do stuff
        } finally {
            this.setCursor(Cursor.getDefaultCursor());
        }
    } 
}

当用户在菜单栏中选择相应的条目时,将调用此函数。但是,光标永远不会更改。请注意,加载文件需要一个文件,因此光标中的更改应该是可见的。

我做错了什么?

编辑:

this是顶级的JFrame。

编辑2:将解决方案移至单独的答案

首先创建一个 SwingWorker 类:

private class FileLoader extends SwingWorker<String, Void> {
    private final JFrame frame;
    private final File file;        
    public SdfLoader(JFrame frame, File file) {            
        frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        this.frame = frame;
        this.file = file;
    }
    @Override
    public String doInBackground() throws IOException {
            String result = null; 
            // read file and set result;
        return result;
    }
    @Override
    public void done() {
        try {
            String result = get();
            //do stuff 
        } catch (ExecutionException | InterruptedException ex) {
            // display error
            JOptionPane.showMessageDialog(SdfViewer.this,
                    ioException.getMessage(),
                    "Error opening file",
                    JOptionPane.ERROR_MESSAGE);
        } finally {
            frame.setCursor(Cursor.getDefaultCursor());
        }
    }
}

然后这样称呼它:

private void loadFileMenuItemActionPerformed(java.awt.event.ActionEvent evt) { 
    int returnVal = fileChoser.showOpenDialog(this);
    if (returnVal == JFileChooser.APPROVE_OPTION) {
        File file = fileChoser.getSelectedFile();
        logger.debug("Opening SD-File '{}'.", file.getAbsoluteFile());
        FileLoader loader = new FileLoader(this, file);
        loader.execute();
    } 
}  

@mKorbel编辑,请为此hi_jack向我道歉

  • 我在这里找不到带有此代码的帖子(底层数据库发生了一些事情),

  • 使用此逻辑,

  • 休息在我的评论中

虚拟 -1k 错误,错误,错误,您的 doInBackground() 丢失 publish()-process(), done() 非常错误 设计,阅读@trashgod回答中的评论,如果可能的话 可运行#用于FileIO,Socket或任何XxxStreams的线程而不是黑色 基于未来和摇摆工人的洞

  • 请根据编辑在您的线程中删除此代码

.

import java.awt.*;
import java.awt.event.*;
import java.text.SimpleDateFormat;
import java.util.Random;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.table.*;
public class TableWithTimer implements ActionListener, Runnable {
    private static final long serialVersionUID = 1L;
    private JFrame frame = new JFrame();
    private JScrollPane scroll = new JScrollPane();
    private JTable myTable;
    private JPanel buttonPanel = new JPanel();
    private JButton startButton = new JButton("Start Thread to Update Table");
    private JButton stopButton = new JButton("Stop Thread for Update Table");
    private JButton newButton = new JButton("Load new Data to Table");
    private int count = 0;
    private int delay = 3;
    private javax.swing.Timer timer = null;
    private boolean runProcess;
    private int row = 0;
    private int column = 0;
    private String value = "Amnd";
    private int amndValue = 0;
    private String valueAt = "";
    private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
    private String[] head = {"One", "Two", "Three", "Four", "Five", "Six"};
    private String[][] data = new String[25][6];
    public TableWithTimer() {
        myTable = new TableBackroundPaint0(data, head);
        myTable.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        myTable.setRowSelectionAllowed(false);
        myTable.setColumnSelectionAllowed(true);
        //myTable.setCellSelectionEnabled(true);
        myTable.setGridColor(Color.gray);
        myTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        final TableCellRenderer cellRendener = myTable.getTableHeader().getDefaultRenderer();
        myTable.getTableHeader().setDefaultRenderer(new TableCellRenderer() {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value,
                    boolean isSelected, boolean hasFocus, int row, int column) {
                JLabel label = (JLabel) cellRendener.getTableCellRendererComponent(
                        table, value, isSelected, hasFocus, row, column);
                label.setBackground(Color.orange);
                label.setForeground(Color.darkGray);
                label.setFont(new Font("SansSerif", Font.BOLD, 12));
                label.setBorder(BorderFactory.createCompoundBorder(label.getBorder(),
                        BorderFactory.createEmptyBorder(0, 5, 0, 0)));
                label.setHorizontalAlignment(SwingConstants.LEFT);
                label.setHorizontalAlignment(SwingConstants.CENTER);
                if ((label.getText().equals("First")) || (label.getText().equals("Second"))) {
                    label.setForeground(Color.red);
                }
                if ((label.getText().equals("Day")) || (label.getText().equals("Month")) || (label.getText().equals("Year"))) {
                    label.setForeground(Color.blue);
                }
                if ((label.getText().equals("Time"))) {
                    label.setForeground(Color.green);
                }
                return label;
            }
        });
        TableColumnModel cm = myTable.getColumnModel();
        for (int column1 = 0; column1 < cm.getColumnCount(); column1++) {
            TableColumn colLeft1 = cm.getColumn(column1);
            cm.getColumn(column1).setWidth(140);
            cm.getColumn(column1).setPreferredWidth(140);
        }
        //myTable.setFillsViewportHeight(true); // apply paintComponent for whole Viewport
        JButton cornerButtonTop = new JButton();
        cornerButtonTop.setBackground(scroll.getViewport().getBackground());
        JButton cornerButtonBottom = new JButton();
        cornerButtonBottom.setOpaque(false);
        scroll.setCorner(JScrollPane.UPPER_RIGHT_CORNER, cornerButtonTop);
        scroll.setCorner(JScrollPane.LOWER_RIGHT_CORNER, cornerButtonBottom);
        scroll.setViewportView(myTable);
        scroll.setMinimumSize(new Dimension(600, 400));
        scroll.setMaximumSize(new Dimension(900, 600));
        scroll.setPreferredSize(new Dimension(850, 430));
        frame.add(scroll, BorderLayout.CENTER);
        buttonPanel.setLayout(new GridLayout(1, 4, 10, 10));
        startButton.addActionListener(this);
        startButton.setEnabled(false);
        stopButton.addActionListener(this);
        stopButton.setEnabled(false);
        JButton hideButton = new JButton();
        newButton.addActionListener(this);
        newButton.setEnabled(false);
        buttonPanel.add(startButton);
        buttonPanel.add(stopButton);
        buttonPanel.add(hideButton);
        buttonPanel.add(newButton);
        hideButton.setVisible(false);
        frame.add(buttonPanel, BorderLayout.SOUTH);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocation(100, 100);
        frame.pack();
        frame.setVisible(true);
        start();
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == startButton) {
            runProcess = true;
            new Thread(this).start();
            myTable.requestFocus();
            startButton.setEnabled(false);
            stopButton.setEnabled(true);
        } else if (e.getSource() == stopButton) {
            scroll.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
            runProcess = false;
            startButton.setEnabled(true);
            stopButton.setEnabled(false);
            newButton.setEnabled(true);
        } else if (e.getSource() == newButton) {
            runProcess = false;
            startButton.setEnabled(true);
            stopButton.setEnabled(false);
            newButton.setEnabled(false);
            addNewData();
        }
    }
    public void addNewData() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                TableModel model = myTable.getModel();
                for (int j = 0; j < model.getRowCount(); j++) {
                    int column = model.getColumnCount();
                    for (int i = 0; i < column; i++) {
                        model.setValueAt("Deleted", j, i);
                    }
                }
                startNewData();
            }
        });
    }
    private void start() {
        scroll.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        timer = new javax.swing.Timer(delay * 100, updateCol());
        timer.start();
    }
    private void startNewData() {
        scroll.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        count = 0;
        timer = new javax.swing.Timer(1500, updateCol());
        timer.start();
    }
    @Override
    public void run() {
        scroll.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        count = 0;
        Random random = new Random();
        while (runProcess) {
            row = random.nextInt(myTable.getRowCount());
            column = random.nextInt(myTable.getColumnCount());
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        amndValue++;
                        valueAt = ((myTable.getValueAt(row, column)).toString());
                        if (!(valueAt.startsWith("A"))) {
                            count++;
                            if (count == ((25 * 6))) {
                                JOptionPane.showMessageDialog(myTable, " Update done ");
                                scroll.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                                runProcess = false;
                            }
                            java.util.Date date = new java.util.Date();
                            String dateTime = sdf.format(date.getTime());
                            myTable.setValueAt((value + " " + String.valueOf(amndValue) + " at: " + dateTime), row, column);
                            //myTable.setValueAt(new Integer(1), row, column); // please uncoment for generate misstype error on EDT
                            myTable.changeSelection(row, column, false, false);
                            System.out.println("update cycle with value :"
                                    + (value + " " + String.valueOf(amndValue) + " at: " + dateTime) + ", table row :" + row
                                    + ", table column " + column);
                        }
                    } catch (Exception e) {
                        runProcess = false;
                        System.out.println("Error for update JTable cell");
                        e.printStackTrace();
                    }
                }
            });
            try {
                Thread.sleep(500);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    public Action updateCol() {
        return new AbstractAction("text load action") {
            private static final long serialVersionUID = 1L;
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("updating row " + (count + 1));
                TableModel model = myTable.getModel();
                int cols = model.getColumnCount();
                int row = 0;
                for (int j = 0; j < cols; j++) {
                    row = count;
                    myTable.changeSelection(row, 0, false, false);
                    timer.setDelay(200);
                    Object value = "row " + (count + 1) + " item " + (j + 1);
                    model.setValueAt(value, count, j);
                }
                count++;
                if (count >= myTable.getRowCount()) {
                    myTable.changeSelection(0, 0, false, false);
                    timer.stop();
                    System.out.println("update cycle completed");
                    myTable.clearSelection();
                    startButton.setEnabled(true);
                    newButton.setEnabled(true);
                    scroll.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                }
            }
        };
    }
    public static void main(String args[]) {
        try {
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                System.out.println(info.getName());
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (UnsupportedLookAndFeelException e) {
            // handle exception
        } catch (ClassNotFoundException e) {
            // handle exception
        } catch (InstantiationException e) {
            // handle exception
        } catch (IllegalAccessException e) {
            // handle exception
        }
        TableWithTimer tableWithTimer = new TableWithTimer();
    }
}
class TableBackroundPaint0 extends JTable {
    private static final long serialVersionUID = 1L;
    TableBackroundPaint0(Object[][] data, Object[] head) {
        super(data, head);
        setOpaque(false);
        ((JComponent) getDefaultRenderer(Object.class)).setOpaque(false);
    }
    @Override
    public void paintComponent(Graphics g) {
        Color background = new Color(168, 210, 241);
        Color controlColor = new Color(230, 240, 230);
        int width = getWidth();
        int height = getHeight();
        Graphics2D g2 = (Graphics2D) g;
        Paint oldPaint = g2.getPaint();
        g2.setPaint(new GradientPaint(0, 0, background, width, 0, controlColor));
        g2.fillRect(0, 0, width, height);
        g2.setPaint(oldPaint);
        for (int row : getSelectedRows()) {
            Rectangle start = getCellRect(row, 0, true);
            Rectangle end = getCellRect(row, getColumnCount() - 1, true);
            g2.setPaint(new GradientPaint(start.x, 0, controlColor, (int) ((end.x + end.width - start.x) * 1.25), 0, Color.orange));
            g2.fillRect(start.x, start.y, end.x + end.width - start.x, start.height);
        }
        super.paintComponent(g);
    }
}

您看不到更改的原因很可能是您正在 EDT 上完成所有工作。永远不要那样做。即使您// do stuff单独的线程上,finally块也会在 UI 有机会重新绘制自身之前执行。

相反,您应该生成一个设置等待光标的SwingWorker,然后在后台执行繁重的工作(文件加载),最后在完成后重置为正常光标。

这可能表明一开始就不需要等待光标,在这种情况下使用进度条会更合适。

  • EventDispatchThread的常见问题是每个事件都在一瞬间完成,然后每个代码,方法,类都在一瞬间重新绘制,之后/当ActionListener中的所有代码被执行时

  • 然后,您必须将此逻辑拆分为包装到(最佳选项)两个摆动操作的两个单独事件,

    1. 一个用于切换光标 - 仅管理 游标可以从 PropertyChangeListener 或从 JMenuItem 的 ButtonModel 调用

    2. 另一个 Swing Action 或任何 SwingListener 来调用其余/或预期代码

    3. 你可以链接这两个摆动动作(我的上午),第一个调用第二个

哇 - 所有代码都是什么。它很简单:

final JScrollPane jsp = new JScrollPane(jt);
jsp.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
                //DO SOMETHING
jsp.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));

加载文件已经使 EDT 保持繁忙状态,因此它没有机会更改光标。

最新更新