2012-01-12 4 views
5

W mojej aplikacji znajduje się JTable ze zmiennymi kolumnami nagłówka. Zwykle po przesunięciu kursora nad nagłówek tabeli w celu zmiany rozmiaru ikona kursora zmienia się, aby zmienić wielkość strzałki, na przykład < ->.Ikona kursora nie zmienia się po wyzwoleniu metody setCursor

Jednak w poniższym scenariuszu sytuacja wygląda inaczej.

Występuje akcja przycisku w tym samym Frame, a podczas wykonywanej akcji ustawiam kursor na ikonę zajętości i zmieniam ją z powrotem na domyślny kursor po zakończeniu akcji, używając metody Container.setCurosr(Cursor cursor).

Czasami po przesunięciu kursora nad nagłówkiem tabeli zmiany rozmiaru, po naciśnięciu przycisku ikona kursora nie zmienia się, aby zmienić wielkość strzałki, kursor nie zmienia się wcale.

Czy można to uznać za błąd w Java Swing lub czy istnieje rozwiązanie tego problemu?

Aktualizacja: Przykładowy kod dołączony

import java.util.*; 
import java.awt.*; 
import javax.swing.*; 
import java.awt.event.*; 

public class ColumnResizeIconTest extends JFrame { 

JScrollPane scrollPane; 
JTable table; 
JButton button; 

public ColumnResizeIconTest() { 
    setLayout(new BorderLayout()); 
    addComponents(); 
    setSize(300,300); 
} 

private void addComponents() { 
    addButton(); 
    addTable(); 
} 

private void addButton() { 
    button = new JButton("Click Me"); 
    button.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent ae) { 
      setWaitCursor(); 
      for(int i=0; i<2000; i++) { 
       System.out.print(i); 
      } 
      setDefaultCursor(); 
     } 
    }); 
    add(button, BorderLayout.NORTH); 
} 

private void addTable() { 
    scrollPane = new JScrollPane(createTable()); 
    add(scrollPane, BorderLayout.CENTER); 
} 

private JTable createTable() { 
    Object[][] cellData = { { "1-1", "1-2","1-3" }, { "2-1", "2-2", "2-3" }, { "3-1", "3-2", "3-3" } }; 
    String[] columnNames = { "column1", "column2", "column3" }; 
    table = new JTable(cellData, columnNames); 
    return table; 
} 

private void setWaitCursor() { 
    Container container = getContentPane(); 
    setWaitCursor(container); 
} 

private void setWaitCursor(Container container) { 
    for(int iCount = 0; iCount < container.getComponentCount(); iCount++) { 
     Component child = (Component) container.getComponent(iCount); 
     if(child instanceof Container) { 
      setWaitCursor((Container) child); 
     } else { 
      child.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 
     } 
    } 
    container.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 
} 

private void setDefaultCursor() { 
    Container container = getContentPane(); 
    setDefaultCursor(container); 
} 

private void setDefaultCursor(Container container) { 
    for(int iCount = 0; iCount < container.getComponentCount(); iCount++) { 
     Component child = (Component) container.getComponent(iCount); 
     if(child instanceof Container) { 
      setDefaultCursor((Container) child); 
     } else { 
      child.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 
     } 
    } 
    container.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 
} 

public static void main(String[] argv) throws Exception { 
    ColumnResizeIconTest test = new ColumnResizeIconTest(); 
    test.setVisible(true); 
} 
} 

Kliknij na przycisk kilka razy i próbować zmienić rozmiar kolumny tabeli. Kursor utknął z domyślnym kursorem.

+0

jaka wersja java na jakiej platformie? –

+2

1) Aby uzyskać lepszą pomoc wcześniej, opublikuj [SSCCE] (http://sscce.org/). 2) * "Czy można to uznać za błąd ..." * Prawdopodobnie. * ".. w Java Swing .." * Prawdopodobnie nie. * ".. lub czy istnieje rozwiązanie tego problemu?" * Napraw swój kod (prawdopodobnie). –

+1

@Andrew Thompson jakże prawdopodobnie dzisiaj, uzgodniony z 4 prawdopodobnie z twojego 3. – mKorbel

Odpowiedz

8

Jak już wspomniano w moim komentarzu: nie jest całkowicie trywialne, aby ponownie et the cursors, nawet dla pojedynczego komponentu :-) Podstawowym problemem (w rekurencyjnym ustawieniu kursora do oczekiwania) jest założenie, że wszystkie komponenty mają domyślny kursor.

