2010-02-18 16 views
9

Come aggiungere un comportamento di selezione al testo di JLabel?Come aggiungere un comportamento di selezione a JLabel

Ho provato questo

JLabel search = new JLabel("<html><marquee>Search</marquee><html>"); 

ma non il suo lavoro.

+10

Arriverete presto qui chiedono come calmare il utenti che hanno visto quel tendone. Cerca rifugio prima del lancio. –

risposta

3

Vedere http://forums.sun.com/thread.jspa?forumID=57&threadID=605616 per i dettagli su come fare questo :)

(Edit: Io probabilmente usare System.currentTimeMillis() direttamente all'interno del metodo invece di utilizzare un timer paint(), e poi dividere/modulo (%) per portarlo nell'intervallo richiesto per 'x offset' negli esempi). Aumentando la dimensione del numero di divisione, è possibile modificare la velocità ((System.currentTimeMillis()/200)% 50).

(Edit 2: Ho appena aggiornato il codice qui sotto per risolvere un problema con la riverniciatura Ora programmiamo un ridisegno all'interno del metodo di vernice; forse c'è un modo migliore, ma questo funziona :).)

(Edit 3: errr, ho provato con una stringa più lunga e incasinato. Questo era facile da riparare (aumento ravvicinato di larghezza di nuovo per compensare valori negativi, sottrarre dalla larghezza)

package mt; 

import java.awt.Graphics; 

import javax.swing.Icon; 
import javax.swing.JLabel; 

public class MyJLabel extends JLabel { 
    public static final int MARQUEE_SPEED_DIV = 5; 
    public static final int REPAINT_WITHIN_MS = 5; 

    /** 
    * 
    */ 
    private static final long serialVersionUID = -7737312573505856484L; 

    /** 
    * 
    */ 
    public MyJLabel() { 
     super(); 
     // TODO Auto-generated constructor stub 
    } 

    /** 
    * @param image 
    * @param horizontalAlignment 
    */ 
    public MyJLabel(Icon image, int horizontalAlignment) { 
     super(image, horizontalAlignment); 
     // TODO Auto-generated constructor stub 
    } 

    /** 
    * @param image 
    */ 
    public MyJLabel(Icon image) { 
     super(image); 
     // TODO Auto-generated constructor stub 
    } 

    /** 
    * @param text 
    * @param icon 
    * @param horizontalAlignment 
    */ 
    public MyJLabel(String text, Icon icon, int horizontalAlignment) { 
     super(text, icon, horizontalAlignment); 
     // TODO Auto-generated constructor stub 
    } 

    /** 
    * @param text 
    * @param horizontalAlignment 
    */ 
    public MyJLabel(String text, int horizontalAlignment) { 
     super(text, horizontalAlignment); 
     // TODO Auto-generated constructor stub 
    } 

    /** 
    * @param text 
    */ 
    public MyJLabel(String text) { 
     super(text); 
    } 



    /* (non-Javadoc) 
    * @see javax.swing.JComponent#paintComponent(java.awt.Graphics) 
    */ 
    @Override 
    protected void paintComponent(Graphics g) { 
     g.translate((int)((System.currentTimeMillis()/MARQUEE_SPEED_DIV) % (getWidth() * 2)) - getWidth(), 0); 
     super.paintComponent(g); 
     repaint(REPAINT_WITHIN_MS); 
    } 
} 
+1

Hm e cosa faresti con quel numero di millis che calcoli in paint()? Tieni presente che lo swing painting è a thread singolo e, quindi, qualsiasi sospensione nel metodo paint() interromperà il resto dell'interfaccia utente. Mi scuso se ho interpretato male la tua risposta. –

+0

Modificato il post originale per riflettere ciò che è necessario :) –

+1

Per misurare il tempo trascorso (relativo), è necessario utilizzare System.nanoTime(). System.currentTimeMillis() fornisce il tempo assoluto in base all'orologio di sistema. L'orologio di sistema potrebbe cambiare improvvisamente se un'applicazione esterna modifica l'ora del sistema (ad es. Ntp). http: // stackoverflow.it/questions/351565/system-currenttimemillis-vs-system-nanotime – Ajay

1

Come hai trovato, l'HTML su JLabel è limitato alla formattazione e non supporta il tag <marquee>. Dovresti utilizzare qualcosa come SwingWorker o ExecutorService per modificare il testo ogni pochi millisecondi.

+0

un'altra opzione è javax.swing.Timer – Karussell

0

hier è una soluzione pratica sporca. Se necessario, posso precisare il codice in alcuni punti:


package gui; 

import java.awt.Color; 
import java.awt.GridLayout; 

import javax.swing.BorderFactory; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollBar; 
import javax.swing.JScrollPane; 
import javax.swing.ScrollPaneConstants; 

public class ScrollLabel extends JPanel { 
    private static final long serialVersionUID = 3986350733160423373L; 
    private final JLabel  label; 
    private final JScrollPane sPane; 
    private final ScrollMe  scrollMe; 

