Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8244338

[macos] JSpinner does not increment/decrement with voiceOver control+option+UpArrow

    XMLWordPrintable

    Details

      Description

      ADDITIONAL SYSTEM INFORMATION :
      MacOS Catalina version 10.15.4
      Java JDK 14
      Apache NetBeans IDE 11.1

      A DESCRIPTION OF THE PROBLEM :
      The instructions are in text labels in the JFrame app which reproduces the bugs.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Attached zip of the netBeans project. There is one JSpinner in a Frame. Does not matter which SpinnerModel is used. Set spinner to request focus. Start up voiceOver. Start up app. Spinner text field receives focus. VoiceOver instructions say to increase value use control+option+UpArrow. That does not work. To give focus to complete spinner, open items window control+option+I and select the Spinner. Follow voiceOver instructions.
      Press shift+control+option+downArrow to control "stepper". Again, control+option+UpArrow says Increasing, but value DOES NOT change.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Would like to see voiceOver announce "Increasing", then the stepper value increase, then announce the current value. When the spinner gets focus, voiceOver should announce the current value. I think that is the behavior that was expected by design; it is just broken.
      ACTUAL -
      The value does not change. There is no announcement of the current value after the increment.

      ---------- BEGIN SOURCE ----------
      /*
       * To change this license header, choose License Headers in Project Properties.
       * To change this template file, choose Tools | Templates
       * and open the template in the editor.
       */

      /**
       *
       * @author Coz
       */
      public class OnlySpinner extends javax.swing.JFrame {

          /**
           * Creates new form OnlySpinner
           */
          public OnlySpinner() {
              initComponents();
          }

          /**
           * This method is called from within the constructor to initialize the form.
           * WARNING: Do NOT modify this code. The content of this method is always
           * regenerated by the Form Editor.
           */
          @SuppressWarnings("unchecked")
          // <editor-fold defaultstate="collapsed" desc="Generated Code">
          private void initComponents() {

              jSpinner1 = new javax.swing.JSpinner();
              jLabel3 = new javax.swing.JLabel();
              jLabel4 = new javax.swing.JLabel();
              jLabel1 = new javax.swing.JLabel();
              jLabel2 = new javax.swing.JLabel();
              jLabel5 = new javax.swing.JLabel();
              jLabel6 = new javax.swing.JLabel();

              setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
              setTitle("PlainJFrame");
              setFocusTraversalPolicyProvider(true);

              jSpinner1.setFont(new java.awt.Font("Lucida Grande", 0, 36)); // NOI18N
              jSpinner1.setToolTipText("The only spinner");
              jSpinner1.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
              jSpinner1.setName("theSpinner"); // NOI18N

              jLabel3.setText("Default focus goes to \"stepper\" text field and instructs to use cntrl+opt+UpArrow.");

              jLabel4.setText("cntrl+opt+upArrow says INCREMENTING; does not increase value.");

              jLabel1.setLabelFor(jSpinner1);
              jLabel1.setText("cntrl+optn+I; pick TheSpinner; value is not announced; follow voiceOver instructions:");
              jLabel1.setToolTipText("Follow instructions");

              jLabel2.setText("cntrl+opt+UpArrow incrementing does not change value; value is not announced.");

              jLabel5.setText("Enable voiceOver command+F5; Start up this application.");

              jLabel6.setText("cntrl+opt+shift+DownArrow to control stepper.");

              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()
                      .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                          .addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
                          .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 518, javax.swing.GroupLayout.PREFERRED_SIZE)
                          .addComponent(jLabel5, javax.swing.GroupLayout.PREFERRED_SIZE, 503, javax.swing.GroupLayout.PREFERRED_SIZE)
                          .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 437, javax.swing.GroupLayout.PREFERRED_SIZE)
                          .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 530, javax.swing.GroupLayout.PREFERRED_SIZE)
                          .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                              .addComponent(jLabel4, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 518, Short.MAX_VALUE)
                              .addComponent(jLabel6, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                      .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
              );
              layout.setVerticalGroup(
                  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                  .addGroup(layout.createSequentialGroup()
                      .addContainerGap()
                      .addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
                      .addGap(18, 18, 18)
                      .addComponent(jLabel5)
                      .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                      .addComponent(jLabel3)
                      .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                      .addComponent(jLabel4)
                      .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                      .addComponent(jLabel1)
                      .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                      .addComponent(jLabel6)
                      .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                      .addComponent(jLabel2)
                      .addGap(16, 16, 16))
              );

              jSpinner1.getAccessibleContext().setAccessibleName("TheSpinner");
              jLabel1.getAccessibleContext().setAccessibleName("cntrl+optn+i; pick TheSpinner; follow voiceOver instructions");
              jLabel2.getAccessibleContext().setAccessibleDescription("bug");

              getAccessibleContext().setAccessibleDescription("Demonstration of accessible bug");

              pack();
          }// </editor-fold>

          /**
           * @param args the command line arguments
           */
          public static void main(String args[]) {
              /* Set the Nimbus look and feel */
              //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
              /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
               * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
               */
              try {
                  for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                      if ("Nimbus".equals(info.getName())) {
                          javax.swing.UIManager.setLookAndFeel(info.getClassName());
                          break;
                      }
                  }
              } catch (ClassNotFoundException ex) {
                  java.util.logging.Logger.getLogger(OnlySpinner.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
              } catch (InstantiationException ex) {
                  java.util.logging.Logger.getLogger(OnlySpinner.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
              } catch (IllegalAccessException ex) {
                  java.util.logging.Logger.getLogger(OnlySpinner.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
              } catch (javax.swing.UnsupportedLookAndFeelException ex) {
                  java.util.logging.Logger.getLogger(OnlySpinner.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
              }
              //</editor-fold>

              /* Create and display the form */
              java.awt.EventQueue.invokeLater(new Runnable() {
                  public void run() {
                      new OnlySpinner().setVisible(true);
                  }
              });
          }

          // Variables declaration - do not modify
          private javax.swing.JLabel jLabel1;
          private javax.swing.JLabel jLabel2;
          private javax.swing.JLabel jLabel3;
          private javax.swing.JLabel jLabel4;
          private javax.swing.JLabel jLabel5;
          private javax.swing.JLabel jLabel6;
          private javax.swing.JSpinner jSpinner1;
          // End of variables declaration
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      I think that i will extend JSpinner and SpinnerModel and possibly make my own editor. For my purposes, I do not need to edit the text field, so probably will disable editor. I have already implemented a custom SpinnerModel override of getNext and getPrevious, but problem was not solved.

      FREQUENCY : always


        Attachments

          Issue Links

            Activity

              People

              Assignee:
              kizune Alexander Zuev
              Reporter:
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: