Используйте Swing Timer
и DocumentListener
, каждый раз, когда обновляется Document
, перезагрузите Timer
Посмотрите на Как использовать Swing Timers и Прослушивание изменений в документе для более подробной информации
В качестве простого примера ...
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
JTextField field = new JTextField(20);
JLabel label = new JLabel("Waiting");
DeferredDocumentListener listener = new DeferredDocumentListener(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Execute your required functionality here...
label.setText(label.getText() + ".");
}
}, true);
field.getDocument().addDocumentListener(listener);
field.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
listener.start();
}
@Override
public void focusLost(FocusEvent e) {
listener.stop();
}
});
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(field, gbc);
add(label, gbc);
}
}
public class DeferredDocumentListener implements DocumentListener {
private final Timer timer;
public DeferredDocumentListener(int timeOut, ActionListener listener, boolean repeats) {
timer = new Timer(timeOut, listener);
timer.setRepeats(repeats);
}
public void start() {
timer.start();
}
public void stop() {
timer.stop();
}
@Override
public void insertUpdate(DocumentEvent e) {
timer.restart();
}
@Override
public void removeUpdate(DocumentEvent e) {
timer.restart();
}
@Override
public void changedUpdate(DocumentEvent e) {
timer.restart();
}
}
}
Вам потребуется создать кластерный слой и использовать его для создания единой текстовой строки, разделенной новой строкой (или пробелом, если вы предпочитаете) для меток, которые в противном случае перекрывались бы. Стиль результирующего текста в кластерном слое и стиль только геометрии в основном слое. Код будет выглядеть примерно так:
var layerStyle = function(feature) {
var defaultStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#8B8B7A',
width: 5
}),
image: new ol.style.Circle({
radius: 4,
fill: new ol.style.Fill({
color: 'black'
}),
stroke: new ol.style.Stroke({
color: 'black'
})
})
});
var level = feature.get("them_vc");
if (!level || !vcLevels[level]) {
return defaultStyle;
}
for (var key in vcLevels) {
if (level == key) {
var style_ab = new ol.style.Style({
image: new ol.style.Circle({
radius: 4,
fill: new ol.style.Fill({
color: 'black'
}),
stroke: new ol.style.Stroke({
color: 'black'
})
}),
stroke: new ol.style.Stroke({
color: vcLevels[level],
width: vcWideth[level]
})
});
return [style_ab];
}
}
}
var clusterStyle = function(cluster) {
var text_ab = '';
var text_ba = '';
cluster.get('features').forEach( function(feature) {
var level = feature.get("them_vc");
if (level && vcLevels[level]) {
text_ab += feature.get("volume_ab").toString() + '\n';
text_ba += feature.get("volume_ba").toString() + '\n';
}
});
var style_ab = new ol.style.Style({
text: new ol.style.Text({
font: "12px YaHei",
text: text_ab,
fill: new ol.style.Fill({
color: 'black'
}),
rotation: 0,
scale: 1,
offsetX: 10,
offsetY: 10
})
});
var style_ba = new ol.style.Style({
text: new ol.style.Text({
font: "12px YaHei",
text: text_ba,
fill: new ol.style.Fill({
color: 'black'
}),
rotation: 0,
scale: 1,
offsetX: -10,
offsetY: -10
})
});
return [style_ab, style_ba];
}
var mainLayer = new ol.layer.Vector({
source: layerSource,
style: layerStyle
});
var clusterLayer = new ol.layer.Vector({
source: new ol.source.Cluster({
distance: 10,
source: layerSource,
geometryFunction: function(feature) {
switch (feature.getGeometry().getType()) {
case 'Point':
return feature.getGeometry();
case 'LineString':
return new ol.geom.Point(feature.getGeometry().getCoordinateAt(0.5));
case 'Polygon':
return feature.getGeometry().getInteriorPoint();
default:
}
}
}),
style: clusterStyle
});
Добавьте оператор declutter: true
после каждого векторного слоя, он отлично работает.