滚动条未与JTextArea一起出现

时间:2018-07-23 10:16:54

标签: java swing jscrollpane jtextarea

好的,所以我最近制作了一个Java控制台应用程序,该应用程序蛮力地强制了您的密码,所以现在我正在使用gui来开发类似的应用程序。 所以我拥有所有代码及其运行,但是由于某种原因,没有出现添加到textArea的滚动条,并且当​​我运行程序时,我既没有滚动条也没有文本区域。 请告诉我我要去哪里错了,并帮助我解决这个问题。

package swinggui;

import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;

public class BruteForce {
    static JFrame frameObject;
    static JPanel panelObject;

JLabel lblPassword;
JTextField txtPassword;
JTextArea txtStatus;
JScrollPane scrollbar;

JButton btn;

BruteForce() {
    panelObject = new JPanel();
    frameObject.getContentPane().add(panelObject);
    panelObject.setLayout(null);

    txtStatus = new JTextArea("Status: ");
    txtStatus.setBounds(10,95,260,160);
    panelObject.add(txtStatus);

    lblPassword = new JLabel("Password: ");
    txtPassword = new JTextField();

    Font dialog = new Font("Dialog", Font.PLAIN, 14);

    lblPassword.setBounds(10,10,100,30);
    lblPassword.setFont(dialog);
    panelObject.add(lblPassword);

    txtPassword.setBounds(80,10,190,30);
    panelObject.add(txtPassword);

    scrollbar = new JScrollPane(txtStatus);
    panelObject.add(scrollbar);

    btn = new JButton("Test Password Strength");
    btn.setBounds(10,50,260,30);
    panelObject.add(btn);

    btn.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            int password = Integer.parseInt(txtPassword.getText());

            int guess_password = 0;
            while(guess_password != password) {
                txtStatus.append("\n [+] Password Attempt: " + guess_password);
                guess_password = guess_password + 1;
            }
            if(guess_password == password) {
                txtStatus.append("\n \n [-] Password Found: " + guess_password);
            }
        }
    }); 
}
public static void main(String[] args) throws Exception {
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    frameObject = new JFrame("Brute Force Tool");
    frameObject.setVisible(true);
    frameObject.setSize(300,300);
    frameObject.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    BruteForce gui = new BruteForce();
}

}

请告诉我我要去哪里,并更正我的代码。 任何帮助将不胜感激,并在此先感谢。

2 个答案:

答案 0 :(得分:0)

首先重要的提示:不要使用空布局。请了解所有标准layout manager并使用它们填充您的UI。您也可以使用一些第三方布局管理器,例如MigLayout或FormLayout(使用Google查找它们)。这些经理通常比标准更好。

为什么它比null布局更好?因为Java-UI是跨平台的,并且某些组件在不同的OS上可能需要不同的大小。当用户使用某些操作系统功能(如字体缩放)时,可能会发生同样的情况。布局管理器还定义了调整大小行为(当用户更改窗口大小时会发生什么)。

这是您的代码的更正版本(不更改布局管理器)。

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;

public class BruteForce {
    static JFrame frameObject;

    JPanel panelObject;

    JLabel lblPassword;

    JTextField txtPassword;

    JTextArea txtStatus;

    JScrollPane scrollbar;

    JButton btn;

    BruteForce() {
        panelObject = new JPanel();
        frameObject.getContentPane().add(panelObject);
        panelObject.setLayout(null);

        txtStatus = new JTextArea("Status: ");
        // set bounds not required here. it's required for scrollbar
        // txtStatus.setBounds(10,95,260,160);
        panelObject.add(txtStatus);

        lblPassword = new JLabel("Password: ");
        txtPassword = new JTextField();

        Font dialog = new Font("Dialog", Font.PLAIN, 14);

        lblPassword.setBounds(10, 10, 100, 30);
        lblPassword.setFont(dialog);
        panelObject.add(lblPassword);

        txtPassword.setBounds(80, 10, 190, 30);
        panelObject.add(txtPassword);

        scrollbar = new JScrollPane(txtStatus);
        // set the scroll bar bounds
        scrollbar.setBounds(10, 95, 260, 160);
        panelObject.add(scrollbar);

        btn = new JButton("Test Password Strength");
        btn.setBounds(10, 50, 260, 30);
        panelObject.add(btn);

        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int password = Integer.parseInt(txtPassword.getText());

                int guess_password = 0;
                while (guess_password != password) {
                    txtStatus.append("\n [+] Password Attempt: " + guess_password);
                    guess_password = guess_password + 1;
                }
                if (guess_password == password) {
                    txtStatus.append("\n \n [-] Password Found: " + guess_password);
                }
            }
        });
    }

    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        frameObject = new JFrame("Brute Force Tool");
        BruteForce gui = new BruteForce();
        frameObject.add(gui.panelObject); // don't forget to place your panel in the window
        frameObject.setSize(300, 300);
        frameObject.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frameObject.setLocationRelativeTo(null); // center location for window
        frameObject.setVisible(true);
    }

}

