Эффект Marquee в Java Swing

Как реализовать эффект Marquee в Java Swing

Вот пример использования javax.swing.Timer .

Marquee.png

 import java.awt.EventQueue; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.Timer; /** @see http://stackoverflow.com/questions/3617326 */ public class MarqueeTest { private void display() { JFrame f = new JFrame("MarqueeTest"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); String s = "Tomorrow, and tomorrow, and tomorrow, " + "creeps in this petty pace from day to day, " + "to the last syllable of recorded time; ... " + "It is a tale told by an idiot, full of " + "sound and fury signifying nothing."; MarqueePanel mp = new MarqueePanel(s, 32); f.add(mp); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); mp.start(); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { new MarqueeTest().display(); } }); } } /** Side-scroll n characters of s. */ class MarqueePanel extends JPanel implements ActionListener { private static final int RATE = 12; private final Timer timer = new Timer(1000 / RATE, this); private final JLabel label = new JLabel(); private final String s; private final int n; private int index; public MarqueePanel(String s, int n) { if (s == null || n < 1) { throw new IllegalArgumentException("Null string or n < 1"); } StringBuilder sb = new StringBuilder(n); for (int i = 0; i < n; i++) { sb.append(' '); } this.s = sb + s + sb; this.n = n; label.setFont(new Font("Serif", Font.ITALIC, 36)); label.setText(sb.toString()); this.add(label); } public void start() { timer.start(); } public void stop() { timer.stop(); } @Override public void actionPerformed(ActionEvent e) { index++; if (index > s.length() - n) { index = 0; } label.setText(s.substring(index, index + n)); } } 

Я знаю, что это поздний ответ, но я только что увидел еще один вопрос о закрытой шатерке, потому что это считалось дубликатом этого ответа.

Поэтому я подумал, что добавлю свое предложение, которое отличается от других предложенных здесь рекомендаций.

MarqueePanel прокручивает компоненты на панели, а не только текст. Таким образом, это позволяет вам в полной мере использовать любой компонент Swing. Простую область выделения можно использовать, добавив JLabel с текстом. Вы можете добавить JLabel с HTML, чтобы вы могли использовать разные шрифты и цвет для текста. Вы даже можете добавить второй компонент с изображением.

Программа java swing для выделения текста

Я просто зашел в Google и нашел эту ссылку . Я запустил код и, похоже, сделал то, что вы хотите.

Основной ответ заключается в том, что вы рисуете текст / графику в bitmap, а затем реализуете компонент, который рисует смещение битмапа на какую-то сумму. Обычно шатры / тикеры прокручиваются влево, так что смещение увеличивается, что означает, что bitmap окрашено в -offset. Ваш компонент запускает таймер, который срабатывает периодически, увеличивая смещение и аннулируя его, чтобы он перекраивался.

Такие вещи, как упаковка, немного сложнее иметь дело, но довольно просто. Если смещение превышает ширину растрового изображения, вы возвращаете его обратно на 0. Если ширина смещения + ширина компонента> ширина растрового изображения вы рисуете остаток компонента, начиная с начала растрового изображения.

Ключом к приличному тикеру является сделать прокрутку гладкой и максимально мерцающей. Поэтому может потребоваться рассмотреть двойную буферизацию результата, сначала покрасив прокручивающийся бит в bitmap, а затем визуализируя это за один раз, вместо того, чтобы рисовать прямо на экране.

Вот код, который я собрал вместе, чтобы вы начали. Я обычно беру код ActionListener и помещаю его в какой-то class MarqueeController чтобы сохранить эту логику отдельно от панели, но это другой вопрос об организации архитектуры MVC, и в достаточно простом classе это может быть не так важно ,

