swing
Podstawy
Szukaj…
Opóźnij zadanie interfejsu użytkownika na określony czas
Wszystkie operacje związane z huśtawką odbywają się w dedykowanym wątku (wątek EDT - E vent D ispatch T ). Jeśli ten wątek zostanie zablokowany, interfejs użytkownika przestanie odpowiadać.
Dlatego jeśli chcesz opóźnić operację, nie możesz użyć Thread.sleep
. Zamiast tego użyj javax.swing.Timer
. Na przykład następujący Timer
odwróci tekst na JLabel
int delay = 2000;//specify the delay for the timer
Timer timer = new Timer( delay, e -> {
//The following code will be executed once the delay is reached
String revertedText = new StringBuilder( label.getText() ).reverse().toString();
label.setText( revertedText );
} );
timer.setRepeats( false );//make sure the timer only runs once
Kompletny przykład, w którym można użyć tego Timer
podano poniżej: interfejs użytkownika zawiera przycisk i etykietę. Naciśnięcie przycisku spowoduje odwrócenie tekstu etykiety po 2 sekundach opóźnienia
import javax.swing.*;
import java.awt.*;
public final class DelayedExecutionExample {
public static void main( String[] args ) {
EventQueue.invokeLater( () -> showUI() );
}
private static void showUI(){
JFrame frame = new JFrame( "Delayed execution example" );
JLabel label = new JLabel( "Hello world" );
JButton button = new JButton( "Reverse text with delay" );
button.addActionListener( event -> {
button.setEnabled( false );
//Instead of directly updating the label, we use a timer
//This allows to introduce a delay, while keeping the EDT free
int delay = 2000;
Timer timer = new Timer( delay, e -> {
String revertedText = new StringBuilder( label.getText() ).reverse().toString();
label.setText( revertedText );
button.setEnabled( true );
} );
timer.setRepeats( false );//make sure the timer only runs once
timer.start();
} );
frame.add( label, BorderLayout.CENTER );
frame.add( button, BorderLayout.SOUTH );
frame.pack();
frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
frame.setVisible( true );
}
}
Powtórz zadanie interfejsu użytkownika w ustalonym odstępie czasu
Aktualizacja stanu komponentu Swing musi nastąpić w wątku wysyłki zdarzeń (EDT). javax.swing.Timer
wyzwala ActionListener
na EDT, co czyni go dobrym wyborem do wykonywania operacji Swing.
Poniższy przykład aktualizuje tekst JLabel
co dwie sekundy:
//Use a timer to update the label at a fixed interval
int delay = 2000;
Timer timer = new Timer( delay, e -> {
String revertedText = new StringBuilder( label.getText() ).reverse().toString();
label.setText( revertedText );
} );
timer.start();
Kompletny przykład, w którym można użyć tego Timer
podano poniżej: interfejs użytkownika zawiera etykietę, a tekst etykiety będzie cofany co dwie sekundy.
import javax.swing.*;
import java.awt.*;
public final class RepeatTaskFixedIntervalExample {
public static void main( String[] args ) {
EventQueue.invokeLater( () -> showUI() );
}
private static void showUI(){
JFrame frame = new JFrame( "Repeated task example" );
JLabel label = new JLabel( "Hello world" );
//Use a timer to update the label at a fixed interval
int delay = 2000;
Timer timer = new Timer( delay, e -> {
String revertedText = new StringBuilder( label.getText() ).reverse().toString();
label.setText( revertedText );
} );
timer.start();
frame.add( label, BorderLayout.CENTER );
frame.pack();
frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
frame.setVisible( true );
}
}
Uruchamianie zadania interfejsu użytkownika określoną liczbę razy
W ActionListener
dołączonym do javax.swing.Timer
możesz śledzić ile razy Timer
wykonał ActionListener
. Po osiągnięciu wymaganej liczby razy możesz użyć metody Timer#stop()
, aby zatrzymać Timer
.
Timer timer = new Timer( delay, new ActionListener() {
private int counter = 0;
@Override
public void actionPerformed( ActionEvent e ) {
counter++;//keep track of the number of times the Timer executed
label.setText( counter + "" );
if ( counter == 5 ){
( ( Timer ) e.getSource() ).stop();
}
}
});
Kompletny przykład, w którym można użyć tego Timer
podano poniżej: pokazuje interfejs, w którym tekst etykiety będzie liczony od zera do pięciu. Po osiągnięciu piątej Timer
zostaje zatrzymany.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public final class RepeatFixedNumberOfTimes {
public static void main( String[] args ) {
EventQueue.invokeLater( () -> showUI() );
}
private static void showUI(){
JFrame frame = new JFrame( "Repeated fixed number of times example" );
JLabel label = new JLabel( "0" );
int delay = 2000;
Timer timer = new Timer( delay, new ActionListener() {
private int counter = 0;
@Override
public void actionPerformed( ActionEvent e ) {
counter++;//keep track of the number of times the Timer executed
label.setText( counter + "" );
if ( counter == 5 ){
//stop the Timer when we reach 5
( ( Timer ) e.getSource() ).stop();
}
}
});
timer.setInitialDelay( delay );
timer.start();
frame.add( label, BorderLayout.CENTER );
frame.pack();
frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
frame.setVisible( true );
}
}
Tworzenie pierwszej JFrame
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class FrameCreator {
public static void main(String args[]) {
//All Swing actions should be run on the Event Dispatch Thread (EDT)
//Calling SwingUtilities.invokeLater makes sure that happens.
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
//JFrames will not display without size being set
frame.setSize(500, 500);
JLabel label = new JLabel("Hello World");
frame.add(label);
frame.setVisible(true);
});
}
}
Jak możesz zauważyć, jeśli uruchomisz ten kod, etykieta znajduje się w bardzo złym miejscu. Trudno to zmienić w dobry sposób za pomocą metody add
. Aby umożliwić bardziej dynamiczne i elastyczne umieszczanie, sprawdź Swing Layout Managers .
Tworzenie podklasy JFrame
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class CustomFrame extends JFrame {
private static CustomFrame statFrame;
public CustomFrame(String labelText) {
setSize(500, 500);
//See link below for more info on FlowLayout
this.setLayout(new FlowLayout());
JLabel label = new JLabel(labelText);
add(label);
//Tells the JFrame what to do when it's closed
//In this case, we're saying to "Dispose" on remove all resources
//associated with the frame on close
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
public void addLabel(String labelText) {
JLabel label = new JLabel(labelText);
add(label);
this.validate();
}
public static void main(String args[]) {
//All Swing actions should be run on the Event Dispatch Thread (EDT)
//Calling SwingUtilities.invokeLater makes sure that happens.
SwingUtilities.invokeLater(() -> {
CustomFrame frame = new CustomFrame("Hello Jungle");
//This is simply being done so it can be accessed later
statFrame = frame;
frame.setVisible(true);
});
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
//Handle error
}
SwingUtilities.invokeLater(() -> statFrame.addLabel("Oh, hello world too."));
}
}
Aby uzyskać więcej informacji na temat FlowLayout tutaj .
Słuchanie wydarzenia
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class CustomFrame extends JFrame {
public CustomFrame(String labelText) {
setSize(500, 500);
//See link below for more info on FlowLayout
this.setLayout(new FlowLayout());
//Tells the JFrame what to do when it's closed
//In this case, we're saying to "Dispose" on remove all resources
//associated with the frame on close
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//Add a button
JButton btn = new JButton("Hello button");
//And a textbox
JTextField field = new JTextField("Name");
field.setSize(150, 50);
//This next block of code executes whenever the button is clicked.
btn.addActionListener((evt) -> {
JLabel helloLbl = new JLabel("Hello " + field.getText());
add(helloLbl);
validate();
});
add(btn);
add(field);
}
public static void main(String args[]) {
//All Swing actions should be run on the Event Dispatch Thread (EDT)
//Calling SwingUtilities.invokeLater makes sure that happens.
SwingUtilities.invokeLater(() -> {
CustomFrame frame = new CustomFrame("Hello Jungle");
//This is simply being done so it can be accessed later
frame.setVisible(true);
});
}
}
Utwórz wyskakujące okienko „Proszę czekać ...”
Ten kod można dodać do dowolnego zdarzenia, takiego jak detektor, przycisk itp. Pojawi się blokujący JDialog
, który pozostanie do zakończenia procesu.
final JDialog loading = new JDialog(parentComponent);
JPanel p1 = new JPanel(new BorderLayout());
p1.add(new JLabel("Please wait..."), BorderLayout.CENTER);
loading.setUndecorated(true);
loading.getContentPane().add(p1);
loading.pack();
loading.setLocationRelativeTo(parentComponent);
loading.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
loading.setModal(true);
SwingWorker<String, Void> worker = new SwingWorker<String, Void>() {
@Override
protected String doInBackground() throws InterruptedException
/** Execute some operation */
}
@Override
protected void done() {
loading.dispose();
}
};
worker.execute(); //here the process thread initiates
loading.setVisible(true);
try {
worker.get(); //here the parent thread waits for completion
} catch (Exception e1) {
e1.printStackTrace();
}
Dodawanie JButtons (Hello World Pt.2)
Zakładając, że pomyślnie utworzyłeś JFrame i że Swing został zaimportowany ...
Swing można importować całkowicie
import javax.Swing.*;
lub Możesz zaimportować komponenty / ramki Swing, których zamierzasz użyć
import javax.Swing.Jframe;
import javax.Swing.JButton;
Teraz dodam Jbutton ...
public static void main(String[] args) {
JFrame frame = new JFrame(); //creates the frame
frame.setSize(300, 300);
frame.setVisible(true);
//////////////////////////ADDING BUTTON BELOW//////////////////////////////
JButton B = new JButton("Say Hello World");
B.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent arg0) {
System.out.println("Hello World");
}
});
B.setBounds(0, 0,frame.getHeight(), frame.getWidth());
B.setVisible(true);
frame.add(B);
////////////////////////////////////////////////////////////////////////////
}
Wykonując / kompilując ten kod powinieneś dostać coś takiego ...
Po kliknięciu przycisku „Hello World” powinien również pojawić się na konsoli.