16

アプリケーションで待機カーソルの表示に問題があります。マウスが独自のカーソルを定義するパネルの上にあるときはいつでも、待機カーソルは表示されません。パネルがカーソルを変更しない場合、待機カーソルが表示されます。

問題を正確に説明するために SSCE を添付しています。

public class BusyCursorTest extends javax.swing.JFrame {

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 java.awt.Component component,
    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 = component.getCursor();
                    component.setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR));
                }

            };
            java.util.Timer timer = new java.util.Timer();

            try {
                timer.schedule(timerTask, DELAY_MS);
                originalActionListener.actionPerformed(e);
            } finally {
                timer.cancel();
                component.setCursor(originalCursor);
            }
        }

    };
    return actionListener;
}

private javax.swing.JPanel cursorPanel = null;

public static java.awt.Cursor originalCursor = null;

public static final int DELAY_MS = 250;
}

付属の SSCE を実行します。

最初のタブ (「デフォルト」) が選択されている場合、1000ms メニュー項目をクリックするとビジー カーソルが表示されます。

2 番目のタブ (「カーソル変更」) が選択されている場合、1000ms メニュー項目をクリックしてもビジー カーソルが表示されません。

この問題を解決するにはどうすればよいですか?

どのパネルが最前線にあるかを追跡するのは非常に難しいため、コードでどのパネルも考慮する必要がないことを強く望みます。また、マウス クリックが原因でイベントが常に生成されるとは限りません。

最上位コンテナーで動作を変更できるようにするための推奨される回避策は何ですか?

4

4 に答える 4

6

インターネットを検索した後、私は私の質問に対する答えを見つけました。

重要なのは、ビジーカーソルを表示したいコンポーネントを含むフレームのガラスペインにカーソルを設定することです。ネットの以下の記事から着想を得ました。

待って、カーソル、待って!

自動待機カーソル: WaitCursorEventQueue

フレーム内のコンポーネントが独自のカーソルを設定する場合に動作するように、SSCE を変更しました。これが変更された 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;

}

于 2011-05-19T15:23:03.493 に答える
4
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);
    }
}
于 2011-05-19T15:00:52.030 に答える
2

うーん、あなたのコードはSwingの同時実行に問題があります.2つの領域があります

Thread.sleep(遅延); を置き換えます。EDTをブロックするため、 java.swing.Timerを使用したjava.util.Timer

しかし一方で、EDT を故意にブロックする方法があります (OTN の splungebob による) 注: この例はすべての Swing ルールに反しており、この形式で例として機能します。

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));
    }
}
于 2011-05-18T22:47:58.243 に答える
1

特定のコンポーネントの代わりにフレームに設定してみてください

于 2011-05-18T22:32:56.170 に答える