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 ...

Produkt finalny

Po kliknięciu przycisku „Hello World” powinien również pojawić się na konsoli.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow