java wait cursor display problem

后端 未结 4 492
我寻月下人不归
我寻月下人不归 2020-11-22 14:22

I am having issues displaying a wait cursor in my application. Whenever the mouse is above a panel that defines its own cursor, the wait cursor does not appear. If a panel d

相关标签:
4条回答
  • 2020-11-22 15:01
    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_SELECTION);
            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);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 15:17

    After searching the internet, I found the answer to my question.

    The key is to set the cursor on the glasspane of the frame that contains the component which wants to display a busy cursor. I got the idea from the following articles on the net.

    Wait, Cursor, Wait!

    An Automatic Wait Cursor: WaitCursorEventQueue

    I modified my SSCE to make it work for the case when components inside the frame set their own cursor. Here is the modified SSCE.

    public class BusyCursorTest extends javax.swing.JFrame {
    
    private javax.swing.JPanel cursorPanel = null;
    
    public BusyCursorTest() {
    
        javax.swing.JMenuBar menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu menu = new javax.swing.JMenu("Menu");
        javax.swing.JMenuItem wait1 = new javax.swing.JMenuItem("Wait 100 ms");
        javax.swing.JMenuItem wait2 = new javax.swing.JMenuItem("Wait 250 ms");
        javax.swing.JMenuItem wait3 = new javax.swing.JMenuItem("Wait 500 ms");
        javax.swing.JMenuItem wait4 = new javax.swing.JMenuItem("Wait 1000 ms");
        menu.add(wait1);
        menu.add(wait2);
        menu.add(wait3);
        menu.add(wait4);
        menuBar.add(menu);
        setJMenuBar(menuBar);
        wait1.addActionListener(getActionListener(this, delayActionListener(100)));
        wait2.addActionListener(getActionListener(this, delayActionListener(250)));
        wait3.addActionListener(getActionListener(this, delayActionListener(500)));
        wait4.addActionListener(getActionListener(this, delayActionListener(1000)));
    
        cursorPanel = new javax.swing.JPanel();
        cursorPanel.addMouseListener(new java.awt.event.MouseAdapter() {
    
            public void mouseEntered(java.awt.event.MouseEvent e) {
                cursorPanel.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.CROSSHAIR_CURSOR));
            }
    
            public void mouseExited(java.awt.event.MouseEvent e) {
                cursorPanel.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR));
            }
    
        });
    
        javax.swing.JTabbedPane tabbedPane = new javax.swing.JTabbedPane();
        tabbedPane.addTab("Default", new javax.swing.JPanel());
        tabbedPane.addTab("Cursor change", cursorPanel);
        getContentPane().add(tabbedPane);
    
        setTitle("Cursor test");
        setSize(400, 400);
        setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE);
        setVisible(true);
    }
    
    private java.awt.event.ActionListener delayActionListener(final int delay) {
        java.awt.event.ActionListener listener = new java.awt.event.ActionListener() {
    
            public void actionPerformed(java.awt.event.ActionEvent ae) {
                try {
                    Thread.sleep(delay);
                } catch (InterruptedException e) {
                }
            }
    
        };
        return listener;
    }
    
    public static void main(String[] args) {
        new BusyCursorTest();
    }
    
    public static java.awt.event.ActionListener getActionListener(final javax.swing.JFrame frame,
        final java.awt.event.ActionListener originalActionListener) {
    
        java.awt.event.ActionListener actionListener = new java.awt.event.ActionListener() {
    
            public void actionPerformed(final java.awt.event.ActionEvent e) {
    
                java.util.TimerTask timerTask = new java.util.TimerTask() {
    
                    public void run() {
                        originalCursor = frame.getCursor();
                        startWaitCursor(frame);
                    }
    
                };
                java.util.Timer timer = new java.util.Timer();
    
                try {
                    timer.schedule(timerTask, DELAY_MS);
                    originalActionListener.actionPerformed(e);
                } finally {
                    timer.cancel();
                    stopWaitCursor(frame);
                }
            }
    
        };
        return actionListener;
    }
    
    private static void startWaitCursor(javax.swing.JFrame frame) {
        frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR));
        frame.getGlassPane().addMouseListener(mouseAdapter);
        frame.getGlassPane().setVisible(true);
    }
    
    private static void stopWaitCursor(javax.swing.JFrame frame) {
        frame.getGlassPane().setCursor(originalCursor);
        frame.getGlassPane().removeMouseListener(mouseAdapter);
        frame.getGlassPane().setVisible(false);
    }
    
    private static java.awt.Cursor originalCursor = null;
    
    private static final java.awt.event.MouseAdapter mouseAdapter = new java.awt.event.MouseAdapter() {
    };
    
    public static final int DELAY_MS = 250;
    

    }

    0 讨论(0)
  • hmmm you code have problem with Concurency in Swing there are two areas

    replace Thread.sleep(delay); and java.util.Timer with java.swing.Timer because block EDT

    but in other hands there is way how to purposely block EDT (by splungebob from OTN) NOTE: this example against all Swing rulles, and works just in this form and as the example

    import java.awt.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.event.*;
    
    public class DelayedComboBoxDemo implements Runnable {
    
        private JCheckBox chkA = new JCheckBox("A");
        private JCheckBox chkB = new JCheckBox("B");
        private JCheckBox chkC = new JCheckBox("C");
        private JComboBox cboItems = new JComboBox();
        private JFrame frame;
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new DelayedComboBoxDemo());
        }
    
        @Override
        public void run() {
            cboItems.addItem("-");
            JPanel p = new JPanel();
            p.add(chkA);
            p.add(chkB);
            p.add(chkC);
            p.add(cboItems);
            frame = new JFrame("Delayed ComboBox Test");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(p);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
            cboItems.addPopupMenuListener(new PopupMenuListener() {
    
                @Override
                public void popupMenuCanceled(PopupMenuEvent e) {
                }
    
                @Override
                public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                }
    
                @Override
                public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                    int items = cboItems.getItemCount();
                    rebuildList();
                    if (items != cboItems.getItemCount()) {
                        cboItems.hidePopup();
                        cboItems.showPopup();
                    }
                }
            });
        }
    
        private void rebuildList() {
            frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
            Vector<String> items = new Vector<String>();
            if (chkA.isSelected()) {
                items.add("A");
            } else if (chkB.isSelected()) {
                items.add("B");
            } else if (chkC.isSelected()) {
                items.add("C");
            } else {
                items.add("-");
            }
            cboItems.setModel(new DefaultComboBoxModel(items));
            try {
                Thread.sleep(3000); // simulate a long transaction
            } catch (InterruptedException ex) {
            }
            frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        }
    }
    
    0 讨论(0)
  • 2020-11-22 15:19

    Try setting it on the frame instead of a given component

    0 讨论(0)
提交回复
热议问题