Memeriksa opsi di Infinite loop kosong vs dosomething infite loop
public static void main(String... s) {
StartUp obj = new StartUp();
while(true) {
//System.out.println("Option - " + option);
if(option == 1) {
option = 0;
obj.setVisible(false);
obj.dispose();
new Test();
break;
}else if(option == 2) {
option = 0;
obj.setVisible(false);
obj.dispose();
new PWorld.Splash().load();
break;
}
}
}
Saya harus meletakkan System.out.println("Option - " + option);di dalam while loop agar bisa bekerja jika tidak programe macet setelah menjalankan StartUp obj = new StartUp ();
optionadalah int statis di dalam kelas StartUp dan diubah oleh Actionlistener, nilai di dalamnya optiondiubah oleh ActionListener tetapi while loop tampaknya tidak berfungsi.
Tetapi jika saya memasukkan ke System.out.println("Option - " + option);dalam while loop, itu berhasil. MENGAPA!
Saya menggunakan loop while ini karena new PWorld.Splash().load();has Thread.sleep(), dan seperti dalam jawaban ini, JFrame baru tidak akan ditarik jika dipanggil dari ActionListener (di UI Thread) yang memiliki Thread.
Terima kasih
Jawaban
Masalah Anda adalah:
- Anda memanggil loop "ketat", yang menghabiskan CPU dan memblokir kode lain agar tidak berjalan. The
System.out.println(...)Pernyataan menambahkan kode yang memperlambat lingkaran ini, merilis CPU dari rahang loop ketat, yang memungkinkan benang lain untuk menjalankan, dan ini adalah asal-usul dari pertanyaan Anda. - Karena itu, sekali lagi, pendekatan pengkodean Anda tidak baik, karena Anda menggunakan
while (true)loop sebagai pengganti merespons suatu peristiwa, yang merupakan cara bagaimana GUI Swing harus dikodekan. - Anda menyatakan bahwa alasannya adalah bahwa satu bit kode di while loop memanggil a
Thread.sleepdan bahwa kode ini, jika dipanggil di thread event Swing, seperti dalam ActionListener, akan memblokir event thread, membekukan GUI Anda - semua benar. - Tapi solusi Anda salah. Solusi yang benar adalah tidak memanggil ini dalam
while (true)loop dalam metode utama, melainkan memanggilThread.sleepdari thread latar belakang, seperti dalamdoInBackground()metode SwingWorker (tautan ke tutorial), atau lebih baik lagi, menggunakan Swing Timer (sekali lagi, tautannya ke tutorial) menggantikanThread.sleep. Ini akan memungkinkan kode Anda untuk menjeda beberapa kode tanpa memblokir thread acara Swing. - Pilihan lain, jika Anda perlu menampilkan jendela dialog (sub) adalah menggunakan modal JDialog untuk menampilkan jendela sambil memblokir interaksi dengan jendela GUI utama, hingga jendela dialog tidak lagi terlihat.
Untuk solusi yang lebih mendetail dan komprehensif, sekali lagi, harap pertimbangkan untuk membuat dan memposting program Contoh Minimal yang Dapat Direproduksi dengan pertanyaan Anda.
Misalnya, inilah Contoh Minimal dan Dapat Direproduksi:
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Window;
import javax.swing.*;
public class MinReproExample {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
Startup startup = new Startup();
startup.showStartUp();
Option option = startup.getOption();
if (option == Option.TEST) {
JOptionPane.showMessageDialog(null, "Test selected", "Selection", JOptionPane.DEFAULT_OPTION);
} else if (option == Option.PWORLD) {
PWorld pworld = new PWorld();
pworld.showSplash();
}
});
}
}
class Startup {
private JDialog startupDialog;
private Option option = null;
public Startup() {
ButtonGroup buttonGroup = new ButtonGroup();
JPanel optionsPanel = new JPanel(new GridLayout(1, 0, 10, 10));
optionsPanel.setBorder(BorderFactory.createTitledBorder("Options"));
for (final Option op : Option.values()) {
JRadioButton rBtn = new JRadioButton(op.getText());
rBtn.setActionCommand(op.getText());
optionsPanel.add(rBtn);
buttonGroup.add(rBtn);
rBtn.addActionListener(e -> {
option = op;
Window window = SwingUtilities.getWindowAncestor(optionsPanel);
window.dispose();
});
}
startupDialog = new JDialog(null, "Select Option", ModalityType.APPLICATION_MODAL);
startupDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
startupDialog.add(optionsPanel);
startupDialog.pack();
startupDialog.setLocationRelativeTo(null);
}
public void showStartUp() {
if (startupDialog != null) {
startupDialog.setVisible(true);
}
}
public Option getOption() {
return option;
}
}
class PWorld {
private static final Color ROBINS_EGG_BLUE = new Color(0, 204, 204);
private JDialog pworldSplashDialog;
private JFrame mainPWorldFrame;
public PWorld() {
JLabel splashLabel = new JLabel("Splash Window", SwingConstants.CENTER);
JPanel splashPanel = new JPanel(new GridBagLayout());
splashPanel.add(splashLabel);
splashPanel.setBackground(Color.PINK);
splashPanel.setPreferredSize(new Dimension(300, 250));
pworldSplashDialog = new JDialog(null, "Splash", ModalityType.MODELESS);
pworldSplashDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
pworldSplashDialog.add(splashPanel);
pworldSplashDialog.pack();
pworldSplashDialog.setLocationRelativeTo(null);
JLabel mainLabel = new JLabel("Main GUI Window", SwingConstants.CENTER);
JPanel mainPanel = new JPanel(new GridBagLayout());
mainPanel.add(mainLabel);
mainPanel.setBackground(ROBINS_EGG_BLUE);
mainPanel.setPreferredSize(new Dimension(500, 350));
mainPWorldFrame = new JFrame("Main PWorld GUI");
mainPWorldFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPWorldFrame.add(mainPanel);
mainPWorldFrame.pack();
mainPWorldFrame.setLocationRelativeTo(null);
}
public void showSplash() {
int timerDelay = 2000; // two second delay
Timer timer = new Timer(timerDelay, e -> {
if (pworldSplashDialog != null && pworldSplashDialog.isVisible()) {
pworldSplashDialog.dispose();
showMainPWorldFrame();
}
});
timer.setRepeats(false);
timer.start();
pworldSplashDialog.setVisible(true);
}
private void showMainPWorldFrame() {
mainPWorldFrame.setVisible(true);
}
}
// options to choose from
enum Option {
TEST("Test"), PWORLD("PWorld");
private String text;
private Option(String text) {
this.text = text;
}
public String getText() {
return text;
}
}
Apa yang diharapkan dilakukan loop ini jika opsi bukan 1 atau 2 pada entri awal? Anda hanya membakar siklus CPU tanpa alasan, menunggu utas lain melakukan sesuatu.
Menambahkan pernyataan print menyuntikkan sedikit penundaan non-CPU-burning, dalam hal ini mungkin utas yang akan menyetel 'opsi' akan berjalan.
(FWIW, 'opsi' mungkin perlu dinyatakan tidak stabil jika Anda mengharapkan perubahan dapat dilihat oleh utas lain).
Ini bukan desain yang bagus. Saya tidak tahu cukup tentang konteks untuk memberi tahu Anda apa yang harus Anda lakukan, tetapi semacam mekanisme pemberitahuan yang layak diperlukan. Tetapi ini harus menjawab pertanyaan Anda tentang 'MENGAPA?'.