Вот код, который я собрал вместе, чтобы вы начали. Обычно я бы взял код ActionListener и поместил его в какой-то класс MarqueeController
, чтобы сохранить эту логику отдельно от панели, но это другой вопрос об организации архитектуры MVC, и в достаточно простом классе, как это, может быть, так что важно.
Существуют также различные библиотеки анимации, которые помогут вам сделать это, но мне обычно не нравится включать библиотеки в проекты только для решения одной такой проблемы.
public class MarqueePanel extends JPanel { private JLabel textLabel; private int panelLocation; private ActionListener taskPerformer; private boolean isRunning = false; public static final int FRAMES_PER_SECOND = 24; public static final int MOVEMENT_PER_FRAME = 5; /** * Class constructor creates a marquee panel. */ public MarqueePanel() { this.setLayout(null); this.textLabel = new JLabel("Scrolling Text Here"); this.panelLocation = 0; this.taskPerformer = new ActionListener() { public void actionPerformed(ActionEvent evt) { MarqueePanel.this.tickAnimation(); } } } /** * Starts the animation. */ public void start() { this.isRunning = true; this.tickAnimation(); } /** * Stops the animation. */ public void stop() { this.isRunning = false; } /** * Moves the label one frame to the left. If it's out of display range, move it back * to the right, out of display range. */ private void tickAnimation() { this.panelLocation -= MarqueePanel.MOVEMENT_PER_FRAME; if (this.panelLocation < this.textLabel.getWidth()) this.panelLocaton = this.getWidth(); this.textLabel.setLocation(this.panelLocation, 0); this.repaint(); if (this.isRunning) { Timer t = new Timer(1000 / MarqueePanel.FRAMES_PER_SECOND, this.taskPerformer); t.setRepeats(false); t.start(); } } }
Если Вы хотите более функциональный подход, и избегать цикличного выполнения можно просто вызвать функцию, пока результат не null
, и на каждом получении Вы нарезаете строку к позиции группы получений.
// The MatchAll Function
function matchAll (regexp, input, matches = []) {
const regex = regexp.exec(input)
if (regex === null) return matches
// Filter out any undefined results
const matched = regex.filter(i => i)
// Destruct some common used values
const { index } = regex
const [ full, g1, g2, g3] = matched
// Slice the input string to last match
const string = input.slice(index + full.length)
// Do something with the captured groups
// Push this into an array
matches.push({
prop: 'H' + g1 + g3 + g3 + 'ary ' + g2
})
// Return
return matchAll(regexp, string)
}
// Record of matches
const matches = []
// The RegExp, we are looking for some random letters / words in string
const regExp = new RegExp(/(i{1}).*(did).*(l{1})/)
// An example string to parse
const testString = `Jeffrey Epstein didn't kill himself!`
// Run
matchAll(regExp, testString, matches)
// Returned Result
console.log(matches)