I am writing a code which takes as input a word (the name of a board game) or a letter and searches it in my DB.
If there are any entries I'll show them in a table, otherwise I don't want to show the empty table and I want to show a label "No results found" which disappears after 1500ms.
The if statement works properly. For example if I write 't' I'll get all the games starting with 't' in a table.
The else statement sometimes has problems:
if I run my program and I first write as input 'b' (no entries starting with 'b' in my DB) --> it shows the label "no results found" and then it disappears (it works!)
if I run my program and I write as input 't' (it works as said) and then I write 'a' (I have entries with 'a', it works) [.....] and then finally I write as input 'b' (no entries starting with 'b' in my DB) here is the problem: it shows the label "No results found" but it ALSO shows the table with the results of my very first input (i.e. the games starting with 't').
What am I doing wrong? Thanks!
Here the code after clicking the button "Search":
btnCerca.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
/*Connect to DB:*/
Database db = new Database();
Connection connection = null;
try
{
connection = db.connectToDB();
}
catch (SQLException ex)
{
ex.printStackTrace();
}
/*Create a query which search in the DB the word/letter entered by the user*/
Query query = new Query (connection);
query.search(textField.getText()); //execute the query
/*Get results:*/
ResultSet rs = query.getResults();
/* check if rs is empty */
boolean res = false;
try
{
res = rs.isBeforeFirst();
}
catch (SQLException e1)
{
e1.printStackTrace();
}
ListTableModel model = null;
JScrollPane scrollPane = new JScrollPane();
if (res) //there is something in rs
{
try
{
model = ListTableModel.createModelFromResultSet(rs);
}
catch (SQLException e1)
{
e1.getMessage();
}
/*The table which will show the results*/
JTable table_1 = new JTable(model);
scrollPane.setBounds(10, 75, 1200, 300);
panelRicerca.add(scrollPane);
scrollPane.setViewportView(table_1);
}
else //rs is empty
{
JLabel lblNoGiochi = new JLabel("No results found.");
lblNoGiochi.setBounds(448, 30, 400, 14);
panelRicerca.add(lblNoGiochi);
panelRicerca.repaint();
/*...I want the label disappear after 1500ms:*/
int delay = 1500;
ActionListener taskPerformer = new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
panelRicerca.remove(lblNoGiochi);
panelRicerca.repaint();
}
};
new Timer(delay, taskPerformer).start();
}
}
});
------------------------EDIT------------------------
I made a simpler example which is affected by the same problem so you can compile and check quicker.
If I write "hello" I want to display a table.
If I write anything else, I want the table to show a label instead.
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JLabel;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Test {
private JFrame frame;
private JTextField textField;
private JTable table;
private JLabel lbl;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Test window = new Test();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Test() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
lbl = new JLabel("Hey");
lbl.setBounds(378, 236, 46, 14);
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
textField = new JTextField();
textField.setBounds(102, 48, 86, 20);
frame.getContentPane().add(textField);
textField.setColumns(10);
JButton btnOk = new JButton("ok");
btnOk.addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent arg0)
{
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(20, 20, 50, 50);
table = new JTable();
if (textField.getText().equals("hello"))
{
System.out.println("I'm in the if statement");
//show the table:
frame.getContentPane().add(scrollPane);
scrollPane.setViewportView(table);
}
else
{
System.out.println("I'm in the else statement");
//don't show the table:
scrollPane.remove(table);
/* Already tried to use:
- revalidate and repaint the scrollPane
- revalidate and repaint the contentPane
- remove the entire scrollPane from the ContentPane
- remove the table from the scrollPane, then remove the scrollPane from the ContentPane
*/
//and show a label instead:
frame.getContentPane().add(lbl);
frame.getContentPane().repaint();
}
}
});
btnOk.setBounds(211, 47, 89, 23);
frame.getContentPane().add(btnOk);
}
}
You add the table to the panel:
panelRicerca.add(scrollPane);
Later you add the label to the panel:
panelRicerca.add(lblNoGiochi);
Nowhere do you remove the table pane from the panel, so it will always be displayed.
You need to either:
remove the table pane before adding the label
Use a CardLayout. The CardLayout allows you to swap components in the same panel so only one is ever visible. Read the Swing tutorial on How to Use CardLayout for more information.
Edit:
Well in my original answer I suggested you need to remove the table from the panel. Actually I meant "scroll pane" since you never add the table to the panel. Notice the code I posted is showed add the "scroll pane" to the panel. You were meant to do the opposite.
In your original code you added and removed the label from the same panel. My suggestion was to add/remove the scroll pane from the same panel.
Again the same concept, you could remove the table from the scroll pane. But again you add the table to the "viewport" of the scrollpane. So if you want to remove it you do the opposite. You remove it from the viewport of the scrollpane, by using setViewportView(null). This won't remove the scroll pane from the panel (which is still the easiest solution) but the table won't display in the scroll pane.
However, neither of the above suggestions will work in you demo code because you keep creating a new JScrollPane in your MouseListener so you don't have a reference to the scrollpane that you added to the frame. So the scroll pane variable needs to be an instance variable and you create the scroll pane in your constructor.
Also, don't use null layouts. Swing was designed to be used with layout managers. So the basic code when do dynamic layout changes is:
panel.remove(...);
panel.add(...);
panel.revalidate(); // to invoke layout manager
panel.repaint(); // repaint changes.
So the basic answer I was trying to give is that if your want to "remove" something, you need to do the opposite of what you did to add the component to the frame.
Related
I am currently having trouble with a JTextPane not updating when a JButton ActionListener is telling it to update. In the code, I have a button that assigns a selected value from a JList to a global variable.
This process works because when I print out the variable when I press the button it prints the selected value in a list. However, when I push the button I also want that variable to populate the text pane so I know what value I am working with when using the UI. Does anyone know what might help with this?
I will try to get the relevant code from my large JavaSwing script as I'm using Eclipse WindowBuilder and it throws everything in the source in whatever order I created it.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class MainMappingGui extends JFrame {
private JPanel contentPane;
String attSelected = "Hello";
String attButSelect = "";
JTextPane textPaneEdits;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainMappingGui frame = new MainMappingGui();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public MainMappingGui() {
setTitle("Data Mapping");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 1105, 892);
contentPane = new JPanel();
contentPane.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
setContentPane(contentPane);
contentPane.setLayout(null);
JButton btnConfigMap = new JButton("Configure Mapping");
btnConfigMap.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
attButSelect = attSelected;
System.out.println(attButSelect);
textPaneEdits.repaint();
textPaneEdits.revalidate();
}
});
btnConfigMap.setFont(new Font("Tahoma", Font.PLAIN, 9));
btnConfigMap.setBounds(206, 406, 122, 23);
contentPane.add(btnConfigMap);
textPaneEdits = new JTextPane();
textPaneEdits.setBounds(634, 38, 314, 357);
textPaneEdits.setEditable(false);
textPaneEdits.setText("Current Output Column: " + attButSelect);
contentPane.add(textPaneEdits);
}
}
For this example, please assume that attSelected is a value that changes dynamically with a ListSelectionListener and works properly for selected values in a list. I have set it to "Hello" for simplicity sake.
As the one of the comments says, you have to manually change the text in the text pane.
btnConfigMap.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
attButSelect = attSelected;
textPaneEdits.setText(attButSelect);
}
});
Repaint and revalidate are not necessary.
Im creating a programme using java. I want the user to enter some text, then push the button so the text entered shows in the label. However, I have 2 problems. First, the text are isn´t displaying when I execute the app. Second, I don´t know how to allow the user to type in the area. Im new in java so that´s why Im asking. Here is the code. Thank you.
import javax.swing.*;
import java.awt.event.*;
class Boton extends JFrame implements ActionListener {
JButton boton;
JTextArea textArea = new JTextArea();
JLabel etiqueta = new JLabel();
public Boton() {
setLayout(null);
boton = new JButton("Escribir");
boton.setBounds(100, 150, 100, 30);
boton.addActionListener(this);
add(boton);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == boton) {
try {
String texto = textArea.getText();
etiqueta.setText(texto);
Thread.sleep(3000);
System.exit(0);
} catch (Exception excep) {
System.exit(0);
}
}
}
}
public class Main{
public static void main(String[] ar) {
Boton boton1 =new Boton();
boton1.setBounds(0,0,450,350);
boton1.setVisible(true);
boton1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Problems:
You never add the JTextArea into your GUI, and if it doesn't show, a user cannot directly interact with it.
You are calling Thread.sleep on the Swing event thread, and this will put the entire application to sleep, meaning the text that you added will not show.
Other issues include use of null layouts and setBounds -- avoid doing this.
Solutions:
Set the JTextArea's column and row properties so that it sizes well.
Since your JTextArea's text is going into a JLabel, a component that only allows a single line of text, I wonder if you should be using a JTextArea at all. Perhaps a JTextField would work better since it allows user input but only one line of text.
Add the JTextArea to a JScrollPane (its viewport actually) and add that to your GUI. Then the user can interact directly with it. This is most easily done by passing the JTextArea into a JScrollPane's constructor.
Get rid of the Thread.sleep and instead, if you want to use a delay, use a Swing Timer. check out the tutorial here
For example:
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Window;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class Main2 {
public static void main(String[] args) {
// create GUI in a thread-safe manner
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
BotonExample mainPanel = new BotonExample();
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
class BotonExample extends JPanel {
private JLabel etiqueta = new JLabel(" ");
private JButton boton = new JButton("Escribir");
// jtext area rows and column properties
private int rows = 5;
private int columns = 30;
private JTextArea textArea = new JTextArea(rows, columns);
public BotonExample() {
// alt-e will activate button
boton.setMnemonic(KeyEvent.VK_E);
boton.addActionListener(e -> {
boton.setEnabled(false); // prevent button from re-activating
String text = textArea.getText();
etiqueta.setText(text);
// delay for timer
int delay = 3000;
Timer timer = new Timer(delay, e2 -> {
// get current window and dispose ofit
Window window = SwingUtilities.getWindowAncestor(boton);
window.dispose();
});
timer.setRepeats(false);
timer.start(); // start timer
});
// create JPanels to add to GUI
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 5, 5));
topPanel.add(new JLabel("Etiqueta:"));
topPanel.add(etiqueta);
JPanel bottomPanel = new JPanel();
bottomPanel.add(boton);
JScrollPane scrollPane = new JScrollPane(textArea);
// use layout manager and add components
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(scrollPane, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
}
}
textarea.setText("Text"); // this will insert text into the text area
textarea.setVisable(true); // this will display the text area so you can type in it
textarea.setSize(500,500); // set size of the textarea so it actually shows
The user should be able to type in the TA when it is displayed and just do a getText to pull the text
The commented codes are the problem. When I am using them, panels are added successfully, but I don't need these commented code anymore but same code is not working after I remove or comment those blocks.
Those codes that I have commented need to be removed. Without those commented codes, program runs but does not add panels. I use IntelliJ for my Java Project.
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class Test extends JFrame{
JPanel panel;
JButton send;
JTextField text;
JPanel chatArea;
boolean typing;
Test(){
setSize(365,515);
setLocation(50,100);
setLayout(null);
panel = new JPanel();
panel.setLayout(null);
panel.setBounds(0,0,350,60);
panel.setBackground(new Color(90000000));add(panel);
JLabel name = new JLabel("IRONMAN");
name.setFont(new Font("SAN_SERIF", Font.PLAIN,14));
name.setForeground(Color.white);
name.setBounds(110,35,120,20);panel.add(name);
text = new JTextField();
text.setBounds(15,430,260,40);
text.setFont(new Font("SAN_SERIF",Font.PLAIN,14));
text.setForeground(Color.BLUE);
// Timer timer = new Timer(1, event -> {
// if (!typing){
// name.setText("IRONMAN");
// }
// });
// timer.setInitialDelay(2000);
// text.addKeyListener(new KeyAdapter() {
// #Override
// public void keyPressed(KeyEvent e) {
// name.setText("IRONMAN typing...");
// timer.stop();
// typing = true;
// }
// #Override
// public void keyReleased(KeyEvent e) {
// typing = false;
// if (!timer.isRunning()){
// timer.start();
// }
// }
// });
add(text);
chatArea = new JPanel();
chatArea.setBounds(5,65,340,350);
add(chatArea);
send = new JButton("Send");
send.setBounds(280,430,65,30);
send.setBackground(new Color(200,120,255));
send.setForeground(new Color(7,95,75));
send.addActionListener(e -> {
String message = "STARK: "+text.getText();
JPanel p2 = formatLabel(message);
chatArea.add(p2);
text.setText("");
});
add(send);
}
private JPanel formatLabel(String message) {
JPanel p3 = new JPanel();
JLabel label1 = new JLabel("<html><p style = \"width : 150px\">" + message + "</p></html>");
label1.setBackground(new Color(200,120,255));
label1.setForeground(new Color(7,95,75));
label1.setFont(new Font("SAN_SERIF",Font.PLAIN,18));
label1.setOpaque(true);
label1.setBorder(new EmptyBorder(15,15,15,70));
p3.add(label1);
return p3;
}
public static void main(String[] args) {
Test t = new Test();
t.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
t.setVisible(true);
}
}
First off all some general comments:
label1.setBorder(new EmptyBorder(15,15,15,70));
Don't be afraid to use whitespace. For example
label1.setBorder(new EmptyBorder(15, 15, 15, 70));
It is easier for our eyes to see text with whitespace.
setLayout(null);
Don't use a null layout. Swing was designed to be used with layout managers. You can easily use the default BorderLayout of the JFrame. Add:
the top panel to BorderLayout.PAGE_START
the chat panel to BorderLayout.PAGE_CENTER
the bottom panel to BorderLayout.PAGE_END
after I remove or comment those blocks.
That code is not the solution or the problem.
The problem is that a component has a size of (0, 0) so there is nothing to paint.
In your existing code try resizing the frame by making it wider. The panel will appear. This is because the resizing will cause the layout manager to be invoked which will give the panel a size so it can be painted.
In your code you need to use:
chatArea.add(p2);
chatArea.revalidate();
The revalidate() will automatically invoke the layout manager.
If I want to prevent the JTextArea from scrolling to the bottom when I add text to the end, the solution is very simple: Just set the caret's update policy to DefaultCaret.NEVER_UPDATE before calling the JTextArea's append method. I am trying to do the same thing (load the text without scrolling), but for prepending text instead of appending text.
I have tried lots of things. One of them is this, but it doesn't work:
public void loadMoreUp(){
caret = (DefaultCaret)ta.getCaret(); // ta is a JTextArea
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE); //doesn't work
String s = "The new text\n";
ta.setText(s + ta.getText()); // I have also tried with ta.getDocument().insertString(0,s,null)
}
The behavior I want is that "The new text" gets prepended to the top, but the JTextArea doesn't scroll up with it. "The new text" should not be visible unless the user manually scrolls up to see it.
How can I prepend text to the top of a JTextArea, without it scrolling up? My JTextArea is in a JScrollPane if that is relevant.
So it turns out that making your JTextArea uneditable is what's keeping the scrollbar at the top. I don't think prepending text is moving it -- it's more the case that it never moves at all.
If the goal is simply to keep the scrollbar scrolled all the way down the scrollpane, however, all you really have to do is set the caret position, and no one should be the wiser.
You can even set the caret position to some previous position by saving .getCaretPosition() and using that value later.
textArea.insert("Mein Hund frisst Nuesse\n", 0);
textArea.setCaretPosition(textArea.getDocument().getLength());
You can see my full example here, which you can use to reconcile against your implementation.
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.awt.Dimension;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Foo extends JFrame implements ActionListener
{
JTextArea textArea;
JScrollPane scrollPane;
JButton button;
public Foo()
{
textArea = new JTextArea();
textArea.setEditable(false);
textArea.setText("a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n");
scrollPane = new JScrollPane(textArea);
scrollPane.setPreferredSize(new Dimension(400, 200));
button = new JButton("Prepend");
button.addActionListener(this);
this.add(button, BorderLayout.PAGE_END);
this.add(scrollPane, BorderLayout.PAGE_START);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == button)
{
textArea.insert("Mein Hund frisst Nuesse\n", 0);
textArea.setCaretPosition(textArea.getDocument().getLength());
//textArea.setText("Mein Hund frisst Nuesse\n" + textArea.getText());
}
}
public static void main(String[] args)
{
Foo f = new Foo();
f.setPreferredSize(new Dimension(500, 300));
f.pack();
f.setVisible(true);
}
}
The following code seems to work:
public void loadMoreUp(){
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
String s = "The new text\n";
JScrollBar vbar = scrollPane.getVerticalScrollBar();
int diff = vbar.getMaximum() - vbar.getValue();
try{
ta.getDocument().insertString(0, s, null);
}
catch(BadLocationException e){
logger.error("Bad Location");
}
SwingUtilities.invokeLater(new Runnable(){
public void run(){
vbar.setValue(vbar.getMaximum()-diff);
}
});
}
The basic idea is to remember the position relative to the END of the document (vbar.getMaximum() - vbar.getValue()), and then restore this value after prepending the text.
invokeLater is needed, otherwise getMaximum runs before its value gets updated. The drawback with this method is that invokeLater makes the text briefly flicker.
okay, so I recently made a java console application that brute forced your password so now I was working on a similar app but with a gui.
So I have all the code and its running but for some reason, a scroll bar I added to a textArea is not appearing and when I run the program iI get neither the scroll bar nor the text area.
Please tell me where I am going wrong and help me solve this issue.
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();
}
}
Please tell me where I am going wrong and correct my code.
Any help will be appreciated and thanks in advance.
First of all an important hint: Don't use null layout. Please learn all standard layout manager and use them to fill your UI. Also you can use some third-party layout manager like MigLayout or FormLayout (use Google to find them). These managers are often better then the standard.
Why is it better than null-layout? because Java-UI is cross-platform and some components can require different size on different OSs. The same can occur when the user uses some OS-features (like font scaling). Also layout manager defines the resize behavoir (what should happen when user changes the size of the window).
And here is the corrected version of your code (without layout manager change).
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);
}
}
You do realize that you don't need an application to figure out that if you supply an integer password value (like 55673) and if you iterate through each value one at a time in a loop that it will take the password number of attempts (55673 iterations) to get to that password. We'll just chalk it up as an example. :/
In my opinion there are a number of issues with your particular project that needs some attention:
For a little easier coding, set the BruteForce Class so that it extends JFrame: public class BruteForce extends javax.swing.JFrame {. You won't need the static JFrame variable (frameObject) and it cleans things up somewhat.
Take out all that code related to the JFrame out of the main() method. Do your JFrame setup within a initialization method instead. In my opinion, I think your main() method would be better if you have:
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);
}
});
}
And your initialization method might look like this:
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;
}
}
});
}
Which then means that your class constructor (BruteForce()) simply contains:
public BruteForce() {
initializeComponents();
}
If you are not going to use JFrame#pack() so that JFrame is automatically sized according to all its contents at or above their preferred sizes then the setSize() method to size the JFrame on its own won't help you much. You will also need to use the setPreferredSize() method as well in this case.
When creating your form, you want to add JTextArea into the JScrollPane, not the JPanel. It will then be the JScrollPane you add into the JPanel.
The setBounds() for JTextArea is not required since it will be filling the entire JScrollPane container. With the null layout you are using it will be the JScrollPane which will need the setBounds() supplied.
Since you are using the Null layout and your application window is
indeed small enough, and you've set boundries for all the components, you should also ensure that the JFrame window can not be resized (setResizable(false);) since the form would look ridiculous if it was. I'm sure you've been preached to enough to know why Null Layout is not necessarily a good choice. But if that isn't enough for you then Google this: Why is null layout in Swing frowned upon?. It does however have its place in the world especially when utilizing multiple layouts.
On a side note:
Understandably, when processing something like this it is usually nice to see the progress of that process while it is being carried out. The sad reality is that speed is seriously hampered when trying to do so.
To effectively update the JTextArea by appending a line to it indicating the brute force attempt (iteration) processed you need to use a new thread to carry out that updating. This of course means that the processing (attempts) are carried out in a separate Thread and not done within the Event Dispatch Thread (EDT) which will not update the JTextArea until all the processing is complete (which is what you are doing in your code). By placing the processing code within its own thread that updates the JTextArea immediatly is really the only viable option but it does takes time to write that update to the JTextArea...considerable time as a matter of fact.
As an example if you run the supplied runnable code (your code modified) below and supply a password of 222222, on my system it will take about 2147 milliseconds (around 2 seconds) to complete the task. If you were to comment out the textStatus.append(...) within the loop you would find that it only takes about 6 milliseconds (around 0.006 seconds) to complete the task. This is a very significant difference in processing time and if you're doing something like Brute Force you want every scrap of speed you can get. If you want the JTextArea to automatically scroll so as to display each update within the view port then speed is hampered much much more.
Progress display should be made optional with the use of Check Boxes which I did implement in the sample runnable code below and because the brute force processing is done within its own thread rather than the EDT, any changes to the Check Boxes takes immediate affect. The button also has a more toggle effect so that brute force processing can be canceled.
Here's the full code:
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);
}
});
}
}