Существуют также различные библиотеки анимации, которые помогут вам сделать это, но мне обычно не нравится включать библиотеки в проекты только для решения одной такой проблемы.

 Открытый class MarqueePanel расширяет JPanel {
   частный JLabel textLabel;
   private int panelLocation;
   частный ActionListener taskPerformer;
   private boolean isRunning = false;

   public static final int FRAMES_PER_SECOND = 24;
   public static final int MOVEMENT_PER_FRAME = 5;

   / **
    * Конструктор classов создает панель выделения.
    * /

   public MarqueePanel () {
     this.setLayout (нуль);
     this.textLabel = новый JLabel («Прокрутка текста здесь»);
     this.panelLocation = 0;
     this.taskPerformer = new ActionListener () {
       public void actionPerformed (ActionEvent evt) {
         MarqueePanel.this.tickAnimation ();
       }
     }
   }

   / **
    * Запускает анимацию.
    * /

   public void start () {
     this.isRunning = true;
     this.tickAnimation ();
   }

   / **
    * Остановка анимации.
    * /

   public void stop () {
     this.isRunning = false;
   }

   / **
    * Перемещает метку на один кадр влево.  Если он вышел из диапазона отображения, верните его назад
    * вправо, вне диапазона отображения.
    * /

   private void tickAnimation () {
     this.panelLocation - = MarqueePanel.MOVEMENT_PER_FRAME;
     if (this.panelLocation 

Добавьте JLabel в рамку или панель.

 ScrollText s= new ScrollText("ello Everyone."); jLabel3.add(s); public class ScrollText extends JComponent { private BufferedImage image; private Dimension imageSize; private volatile int currOffset; private Thread internalThread; private volatile boolean noStopRequested; public ScrollText(String text) { currOffset = 0; buildImage(text); setMinimumSize(imageSize); setPreferredSize(imageSize); setMaximumSize(imageSize); setSize(imageSize); noStopRequested = true; Runnable r = new Runnable() { public void run() { try { runWork(); } catch (Exception x) { x.printStackTrace(); } } }; internalThread = new Thread(r, "ScrollText"); internalThread.start(); } private void buildImage(String text) { RenderingHints renderHints = new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); renderHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); BufferedImage scratchImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); Graphics2D scratchG2 = scratchImage.createGraphics(); scratchG2.setRenderingHints(renderHints); Font font = new Font("Serif", Font.BOLD | Font.ITALIC, 24); FontRenderContext frc = scratchG2.getFontRenderContext(); TextLayout tl = new TextLayout(text, font, frc); Rectangle2D textBounds = tl.getBounds(); int textWidth = (int) Math.ceil(textBounds.getWidth()); int textHeight = (int) Math.ceil(textBounds.getHeight()); int horizontalPad = 600; int verticalPad = 10; imageSize = new Dimension(textWidth + horizontalPad, textHeight + verticalPad); image = new BufferedImage(imageSize.width, imageSize.height, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = image.createGraphics(); g2.setRenderingHints(renderHints); int baselineOffset = (verticalPad / 2) - ((int) textBounds.getY()); g2.setColor(Color.BLACK); g2.fillRect(0, 0, imageSize.width, imageSize.height); g2.setColor(Color.GREEN); tl.draw(g2, 0, baselineOffset); // Free-up resources right away, but keep "image" for // animation. scratchG2.dispose(); scratchImage.flush(); g2.dispose(); } public void paint(Graphics g) { // Make sure to clip the edges, regardless of curr size g.setClip(0, 0, imageSize.width, imageSize.height); int localOffset = currOffset; // in case it changes g.drawImage(image, -localOffset, 0, this); g.drawImage(image, imageSize.width - localOffset, 0, this); // draw outline g.setColor(Color.black); g.drawRect(0, 0, imageSize.width - 1, imageSize.height - 1); } private void runWork() { while (noStopRequested) { try { Thread.sleep(10); // 10 frames per second // adjust the scroll position currOffset = (currOffset + 1) % imageSize.width; // signal the event thread to call paint() repaint(); } catch (InterruptedException x) { Thread.currentThread().interrupt(); } } } public void stopRequest() { noStopRequested = false; internalThread.interrupt(); } public boolean isAlive() { return internalThread.isAlive(); } } 

Предполагается, что это будет улучшение @mamickr MarqueePanel. См. Выше.

Чтобы сопоставить события мыши с конкретными компонентами, добавленными в MarqueePanel

Override add(Component comp) из MarqueePanel, чтобы направить все события мыши на компоненты

Проблема здесь в том, что делать с MouseEvents, выпущенным из отдельных компонентов. Мой подход заключается в том, чтобы удалить слушателей мыши из добавленных компонентов и позволить MarqueePanel перенаправить событие на правильный компонент.

В моем случае эти компоненты должны быть ссылками.

  @Override public Component add(Component comp) { comp = super.add(comp); if(comp instanceof MouseListener) comp.removeMouseListener((MouseListener)comp); comp.addMouseListener(this); return comp; } 

Затем отобразите компонент x в MarqueePanel x и, наконец, правильный компонент

 @Override public void mouseClicked(MouseEvent e) { Component source = (Component)e.getSource(); int x = source.getX() + e.getX(); int y = source.getY(); MarqueePanel2 marqueePanel = (MarqueePanel2) ((JComponent)e.getSource()).getParent(); double x2 = marqueePanel.getWidth(); double x1 = Math.abs(marqueePanel.scrollOffset); if(x >= x1 && x <= x2) { System.out.println("Bang " + x1); Component componentAt = getComponentAt(x+marqueePanel.scrollOffset, y); if(comp instanceof MouseListener) ((MouseListener) componentAt).mouseClicked(e); System.out.println(componentAt.getName()); } else { return; } //System.out.println(x); } 
  • Нарисуйте круг с радиусом и острием по краю
  • Почему мой JLabel не появляется
  • JTable отключить флажок в ячейке
  • Присоединение к одному пользователю
  • Swing Worker: функция get ()
  • Лучший способ ограничить пользователя вводом времени в JTextField
  • addKeyListener () не работает для JPanel
  • JTextArea не выбирается, но все еще отображается курсор «призрак»
  • Перемещение объектов и таймеров
  • Как изменить цвет конкретных слов в JTextPane?
  • SwingUtilities.invokeLater () зачем он нужен?
  • Interesting Posts
    Давайте будем гением компьютера.