You have to understand the concept of the thread. AWT and Swing run on a thread called EDT (see in this answer as well as in this question ). The EDT is responsible for receiving events from the operating system (mouse, keyboard, drag windows, maximize, minimize, redraw the screen, etc.). EDT is also the thread that responds to events, such as a click of a button.
It's important for the application to be responsive, never overloading the WBS with heavy tasks. You should always make the best effort so that she is free to do what is her purpose and nothing more. That is, tasks such as reading or writing files, doing complicated loop operations, performing batch operations, uploading or downloading data on the internet, etc. from within EDT is a bad idea.
What happens is that you are locking the EDT in an infinite loop. That being said, it will get stuck in the loop and will not be able to process events to redraw the screen or receive the click on the other button. The solution in your case is to use another thread to release the EDT:
private volatile Thread runner;
private void loop() {
while (runner == Thread.currentThread()) {
System.out.print("Olá");
}
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
if (runner != null) return;
runner = new Thread(this::loop);
runner.start();
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
runner = null;
}