проблема отображения курсора java wait

У меня возникают проблемы с отображением курсора ожидания в моем приложении. Всякий раз, когда мышь находится над панелью, которая определяет свой собственный курсор, курсор ожидания не появляется. Если панель не изменит курсор, появится курсор ожидания.

Я прикрепляю 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 отобразит курсор занятой.

Когда выбрана вторая вкладка («Смена курсора»), нажатие на пункт меню 1000ms не отображает курсор занятой.

Как мне исправить эту проблему?

Я бы предпочел, чтобы мой код не учитывал ни одну из панелей, так как мне очень сложно отслеживать, какие панели могут быть на переднем крае. Кроме того, события не всегда генерируются из-за щелчка мыши.

Какое рекомендуемое обходное решение, чтобы я мог изменить поведение в контейнере верхнего уровня?

После поиска в Интернете я нашел ответ на свой вопрос.

Ключ состоит в том, чтобы установить курсор на стеклянную панель кадра, содержащую компонент, который хочет отображать курсор занятости. Я получил эту идею из следующих статей в сети.

Подождите, Курсор, Подождите!

Автоматический курсор ожидания: 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; 

}

 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); } } 

хм, у вас код проблемы с Concurency в Swing Есть две области

замените Thread.sleep (delay); и java.util.Timer с java.swing.Timer, потому что блок EDT

но в других armх есть способ, как преднамеренно блокировать EDT (от splungebob от OTN). ПРИМЕЧАНИЕ: этот пример против всех вершин 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 items = new Vector(); 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)); } } 

Попробуйте установить его на кадре вместо заданного компонента

  • Как вставить изображение в JTable Cell
  • Использование JInternalFrame и некоторой кнопки
  • Java: сохранение формата изображения JPanel
  • Закройте один JFrame, не закрывая другого?
  • Изменение размера с canvasом в jscrollpane в jsplitpane
  • Эффект безопасного рабочего режима для Java-приложения
  • Получение состояния JToggleButton
  • o отобразить изображение
  • JPanel в игре-головоломке не обновляется
  • Нарисуйте строку в JPanel с нажатием кнопки на Java
  • JMenuItem ImageIcon слишком большой
  • Давайте будем гением компьютера.