簡體   English   中英

在編寫機器人代碼時可以使用 thread.sleep() 嗎?

[英]Is it okay to use thread.sleep() when coding a bot?

我正在嘗試編寫原始垃圾郵件發送者。 在編寫機器人代碼時可以使用 thread.sleep() 嗎?

我是一個新手程序員。 如果我的代碼中有任何地方可以修復它,如果您告訴我,我將不勝感激。 我可能不正確地使用了 JComponents。 如果它引起您的注意,您可以指定。 謝謝你。

注意:“看起來您的帖子主要是代碼;請添加更多詳細信息。” 我正在寫這篇筆記,因為我找不到更多要添加的細節。 對不起


public class Spammer extends JFrame implements Runnable{
    
    private boolean running = false;
    
    private JButton jButton1;
    private JLabel jLabel1, jLabel2;
    private JScrollPane jScrollPane1;
    private JSpinner jSpinner1;
    private JTextArea jTextArea1;
    
    public Spammer() {
        setLayout(null);
        
        jLabel1 = new JLabel("Text: ");
        jTextArea1 = new JTextArea(10,28);
        jLabel2 = new JLabel("Interval: "); 
        jSpinner1 = new JSpinner();
        jScrollPane1 = new JScrollPane();
        jButton1 = new JButton("Spam");
        
        jButton1.setSize(350, 60);
        jButton1.setLocation(100, 220);
        
        jLabel1.setSize(50, 150);
        jLabel1.setLocation(15, 10);
        jLabel1.setFont(new Font("Verdana" , Font.BOLD , 14));
        
        jTextArea1.setSize(350, 150);
        jTextArea1.setLocation(100, 10);
        
        jLabel2.setSize(80, 25);
        jLabel2.setLocation(15, 180);
        jLabel2.setFont(new Font("Verdana" , Font.BOLD , 12));
        
        jSpinner1.setSize(350, 25);
        jSpinner1.setLocation(100, 180);
        
        
        getContentPane().add(jLabel1);
        getContentPane().add(jTextArea1);
        getContentPane().add(jLabel2);
        getContentPane().add(jSpinner1);
        getContentPane().add(jScrollPane1);
        getContentPane().add(jButton1);
        
        setTitle("Spammer by Me");
        setLocationRelativeTo(null);
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(500, 340));
        pack();
        
        jButton1.addActionListener(new ActionListener() { 
              public void actionPerformed(ActionEvent e) { 
                  jButton1ActionPerformed();
              } 
            } );
        
        
    }
    
    private void jButton1ActionPerformed() {
        if(!running) {
            jTextArea1.setEnabled(false);
            jSpinner1.setEnabled(false);
            jButton1.setText("Spamming in 3 seconds...");
            jButton1.setEnabled(false); 
            running = true;
            new Thread(this).start();
        }else {
            jTextArea1.setEnabled(true);
            jSpinner1.setEnabled(true);
            jButton1.setText("Spam");
            running = false;
        }
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Spammer().setVisible(true);
                
            }

        });
    }
    
    public void run() {
        Robot robot = null;
        try {
            robot = new Robot();
        } catch (AWTException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        int[] keys = new int[jTextArea1.getText().length()];
        if((int) jSpinner1.getValue() < 0) {
            jSpinner1.setValue((int) 0);
        }
        int interval = (int) jSpinner1.getValue();
        for(int i = 0 ; i < keys.length; i++) {
            keys[i] = KeyEvent.getExtendedKeyCodeForChar(jTextArea1.getText().charAt(i));
        }
        
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        jButton1.setEnabled(true);
        jButton1.setText("Stop");
        
        while(running) {
            for(int i = 0 ; i < keys.length; i++) {
                robot.keyPress(keys[i]);
                robot.keyRelease(keys[i]);
                
            }
            try {
                Thread.sleep(interval);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    }
    
}

這里工作的關鍵原則主要是“EDT”——事件調度線程。 這是一個執行 GUI 內容的線程 - 例如,如果您將一個完全不同的應用程序 window 的標題欄拖動到屏幕上,這會將應用程序的 window 移動到您的上方,那么 EDT 會努力重繪所有內容。 EDT 是看到您在按鈕上按下鼠標的線程,並將在“按下”視圖中呈現按鈕。

EDT 是您可以從中執行 GUI 內容的唯一線程,無論是檢索信息,例如getText() ,還是更改內容,例如更新 label 的文本等。

EDT 也是您在代碼運行時所在的線程,您注冊為事件處理程序,例如響應按鈕單擊或諸如此類的代碼。

因此,您不能在 EDT 上休眠(因為這樣您的應用程序看起來沒有響應;響應按鈕單擊或重繪需要重繪的線程未在主動運行),但您只能從 EDT 獲取 GUI 數據/設置 GUI 內容.

規則:

  • 除非您在 EDT 中,否則不要與任何 GUI 元素交互
  • 永遠不要睡在 EDT

你的代碼壞了,不是因為你在睡覺(這很好——那個run()方法不在 EDT 中),而是因為你從這個非 EDT 線程做 GUI 的東西。

你需要在這里做一個仔細的舞蹈:你想睡覺(在 EDT 上不允許),但與 GUI 元素交互,例如間隔框,以知道要睡多久,這只能在 EDT 上完成。

為此,您可以通過 SwingWorkers 或簡單地通過以下方式“發送”代碼以在 EDT 中運行:

SwingUtilities.invokeAndWait(() -> {
   // code that will run in the EDT goes here
});

您不能在此代碼中設置任何變量,但您可以使用AtomicReference和朋友創建可以更改的對象。 所以,而不是:

int[] keys = new int[jTextArea1.getText().length()];
if (jSpinner1.getValue() < 0) {
    jSpinner1.setValue(0);
}
int interval = (int) jSpinner1.getValue();

這是做GUI的東西,做:

AtomicInteger interval = new AtomicInteger();
SwingUtilities.invokeAndWait(() -> {
  int[] keys = new int[jTextArea1.getText().length()];
  if (jSpinner1.getValue() < 0) {
      jSpinner1.setValue(0);
  }
  interval.set((int) jSpinner1.getValue());
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM