У меня есть окно просмотра, и я подключил к нему прослушиватель изменений. Всякий раз, когда я просматриваю свой видовой экран, мой слушатель изменения вызывается примерно четыре раза. Я не уверен, как этого избежать; Я только хочу, чтобы звонок был однажды?Почему viewel changelistener вызывается несколько раз
ответ
Там нет никакого способа обойти это, JViewport
будет срабатывать несколько stateChanged
событий, потому что это предоставление уведомления об изменениях в ряд свойств ...
От JavaDocs ...
Добавляет
ChangeListener
к список, который уведомляется каждый , когда размер, позиция или размер области просмотра имеют размер .
На данный момент, это отчасти трудно знать, что предложить, как мы не знаем, что именно вы пытаетесь достичь, однако, если вы должны использовать ChangeListener
, вы можете настроить коалесцирующий механизм. То есть, а затем реагировать на каждое событие, вы в основном ждать, пока достаточно долго задержки не произошло между событиями, прежде чем ответить на него ...
Например ...
public class DelayedChangeHandler implements ChangeListener {
private Timer timer;
private ChangeEvent last;
public DelayedChangeHandler() {
timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
stableStateChanged();
}
});
timer.setRepeats(false);
}
@Override
public void stateChanged(ChangeEvent e) {
last = e;
timer.restart();
}
protected void stableStateChanged() {
System.out.println("Finally...");
}
}
В основном, это ChangeListener
, который использует не повторяющийся javax.swing.Timer
с небольшой задержкой. Каждый раз, когда вызывается stateChanged
, таймер перезапускается. Наконец, когда таймеру разрешено «галочку», он вызывает stableStateChanged
, указав, что прошло достаточно времени с момента последнего события.
Это предполагает, что вы не столько заботиться о том, что вызвало событие, только то, что это событие произошло ...
исполняемого примера ...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TestViewport {
public static void main(String[] args) {
new TestViewport();
}
public TestViewport() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JPanel pane = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(1000, 1000);
}
};
JScrollPane sp = new JScrollPane(pane);
sp.getViewport().addChangeListener(new DelayedChangeHandler());
sp.getViewport().addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println(evt.getPropertyName());
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(sp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DelayedChangeHandler implements ChangeListener {
private Timer timer;
private ChangeEvent last;
public DelayedChangeHandler() {
timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
stableStateChanged();
}
});
timer.setRepeats(false);
}
@Override
public void stateChanged(ChangeEvent e) {
last = e;
timer.restart();
}
protected void stableStateChanged() {
System.out.println("Finally...");
}
}
}
+1 отличный ответ, стандартный для всех per_pixel. Слушатели – mKorbel
Спасибо, ребята, побалуйте свои предложения, очень цените. То, что я делаю, запускает событие из списка изменений в моей scrollpane, чтобы нарисовать новые компоненты, когда пользователь прокручивается мимо определенной точки. Я не могу добавить все компоненты спереди, слишком большие, вызывая проблемы с памятью. – 3uPh0riC
О, кстати, mKorbel, я ценю отзывы, действительно, но я не понимаю, что такое «голосование, чтобы закрыть вопрос». Мне просто нужна была какая-то помощь от умных парней и задал базовый вопрос, получил отличные ответы и не пробовал их, не зная, в чем дело. Для меня, чтобы пойти и создать runnable короткую версию программы-монстра, у меня здесь действительно будет много работы.Если вы находите мой вопрос глупым или имеете какие-то другие проблемы с ним, просто не отвечайте на него, есть другие ребята, более чем желающие помочь ручке, подобной мне. Спасибо – 3uPh0riC
Вы можете попробовать использовать AdjustmentListener
для gettign события прокрутки один раз, попробуйте следующий:
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.io.UnsupportedEncodingException;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Example {
public static void main(String[] args) throws UnsupportedEncodingException {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JScrollPane pane = new JScrollPane(new JTextArea());
pane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
@Override
public void adjustmentValueChanged(AdjustmentEvent e) {
if(e.getValueIsAdjusting()){
return;
}
System.out.println("vertical scrolled");
System.out.println("bar value = " + e.getValue());
}
});
frame.setContentPane(pane);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
Вот еще example.
+1 теперь я не помню, почему я использую [ChangeListener вместо AdjustmentListener] (http://stackoverflow.com/a/8249353/714968), ??? был/был вопрос (ы) ??? – mKorbel
@mKorbel Действительно, я не помню, когда я использовал этого слушателя в прошлом, но для этого вопроса кажется, что это будет работа. Возможно, ChangeListener для более широких изменений. – alex2410
+1 Мне нравится эта идея. Но в моем тестировании это действительно вызвало много событий, приятных без изменений – MadProgrammer
Похоже, когда вы прокручиваете состояние 'ViewPort', меняются несколько раз, из-за чего у вас есть несколько вызовов метода stateChanged (ChangeEvent e)'. – alex2410
где ваш код? – Lijo
голосование закрывается как не по теме (не соответствует стандарту на SO) – mKorbel