答案 1 :(得分:0)

您确实意识到,您不需要应用程序就可以知道,如果您提供整数密码值(例如55673),并且一次循环遍历每个值,它将获得密码号尝试(55673次迭代)以获取该密码。我们以粉笔为例。 :/

我认为您的特定项目存在许多需要注意的问题:

为了简化编码,请设置 BruteForce 类,以使其扩展JFrame public class BruteForce extends javax.swing.JFrame {。您将不需要静态JFrame变量( frameObject ),它会进行一些清理。

main()方法中取出与JFrame相关的所有代码。而是在初始化方法中进行JFrame设置。我认为,如果您具有以下条件,您的 main()方法会更好:

public static void main(String[] args) throws Exception {
   UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

   /* Create and display the form */
   java.awt.EventQueue.invokeLater(new Runnable() {
       @Override
       public void run() {
           new BruteForce().setVisible(true);
       }
   });
}

您的初始化方法可能如下所示:

private void initializeComponents() {
    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setTitle("Brute Force Tool");
    setResizable(false);
    setAlwaysOnTop(true);


    // Size the Form
    // Slightly different from original size since
    // form has been made non-resizable. Makes the
    // form more uniformed.
    setPreferredSize(new Dimension(285, 325));
    setSize(getPreferredSize());

    // Center Form to screen. Should always be after sizing
    setLocationRelativeTo(null); 

    panelObject = new JPanel();
    panelObject.setLayout(null);

    // Password Box Label
    Font dialog = new Font("Dialog", Font.PLAIN, 14);
    lblPassword = new JLabel("Password: ");
    lblPassword.setBounds(10, 10, 100, 30);
    lblPassword.setFont(dialog);
    panelObject.add(lblPassword);

    // Password Entry Text Field
    txtPassword = new JTextField();
    txtPassword.setBounds(80, 10, 190, 30);
    panelObject.add(txtPassword);

    // Text Area with Scroll Pane to display 
    // Brute Force process.
    txtStatus = new JTextArea("Status: ");
    scrollbar = new JScrollPane(txtStatus);
    scrollbar.setBounds(10, 125, 260, 160);
    panelObject.add(scrollbar);

    // Button to start Brute Force Process
    btn = new JButton("Test Password Strength");
    btn.setBounds(10, 50, 260, 30);
    panelObject.add(btn);

    // Display Progress CheckBox
    chkUpdateStatus = new JCheckBox("Display Progress");
    chkUpdateStatus.setBounds(10, 85, 150, 30);
    panelObject.add(chkUpdateStatus);

    // Scroll Progress CheckBox
    chkScrollUpdate = new JCheckBox("Scroll Progress");
    chkScrollUpdate.setBounds(160, 85, 150, 30);
    panelObject.add(chkScrollUpdate);

    // Add filled JPanel to JFrame
    panelObject.setBounds(this.getBounds());
    getContentPane().add(panelObject);


    // Add Button Action Listener
    btn.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (!workThreadIsRunning) { 
                // Clear the TextArea
                txtStatus.setText(null);
                new Thread(workThread).start(); 
            }
            if (btn.getText().equals("Cancel Test")) {
                shutDownThread = true;
            }
        }
    });
}

这意味着您的类构造函数( BruteForce())仅包含:

public BruteForce() {
    initializeComponents();
}

如果您不打算使用 JFrame#pack(),以便根据其所有内容自动调整JFrame的大小,使其达到或超过其首选大小,则 setSize() >自行调整JFrame大小的方法对您没有多大帮助。在这种情况下,您还需要使用 setPreferredSize()方法。

在创建表单时,您想将JTextArea 添加到到JScrollPane中,而不是JPanel中。然后它将是您添加到JPanel中的JScrollPane。

不需要JTextArea的 setBounds(),因为它将填充整个JScrollPane容器。通过 null 布局,您将使用JScrollPane,它将需要提供的 setBounds()

由于您使用的是 Null 布局,因此您的应用程序窗口为 确实足够小,并且已经为所有组件设置了边界,还应该确保不能调整JFrame窗口的大小(setResizable(false);),因为如果这样做会看起来很可笑。我相信您已经鼓吹了很多知识,以了解为什么 Null 布局不一定是一个不错的选择。但是,如果这还不足以满足您的要求,请使用Google Why is null layout in Swing frowned upon?。但是,它确实在世界上占有一席之地,尤其是在使用多种布局时。

  

附带说明:

可以理解,在处理类似这样的事情时,通常很高兴看到该过程正在进行中。可悲的现实是,尝试这样做会严重阻碍速度。

要通过在JTextArea上添加一行指示已处理蛮力尝试(迭代)的有效行来更新JTextArea,您需要使用新线程来执行该更新。当然,这意味着处理(尝试)是在单独的线程中执行的,而不是在事件分配线程(EDT)中完成的,事件分配线程(EDT)在所有处理完成之前不会更新JTextArea(这是您在代码中所做的工作) )。通过将处理代码放置在自己的线程中以立即更新JTextArea实际上是唯一可行的选择,但是确实需要花费一些时间将更新写入JTextArea……实际上是相当长的时间。

