2014-01-09 22 views
5

Siehe auch Java Swing GUI hour glass. Die angegebene Antwort scheint jedoch nicht zu funktionieren.Swing: Ändern Sie den Cursor, um den Cursor zu warten

Ich habe folgenden Code:

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

Diese wird aufgerufen, wenn der Benutzer nach dem Eintritt in bar Menü auswählt. Der Cursor ändert sich jedoch nie. Beachten Sie, dass das Laden der Datei eine Datei erfordert und daher eine Änderung des Cursors sichtbar sein sollte.

Was mache ich falsch?

EDIT:

this ist die oberste Ebene JFrame.

EDIT 2: moved solution to separate answer

+0

Für eine bessere Hilfe früher posten, ein [SSCCE] (http://sscce.org /). Beachten Sie, dass das Dokument überprüft und auf [diese Frage] diskutiert wird (http://meta.stackexchange.com/q/214955/155831), willkommene Beiträge. –

+0

Was passiert in // Sachen? Der Code, der dort implementiert wird, sollte in einem getrennten Thread sein. Andernfalls werden in Ihrer Anwendung keine Änderungen am Cursor angezeigt. – oopbase

+2

Blockieren Sie nicht den EDT (Event Dispatch Thread) - die GUI wird "eingefroren", wenn das passiert. Anstatt 'Thread.sleep (n)' aufzurufen, implementieren Sie einen Swing 'Timer' für wiederkehrende Aufgaben oder einen' SwingWorker' für lang andauernde Aufgaben. Weitere Informationen finden Sie unter [Parallelität in Swing] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/). –

Antwort

5

zuerst eine Klasse Swingworker machen:

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

} 

Dann es so nennen:

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

EDIT von @mKorbel gemacht, entschuldigen Sie mich bitte für diese hi_jack

  • Ich kann meine Beiträge nicht finden wit h dieser Code hier (etwas happends mit underlaing Datenbank),

  • Verwendung dieser Logik,

  • Rest ist in meinem Kommentar hier

virtuelle -1k falsch, falsch, falsch, Ihr doInBackground() fehlt publish() - process(), done() is extremly wrong designed, lesen Sie Kommentare in der Antwort von @trashgod, wenn es möglich ist zu verwenden Runnable # Thread für FileIO, Socket oder andere XxxStreams anstelle von schwarz Loch basierend auf Zukunft und Swingworker

  • bitte diesen Code in Ihrem Thread zu löschen, wie pro bearbeiten

.

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

virtuell -1k falsch, falsch, falsch, doInBackground() fehlt publish() - process(), [done() ist extrem falsch gestaltet] (http://stackoverflow.com/questions/7053865/cant- get-arrayIndexoutofboundexception-from-future-and-swingworker-if-threa), lesen Kommentare in Antwort von @trashgod, wenn Runnable # Thread für FileIO, Socket oder beliebige XxxStreams anstelle von Black Hole basierend auf Future und SwingWorker – mKorbel

+0

möglich ist Ich brauche keine Veröffentlichungs- und Prozessmethoden und das ist jetzt erledigt. Runnable hat ein Problem, da Sie keine Ausnahmen an Benutzer melden können ... es wird nur fehlschlagen und die Ausnahme wird unbemerkt bleiben: Ich denke, das ist ziemlich dumm, besonders mit FileIO. –

+0

Dies ist nicht wahr, Runnable hat kein Problem, noch in Ihrem Kommentar beschrieben, diese Beschreibung im Gespräch darüber, warum nicht SwingWorker (hat lange und große Buggy-Geschichte, und oft wiederholen), noch für den Produktionscode, sicher alles ist an dir, Runnable ist die beste Wahl für FileIO, XxxStream, Socket, JDBC – mKorbel

2

Laden der Datei hält bereits das EDT beschäftigt, so dass es nicht die Chance bekommen, um den Cursor zu ändern.

3
  • häufiges Problem für EventDispatchThread ist, dass alle Ereignisse in einem Augenblick fertig sind, dann werden in einem Moment jedem Code, Methoden, Klassen neu gestrichen, nach/wenn alle Code in Action

    ausgeführt wird Dich
  • dann haben Split diese Logik auf die zwei separate Ereignisse, die (am besten Optionen) zwei Swing-Aktionen eingewickelt verwenden,

    1. eine für mit Cursor Makeln - verwalten kann nur Cursor von Property aufgerufen werden oder von Button von JM enuItem

    2. andere Swing-Aktion oder eine SwingListener nennen Rest/oder erwarteten Code

    3. Sie können diese zwei Swing-Aktionen (meine Uhr) zu verketten, 1. 1 Sekunde

zu nennen
+0

@Andrew Thompson nicht notwendig Ich habe diesen Thread in meinem Radar :-), – mKorbel

