2013-11-29 38 views
0

我使用Eclipse IDE在運行OSX 10.7.5的Mac上開發。這個程序構造了一個JPanel數組,當用戶點擊一個面板時,同一行或列上的所有其他面板都會改變顏色,藍色表示鼠標左鍵,紅色表示右鍵。當我從IDE運行時,一切正常,至少我從來沒有見過它失敗。但是,當我創建一個.jar文件並通過雙擊運行時,大多數情況下它可以正常工作,但每隔一段時間它都不會更改其他某些面板的顏色。GUI更新在IDE中工作,但並不總是從jar文件中運行

要測試我選擇一個正方形,並交替地右鍵單擊並左鍵單擊它。正如我所說的大多數時候它工作的那樣,同一行或同一列中的所有其他面板都會改變顏色。但是,如果我右鍵點擊一個正方形,並且一些面板保持藍色,那就是失敗。如果我再次右擊同一方塊,它不會改變顯示;失敗的面板保持藍色。這就像經理認爲一切都是正確的顏色,並且不用更新顯示器。

如果我調整面板大小或用任一按鈕單擊任何其他方塊,所有面板都會翻轉到正確的顏色。此代碼沒有顯式調用repaint(),但我試過,並沒有解決問題。我試過閱讀重繪管理器,但還沒有找到讓顯示器可靠更新的方法。正如我所說,運行IDE時我從來沒有見過這種情況,並且大多數情況下它也可以作爲應用程序運行。剛纔,大約需要50次點擊才能失敗。

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

public class GUITest extends JPanel { 

    final static int NROWS = 81; 
    final static int TOTAL_SQ = NROWS * NROWS; 
    Square[] square = new Square[TOTAL_SQ]; 

    public GUITest() { 
     setLayout(new GridLayout(NROWS, NROWS)); 
     for (int i = 0; i < TOTAL_SQ; i++) { 
      square[i] = new Square(i); 
      add(square[i]); 
     } 

    } 

    public void squareClicked(int id, int button) { 
     // determine which row and column 
     int row = id/NROWS; 
     int col = id % NROWS; 
     // change background color of all squares on same row or column 
     for (int i = 0; i < TOTAL_SQ; i++) { 
      if ((row == i/NROWS) || (col == i % NROWS)) 
       if (button == MouseEvent.BUTTON3) 
        square[i].setBackground(Color.RED); 
       else 
        square[i].setBackground(Color.BLUE); 
     } 
    } // squareClicked 

    class Square extends JPanel implements MouseListener { 
     int id = 0; // which square this is 

     public Square(int id) { 
      this.id = id; 
      setBorder(BorderFactory.createLineBorder(Color.black)); 
      addMouseListener(this); 
     } // Square constructor 

     public void mouseClicked(MouseEvent e) { 
     } 

     public void mouseEntered(MouseEvent e) { 
     } 

     public void mouseExited(MouseEvent e) { 
     } 

     public void mousePressed(MouseEvent e) { 
     } 

     public void mouseReleased(MouseEvent e) { 
      squareClicked(id, e.getButton()); 
     } 
    } // Square 

    public static void main(String[] args) { 
     JFrame frame = new JFrame("GUI Test"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     GUITest app = new GUITest(); 
     frame.setSize(800, 600); 
     frame.setLocationRelativeTo(null); 
     frame.getContentPane().add(app, BorderLayout.CENTER); 
     frame.setVisible(true); 
    } 
} 

我有第二個問題可能是相關的。 IDE顯示比應用程序快得多。 IDE在閃存中更新。應用程序逐個更新每個面板,但速度明顯較慢。我猜IDE是使用雙緩衝顯示器。我也閱讀了這些內容,但沒有看到如何在整個顯示屏準備就緒前暫停更新。

在此先感謝。

+0

1)文字牆報警!使用段落。 2)*「我有第二個問題可能是相關的。」*整個文字不包含'?'所以......你的第一個問題是什麼? –

回答

1

我沒有看到你的邏輯的任何問題,當我從Windows上使用JDK7 7

但是在命令行中運行代碼,我不能重複你的問題,當我運行代碼,我做得到一個異常,當幀載荷:

C:\Java>java GUITest 
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Comparison method violates its general contract! 
     at java.util.TimSort.mergeLo(Unknown Source) 
     at java.util.TimSort.mergeAt(Unknown Source) 
     at java.util.TimSort.mergeCollapse(Unknown Source) 
     at java.util.TimSort.sort(Unknown Source) 
     at java.util.TimSort.sort(Unknown Source) 
     at java.util.Arrays.sort(Unknown Source) 
     at java.util.Collections.sort(Unknown Source) 
     at javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(Unknown Source) 
     at javax.swing.SortingFocusTraversalPolicy.getFocusTraversalCycle(Unknown Source) 
     at javax.swing.SortingFocusTraversalPolicy.getFirstComponent(Unknown Source) 
     at javax.swing.LayoutFocusTraversalPolicy.getFirstComponent(Unknown Source) 
     at javax.swing.SortingFocusTraversalPolicy.getDefaultComponent(Unknown Source) 

我想是爲了確保所有的代碼是在美國東部時間執行的第一件事:

EventQueue.invokeLater(new Runnable() 
{ 
    public void run() 
    { 
     JFrame frame = new JFrame("GUI Test"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     GUITest app = new GUITest(); 
     frame.getContentPane().add(app, BorderLayout.CENTER); 
     frame.setSize(800,600); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 
}); 

我仍然有例外。於是,我又試圖更改代碼,以減少被顯示在一個面板上的組件數量:

setLayout(new GridLayout(NROWS,1)); 
int squares = 0; 

for (int i = 0; i < NROWS; i++) 
{ 
    JPanel panel = new JPanel(new GridLayout(1, NROWS)); 

    for (int j = 0; j < NROWS; j++) 
    { 
     square[squares] = new Square(squares); 
     panel.add(square[squares]); 
     squares++; 
    } 

    add(panel); 
} 

我不再得到的異常。不知道這是否有用。

此外,Swing默認是雙緩衝,所以我不確定爲什麼每個組件都單獨更新。 Swing應該爲個別組件重新組合重繪請求,以便它們一次完成,但可能只有一組組件正在重新繪製。

解決此問題的唯一方法是不使用組件,而是創建您自己的組件,以自定義繪製每個矩形。當然,這會涉及更多,因爲您還需要執行自己的「點擊檢測」來確定哪個矩形被點擊。

+0

感謝您的回覆。我以前沒有得到例外。我決定打開一個終端窗口並從那裏跑去看看我是否得到它。我沒有這樣,這仍然是一個問題。但我也沒有得到失敗,至少不是那麼遠,並且顯示更新很快。我想也許這是JVM中的一個設置,因爲我唯一一次看到它是在Mac查找器中雙擊jar文件的時候。雙擊文件vs從終端窗口運行有什麼不同?我不知道。 – user3047784

相關問題