    public ScrollLabel(String text) { 
     setLayout(new GridLayout(1, 1)); 
     label = new JLabel(text); 
     sPane = new JScrollPane(label); 
     sPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); 
     JScrollBar horizontalScrollBar = new JScrollBar(JScrollBar.HORIZONTAL); 
     sPane.setHorizontalScrollBar(horizontalScrollBar); 
     setBorder(BorderFactory.createLineBorder(Color.RED)); 
     add(sPane.getViewport()); 
     scrollMe = new ScrollMe(this, label, sPane); 
     scrollMe.start(); 
    } 

    class ScrollMe extends Thread { 
     JScrollPane sPane; 
     ScrollLabel parent; 
     JLabel  label; 

     ScrollMe(ScrollLabel parent, JLabel label, JScrollPane sPane) { 
      this.sPane = sPane; 
      this.parent = parent; 
      this.label = label; 
     } 

     boolean isRunning = true; 

     @Override 
     public void run() { 
      int pos = 0; 
      try { 
       while (isRunning) { 
        if (sPane.isVisible()) { 
         int sWidth = parent.getSize().width; 
         int lWidth = label.getWidth(); 

         if (sWidth < lWidth) { 
          if (pos + sWidth > lWidth) 
           pos = 0; 
          sPane.getHorizontalScrollBar().setValue(pos); 
         } 
        } 
        synchronized (this) { 
         wait(50); 
         pos += 1; 
        } 
       } 
      } 
      catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      finally { 
       isRunning = false; 
      } 
     } 
    } 

    public static void main(String[] args) { 
     JFrame jFrame = new JFrame("ScrollLabel"); 
     jFrame.getContentPane().add(new ScrollLabel("how to add marquee behaviour to Jlabel !Java")); 
     jFrame.setVisible(true); 
    } 
} 

2

Questa grande opera (ho scritto questo per me, quindi ci potrebbero essere alcuni errori):

import java.awt.Font; 
import java.awt.FontMetrics; 
import java.awt.Graphics; 

import javax.swing.JLabel; 
import javax.swing.JPanel; 

public class JMarqueeLabel extends JPanel implements Runnable 
{ 
    /** 
    * 
    */ 
    private static final long serialVersionUID = -2973353417536204185L; 
    private int x; 
    private FontMetrics fontMetrics; 
    public static final int MAX_SPEED = 30; 
    public static final int MIN_SPEED = 1; 
    private int speed; 
    public static final int SCROLL_TO_LEFT = 0; 
    public static final int SCROLL_TO_RIGHT = 1; 
    private int scrollDirection = 0; 
    private boolean started = false; 
    private JLabel label; 

    public JMarqueeLabel(String text) 
    { 
     super(); 
     label = new JLabel(text) 
     { 
      /** 
      * 
      */ 
      private static final long serialVersionUID = -870580607070467359L; 

      @Override 
      protected void paintComponent(Graphics g) 
      { 
       g.translate(x, 0); 
       super.paintComponent(g); 
      } 
     }; 
     setLayout(null); 
     add(label); 
     setSpeed(10); 
     setScrollDirection(SCROLL_TO_RIGHT); 
    } 

    @Override 
    protected void paintComponent(Graphics g) 
    { 
     super.paintComponent(g); 
     label.paintComponents(g); 
    } 

    public void setScrollDirection(int scrollDirection) 
    { 
     this.scrollDirection = scrollDirection; 
    } 

    public int getScrollDirection() 
    { 
     return scrollDirection; 
    } 

    public void setSpeed(int speed) 
    { 
     if (speed < MIN_SPEED || speed > MAX_SPEED) 
     { 
      throw new IllegalArgumentException("speed out of range"); 
     } 
     this.speed = speed; 
    } 

    public int getSpeed() 
    { 
     return speed; 
    } 

    @Override 
    public void validateTree() 
    { 
     System.out.println("Validate..."); 
     super.validateTree(); 
     label.setBounds(0, 0, 2000, getHeight()); 
     if (!started) 
     { 
      x = getWidth() + 10; 
      Thread t = new Thread(this); 
      t.setDaemon(true); 
      t.start(); 
      started = true; 
     } 
    } 

    public String getText() 
    { 
     return label.getText(); 
    } 

    public void setText(String text) 
    { 
     label.setText(text); 
    } 

    public void setTextFont(Font font) 
    { 
     label.setFont(font); 
     fontMetrics = label.getFontMetrics(label.getFont()); 
    } 

    @Override 
    public void run() 
    { 
     fontMetrics = label.getFontMetrics(label.getFont()); 
     try 
     { 
      Thread.sleep(100); 
     } catch (Exception e) 
     { 
     } 
     while (true) 
     { 
      if (scrollDirection == SCROLL_TO_LEFT) 
      { 
       x--; 
       if (x < -fontMetrics.stringWidth(label.getText()) - 10) 
       { 
        x = getWidth() + 10; 
       } 
      } 
      if (scrollDirection == SCROLL_TO_RIGHT) 
      { 
       x++; 
       if (x > getWidth() + 10) 
       { 
        x = -fontMetrics.stringWidth(label.getText()) - 10; 
       } 
      } 
      repaint(); 
      try 
      { 
       Thread.sleep(35 - speed); 
      } catch (Exception e) 
      { 
      } 
     } 
    } 

} 

questo funziona per stringhe molto lunghe. Se hai bisogno di stringhe più lunghe, devi cambiare 2000 in un numero più alto.

Spero che questo è ciò che si vuole :-)

Problemi correlati