+0

Viel cool. Hoffentlich sehen wir bald eine neue, verbesserte Version. :) –

+1

@Andrew Thompson Entschuldigung für meinen vorherigen ziemlich leeren Kommentar, wichtig für mich ist, dass diese Option als Standard hier existiert, nichts anderes, ich ignoriere jeden blablblba, jedes Wort für/gegen oder was auch immer .... – mKorbel

5

Der Grund, warum Sie die Änderungen nicht sehen, ist wahrscheinlich, dass Sie die ganze Arbeit an der EDT tun. Tu das nie. Selbst wenn Sie // do stuff in einem separaten Thread verwenden, wird der finally Block ausgeführt, bevor die UI die Möglichkeit hatte, sich neu zu streichen.

Stattdessen sollten Sie einen SwingWorker spawn, der den Wartecursor einstellt, dann die schwere Arbeit (Dateiladen) im Hintergrund ausführt und schließlich auf den normalen Cursor zurücksetzt, wenn Sie fertig sind.

Dies könnte zeigen, dass der Warte-Cursor nicht wirklich benötigt wurde, und dass die Verwendung eines Fortschrittsbalkens in diesem Fall besser geeignet wäre.

+0

Siehe Bearbeiten in meiner Frage für meine Lösung –

2

Wow - was ist mit dem ganzen Code. Es ist einfach:

final JScrollPane jsp = new JScrollPane(jt); 

jsp.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 

       //DO SOMETHING 
jsp.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
0

Sie sollten niemals einen langen Prozess auf dem Swing-Event Dispatch Thread (EDT) laufen, oft wie Sie wollen einen Wartecursor in dem Rahmen zeigen, während einige schnelle Laden von Daten (zB beim Panel Schalt) .

Um dies zu erreichen ich den Cursor Änderung an der Wurzel Bereich des JFrame

Beispiel befestigen

public class TestFrame extends JFrame { 

    private static final long serialVersionUID = 5671798241966272024L; 

    /** 
    * In this example static to show how they can be 
    * centralized in application with multiple frames 
    */ 
    public static void setWaitCursor(JFrame frame) { 
     if (frame != null) { 
      RootPaneContainer root = (RootPaneContainer) frame.getRootPane().getTopLevelAncestor(); 
      root.getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 
      root.getGlassPane().setVisible(true); 
     } 
    } 

    public static void setDefaultCursor(JFrame frame) { 
     if (frame != null) { 
      RootPaneContainer root = (RootPaneContainer) frame.getRootPane().getTopLevelAncestor(); 
      root.getGlassPane().setCursor(Cursor.getDefaultCursor()); 
     } 
    } 

    public TestFrame() { 
     super("Test"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     init(); 
    } 

    private void init() { 
     getContentPane().setLayout(new BorderLayout()); 
     JButton btnTest = new JButton("Load some quick stuff"); 
     btnTest.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       TestFrame.setWaitCursor(TestFrame.this); 
       doSomeShortProccessing(); 
       TestFrame.setDefaultCursor(TestFrame.this); 
      } 
     }); 
     getContentPane().add(btnTest); 
     pack(); 
    } 

    protected void doSomeShortProccessing() { 
     try { 
      //You should never do Thread.sleep on the EDT is just to display function 
      //Normaly process would be create a new panel and load some quick data 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     TestFrame frame = new TestFrame(); 
     frame.setLocationRelativeTo(null); //Middle of screen 
     frame.setVisible(true); 
    } 
} 
Verwandte Themen