2013-04-05 62 views
1

我在FlowLayout中添加了多個JLabel的JFrame,但是當我調用JLabels上的重繪時,它們的paintComponent不會被調用。如果我刪除FlowLayout,只添加最後一個JLabel,並正確顯示並重新繪製。我試圖使用面板,但它沒有奏效。我不確定我是否正確使用它。JFrame組件可以通過重繪調用paintComponent,雖然使用flowlayout

import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.FlowLayout; 
import java.awt.Toolkit; 
import javax.swing.JFrame; 

public class RacingLetters { 

    public static void main(String[] args) { 

     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       final JFrame jframe = new JFrame(); 
       jframe.setTitle("Racing letters"); 
       jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       //jframe.setExtendedState(Frame.MAXIMIZED_BOTH); 
       Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize(); 
       int x = (int) ((dimension.getWidth() - jframe.getWidth())/2); 
       int y = (int) ((dimension.getHeight() - jframe.getHeight())/2); 
       jframe.setLocation(x, y); 
       jframe.setMinimumSize(new Dimension(500, 200)); 
       FlowLayout fl = new FlowLayout(); 
       jframe.setLayout(fl); 
       //jframe.setLayout(null); 
       jframe.setVisible(true);  

       StringBuffer[] stringBufferArray = new StringBuffer[20]; 
       char ch = 'A'; 

       int yy = 20; 
       for (int i = 0; i < 5; i++) { 
        stringBufferArray[i] = new StringBuffer(""); 
        BufferThread bt = new BufferThread(stringBufferArray[i], ch, 10, yy); 
        //pane.add(bt); 
        jframe.add(bt); 

        new Thread(bt).start(); 
        ch++; 
        yy += 20; 
       } 

      } 
     }); 

    } 
} 

..

import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.util.Random; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JLabel; 


public class BufferThread extends JLabel implements Runnable { 

    char ch; 
    StringBuffer sb; 
    int x,y; 

    BufferThread(StringBuffer sb, char ch,int x, int y) { 
     this.sb = sb; 
     this.ch = ch; 
     this.x = x; 
     this.y = y; 
    } 

    @Override 
    public void run() { 
     Random rand = new Random(); 

     for (int i = 0; i < 5; i++) { 
      sb.append(ch); 
      System.out.println(x + " " + y + " " + ch); 
      repaint(); 

      try { 
       Thread.sleep(rand.nextInt(500)); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(BufferThread.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    } 

    public void paintComponent(Graphics g) { 
     //System.out.println(x + " " + y + " " + ch); 
     //System.out.println("aaaa"); 
     //stem.out.println(sb); 
     Graphics2D g2 = (Graphics2D) g; 

     Font f = new Font("Serif", Font.PLAIN, 24); 
     //if (sb.toString().indexOf("E") < 0) 
      g2.drawString(sb.toString(), x, y); 

    } 

} 
+1

Swing組件不應該用在Event Dispatch Thread之外,所以你應該以不同的方式做。我建議使用擺動計時器。 – 2013-04-05 19:16:34

+1

順便說一句,它看起來組件的大小保持不變在0x0。出於這個原因,'repaint'發現不必調用'paintComponent'。 – 2013-04-05 19:37:49

+2

請勿重寫JLabel以實現線程或執行自定義繪製。 – camickr 2013-04-05 19:46:24

回答

2

的核心問題是,JLabel不提供任何信息反饋給框架的佈局管理器它想有多大是。它實際上並不是告訴框架的佈局管理器它已更新並需要調整大小。

爲什麼你試圖在標籤上繪製文本超出了我的視野,因爲這是標籤所做的設計。

在處理Swing組件時應避免使用Thread,並應儘可能使用javax.swing.TimerSwingWorker

import java.awt.EventQueue; 
import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Ticker { 

    public static void main(String[] args) { 
     new Ticker(); 
    } 

    public Ticker() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException ex) { 
       } catch (InstantiationException ex) { 
       } catch (IllegalAccessException ex) { 
       } catch (UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new FlowLayout()); 
       frame.add(new TickerLabel()); 
       frame.setSize(100, 100); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 

     }); 
    } 

    public class TickerLabel extends JLabel { 

     private int counter; 

     public TickerLabel() { 
      Timer timer = new Timer(500, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        if (counter > 4) { 
         ((Timer)e.getSource()).stop(); 
        } else { 
         String text = getText(); 
         text += (char)(((int)'A') + counter); 
         setText(text); 
        } 
        counter++; 
       } 
      }); 
      timer.setRepeats(true); 
      timer.setCoalesce(true); 
      timer.start(); 
     } 

    } 

} 
+0

做得很好!我沒有足夠好地檢查他的代碼,以瞭解爲什麼大小不會改變。他希望延遲是隨機的,這樣多個標籤就會競爭。 – 2013-04-05 21:14:13

+0

@Lonenebula我相信OP可以弄清楚如何實現;) – MadProgrammer 2013-04-05 22:26:54

+0

+1強調標籤的核心功能:-) – kleopatra 2013-04-05 22:39:20

相關問題