Delay erzeugen, ohne Programm zu blockieren

Javaman91

Bekanntes Mitglied
Hallo,

ich weiß nicht wie ich ein Delay erzeugen kann, ohne dass mein Programm während das Delay ausgeführt wird blockiert ist und nicht mehr auf Inputs reagiert.
Thread.sleep(); funktioniert wunderbar, aber während Thread.sleep(); abgearbeitet wird, reagiert das Programm einfach nicht auf Inputs wie z.B. Maus klicks, Tastatur, Buttons die angeklcikt werden usw.

Das ist ein Problem, da ich das Programm jeder Zeit abrechnen möchte, egal ob gerade das Delay ausgeführt wird oder nicht.

Wie kann ich das ganz einfach machen?
Für ein Beispiel wäre ich euch sehr dankbar.

Viele Grüße
 
Du scheinst von einer UI Anwendung zu sprechen. Die blockiert schlicht nicht! An der Stelle, an der etwas aufhören soll, hörst Du einfach auf. Und wenn es weiter gehen soll, dann machst Du weiter. Wenn dies zeitlich gesteuert sein soll, dann kommt z.B. ein Timer in Frage.
 
Hallo,

ich weiß nicht wie ich ein Delay erzeugen kann, ohne dass mein Programm während das Delay ausgeführt wird blockiert ist und nicht mehr auf Inputs reagiert.
Thread.sleep(); funktioniert wunderbar, aber während Thread.sleep(); abgearbeitet wird, reagiert das Programm einfach nicht auf Inputs wie z.B. Maus klicks, Tastatur, Buttons die angeklcikt werden usw.

Das ist ein Problem, da ich das Programm jeder Zeit abrechnen möchte, egal ob gerade das Delay ausgeführt wird oder nicht.

Wie kann ich das ganz einfach machen?
Hier eine einfache Klasse PauseWorker die du als Schablone für das Problem verwenden kannst.
Anbei das Demo zum Testen.
Java:
import javax.swing.JFrame;

public class StartPauseDemo {

    public static void main(String[] args) {
        JFrame frame = new JFrame("Pause Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        PausePanel pausePanel = new PausePanel(400, 400);
        frame.add(pausePanel);
        frame.pack();
        frame.addKeyListener(pausePanel.getKeyBoard());
        frame.setVisible(true);
    }
}
Java:
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class PausePanel extends JPanel {
    private int count = 0;

    protected PauseWorker worker = new PauseWorker() {
        @Override
        protected boolean executeJob() {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
            count++;
            repaint();
            return false;
        }
    };

    public PausePanel(int width, int height) {
        setPreferredSize(new Dimension(width, height));
        worker.start();
    }

    public KeyAdapter getKeyBoard() {
        return new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                int code = e.getKeyCode();
                if (code == KeyEvent.VK_ESCAPE)
                    worker.pause();
                if (code == KeyEvent.VK_R)
                    worker.resume();
            }
        };
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int fontSize = 25;
        g.setFont(new Font("Courier", Font.BOLD, fontSize));
        g.drawString(count + "", (getWidth() - fontSize) / 2, (getHeight() - fontSize) / 2);
        g.drawString("Press '" + (worker.isPause() ? "R' to resume" : "ESC' to pause") + " job", 10, 2 * fontSize);
    }

}
Java:
public abstract class PauseWorker implements Runnable {
    private boolean pause = false;
    private boolean running = false;
    private Thread thread = null;

    protected abstract boolean executeJob();

    public final boolean isPause() {
        return pause;
    }

    public final boolean isRunning() {
        return running;
    }

    public final void pause() {
        pause = true;
    }

    public final void resume() {
        pause = false;
    }

    @Override
    public final void run() {
        while (running) {
            if (!pause)
                executeJob();
            else {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public final void start() {
        if (running)
            return;
        running = true;
        pause = false;
        thread = new Thread(this);
        thread.start();
    }

    public final void stop() {
        running = false;
        pause = true;
        while (thread != null && thread.isAlive())
            ;
        thread = null;
    }
}
😉
 

Anhänge

Zuletzt bearbeitet:
Thread.sleep(); funktioniert wunderbar, aber während Thread.sleep(); abgearbeitet wird, reagiert das Programm einfach nicht auf Inputs wie z.B. Maus klicks, Tastatur, Buttons die angeklcikt werden usw.
Kein Wunder...du hast den Thread, in dem dein Programm ausgeführt wird, schlafen geschickt. Natürlich tut der dann nix mehr.

Die Kunst, die Blender3D bereits demonstriert hat, besteht darin, die Arbeit an einen anderen Thread auszulagern. Also diesen Thread dann entweder die Abbrucheingabe entgegenzunehmen. Oder nach einer gewissen Zeit eben die gewünschte Aktion selber ausführt, wie du das aufteilst ist egal.
 
Vielen Dank für eure Hilfe!
Auch für das sehr ausführliche Beispiel!!
Ich habs mal mit dem Timer probiert, den habe ich zuvor noch nie verwendet.

Soweit funktioniert das mit dem Timer echt super.
Was mir aber aufgefallen ist, ist das wenn die run() - Methode mit sehr geringen Zeitabständen aufgerufen wird, das Programm nicht sofort beendet wird, wenn ich z.B. die Maus klicke.
Läuft der Timer z.B. mit 1000ms, dann unterbricht das Programm beim Mausklick sofort.
Läuft er aber z.B. mit nur 10ms, dann muss ich sehr oft die Maus betätigen, bis das Programm reagiert.

Da muss ich noch etwas herumprobieren.

Schöne Grüße
 
Ganz einfacher Code.
Ich habe ein JFrame mit JPanel und darauf buttons.
Beim anklicken vom button "move" startet das Programm.

Hier ist der Teil des Codes, wo alles passiert:

Java:
@Override
public void actionPerformed(ActionEvent e) {
    if(e.getSource() == move) { // JButton move

          timer = new Timer(); // Timer als globale Variable
          TimerTask task = new TimerTask(){
                                                               
                    @Override
                    public void run(){

                    // Hier ist der Code der nach einer Zeit vom Timer aufgerufen wird.
                    // Hier wird nur eine Zufallszahl generiert und dann als Position
                    // an rob.mouseMove übergeben.
                        
                    rob.mouseMove(randomNumberX, randomNumberY);
                    }
                };
                timer.schedule(task, 10, 10);   
            }   
        }
    
    @Override
        public void mouseClicked(MouseEvent e) {
            
            if(SwingUtilities.isRightMouseButton(e)) {
                timer.cancel();
                System.out.println("Stop");
            }   
        }

Wie gesagt, mit 1000ms bei timer.schedule funktioniert es wunderbar, mit 10ms fast garnicht mehr.

SG
 

Neue Themen


Zurück
Oben