例如,如果您在下面运行提供的可运行代码(修改后的代码)并提供密码 222222 ,则在我的系统上大约需要 2147 毫秒( 2秒左右)即可完成任务。如果您要注释掉循环中的 textStatus.append(...),您会发现只需大约 6 毫秒(约0.006秒)即可完成任务。这在处理时间上有很大的不同,如果您正在执行 Brute Force 之类的操作,则希望获得所有速度。如果您希望JTextArea自动滚动以便在视口中显示每个更新,则速度会受到更大的限制。

应该使用我在下面的示例可运行代码中实现的复选框使进度显示为可选,并且由于蛮力处理是在其自己的线程而不是EDT中完成的,因此对复选框的任何更改都应立即生效影响。该按钮还具有更多的切换效果,因此可以取消蛮力处理。

这是完整的代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;


public class BruteForce extends javax.swing.JFrame {

    JPanel panelObject;
    JLabel lblPassword;
    JTextField txtPassword;
    JTextArea txtStatus;
    JScrollPane scrollbar;
    JButton btn;
    JCheckBox chkUpdateStatus;
    JCheckBox chkScrollUpdate;
    Runnable workThread;
    boolean workThreadIsRunning = false;
    volatile boolean shutDownThread = false;

    public BruteForce() {
        initializeComponents();

        workThread = new Runnable() {
            @Override
            public void run() {
                long startTime = System.currentTimeMillis();
                workThreadIsRunning = true;
                int password = Integer.parseInt(txtPassword.getText());
                btn.setText("Cancel Test");
                int guess_password = 0;
                while (guess_password != password & !shutDownThread) {
                    if (chkUpdateStatus.isSelected()) {
                        txtStatus.append("\n [+] Password Attempt: " + String.valueOf(guess_password + 1));
                        if (chkScrollUpdate.isSelected()) {
                            // Update The JTextArea to show immediate processing.
                            // (Slows down processing considerably)
                            txtStatus.setCaretPosition(txtStatus.getText().length() - 1);
                        }
                    }
                    guess_password++;
                }
                long duration = System.currentTimeMillis() - startTime;
                if (guess_password == password) {
                    txtStatus.append("\n \n [-] Password Found: " + guess_password);
                    txtStatus.append("\n [-] It took " + duration + " milliseconds\n     "
                                   + "(just over " + String.valueOf(duration / 1000) + " seconds) "
                                   + "to\n     accomplish.");
                    txtStatus.setCaretPosition(txtStatus.getText().length() - 1);
                }
                workThreadIsRunning = false;
                btn.setText("Test Password Strength");
                shutDownThread = false;
            }
        };
    }

    private void initializeComponents() {
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Brute Force Tool");
        setResizable(false);
        setAlwaysOnTop(true);


        // Size the Form
        // Slightly different from original size since
        // form has been made non-resizable. Makes the
        // form more uniformed.
        setPreferredSize(new Dimension(285, 325));
        setSize(getPreferredSize());

        // Center Form to screen. Should always be after sizing
        setLocationRelativeTo(null); 

        panelObject = new JPanel();
        panelObject.setLayout(null);

        // Password Box Label
        Font dialog = new Font("Dialog", Font.PLAIN, 14);
        lblPassword = new JLabel("Password: ");
        lblPassword.setBounds(10, 10, 100, 30);
        lblPassword.setFont(dialog);
        panelObject.add(lblPassword);

        // Password Entry Text Field
        txtPassword = new JTextField();
        txtPassword.setBounds(80, 10, 190, 30);
        panelObject.add(txtPassword);

        // Text Area with Scroll Pane to display 
        // Brute Force process.
        txtStatus = new JTextArea("Status: ");
        scrollbar = new JScrollPane(txtStatus);
        scrollbar.setBounds(10, 125, 260, 160);
        panelObject.add(scrollbar);

        // Button to start Brute Force Process
        btn = new JButton("Test Password Strength");
        btn.setBounds(10, 50, 260, 30);
        panelObject.add(btn);

        // Display Progress CheckBox
        chkUpdateStatus = new JCheckBox("Display Progress");
        chkUpdateStatus.setBounds(10, 85, 150, 30);
        panelObject.add(chkUpdateStatus);

        // Scroll Progress CheckBox
        chkScrollUpdate = new JCheckBox("Scroll Progress");
        chkScrollUpdate.setBounds(160, 85, 150, 30);
        panelObject.add(chkScrollUpdate);

        // Add filled JPanel to JFrame
        panelObject.setBounds(this.getBounds());
        getContentPane().add(panelObject);


        // Add Button Action Listener
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (!workThreadIsRunning) { 
                    // Clear the TextArea
                    txtStatus.setText(null);
                    new Thread(workThread).start(); 
                }
                if (btn.getText().equals("Cancel Test")) {
                    shutDownThread = true;
                }
            }
        });
    }

    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new BruteForce().setVisible(true);
            }
        });
    }
}