Jak widać w nagłówku tabeli, to założenie nie jest poprawne: w przypadku tego składnika "domyślny" jest domyślnym kursorem lub kursorem zmiany rozmiaru, w zależności od lokalizacji myszy. Ponadto wewnętrzne przełączanie kursorów nie jest zbyt inteligentne: nie sprawdza stanu (z góry mojej głowy, zostałem przez to uderzony jakiś czas temu :-)

Nie do końca pewny, do czego chcesz dotrzeć, więc nie ma konkretnego rozwiązania, z wyjątkiem całkowitego zniesienia rekursywnego ustawienia, jest to zbyt trudne, aby uzyskać właściwe rozwiązanie. Opcje mogą być

  • dokonać glassPane (od rootpane ramy za) widoczny i ustaw waitCursor na to
  • użycie JLayer (jdk7) lub JXLayer (JDK6) na mniejszej powierzchni i ustawić waitCursor tego
  • użyj mniej inwazyjnej wizualizacji, fiJProgressBar lub JXBusyLabel (in the SwingX project) gdzieś

Uzupełnienie (dla @mKorbel :-)

Problemem jest łatwo powtarzalna, z niewielkimi zmianami do SSCCE OPS (dzięki za to): zmiana metodę addButton, jak poniżej, a następnie kliknij przycisk i gdy wyświetlany jest kursor oczekiwania, przenieś mysz do nagłówka, a następnie do innej kolumny (wzdłuż krawędzi kolumny). Wykonanie tego kilka razy doprowadzi do nieprzewidywalnych kursorów na nagłówku ...

private void addButton() { 
    button = new JButton("Click Me"); 
    final ActionListener off = new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      setDefaultCursor(); 
      button.setEnabled(true); 
     } 

    }; 
    button.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent ae) { 
      setWaitCursor(); 
      button.setEnabled(false); 
      Timer timer = new Timer(2000, off); 
      timer.setRepeats(false); 
      timer.start(); 
     } 
    }); 

    add(button, BorderLayout.NORTH); 
} 
+0

do ..., byłem pewien, że 13 z FRI jest jutro, jeśli dobrze pamiętam, to jest problem z relacją EDT, czytałem pytanie z similair (nie wiem gdzie), o tym, że ten proces musi zostać podzielony na dwie oddzielne akcje, w przeciwnym razie nie jest to gwarancja kolejności zdarzeń dla obiektów pochodzących z Natywnego systemu operacyjnego, może tak samo jak z Focusem – mKorbel

+0

zapomniałem o +1 – mKorbel

+0

naruszenia @mKorbel EDT często są naturalny winowajca - nie tym razem jest to jednak tylko niekompletna logika :-) – kleopatra

1

1) ma przekierowanie kod

for(int i=0; i<2000; i++) { 
    System.out.print(i); 
} 

do tła Zadanie można realizuje javax.swing.Timer, SwingWorke R lub zawijania te linie kodu wewnątrz Runnable#Thread Przykład here

2) należy przywrócić Cursor na Error/Exception też, to jest prawdopodobnie powód, dlaczego Cursor nie został zmieniony

+0

Obawiam się, że zrozumiałeś mój problem poprawnie. Zanim kliknę przycisk, jeśli ustawię kursor nad odstępem między nagłówkami kolumn tabeli, kursor zmieni się na <->. Kiedy kliknę przycisk, wykonując wewnętrzną akcję, zmieni ona kursor na godzinę i rozpocznie akcję. po zakończeniu akcji kursor zostanie zmieniony na domyślny kursor i pozostawi czynność wykonaną. Następnie, jeśli umieściłem kursor na luce kolumny nagłówka tabeli, ikona jest domyślną ikoną, a nie <->. Dzieje się tak, gdy kilka razy kliknę przycisk. Ale nadal mogę zmienić rozmiar kolumny. – AnupD

+0

Nie jestem w stanie wygenerować twojego problemu, ani jeśli wielokrotnie wciskam JButton, przekierowałem Cursor do JFrame, JButton, JTable i mogę generować ten problem za pomocą Cursora, tylko wtedy, gdy jest generowany wyjątek, a kursor nie jest zmieniony w bloku finally, to tam Cursor.WAIT_CURSOR, hmm zostań na zawsze – mKorbel

+0

hmm .. Dostałem część wyjątku, ale nie w tym przypadku. Chciałbym móc udostępnić Ci film lub zrzut ekranu z tego problemu. – AnupD