I am trying to make a calculator in Java GUI classes that has the following properties:
The Text field where the opertations occur must be composed of two lines
Line 1 to print the operation we do
Line 2 to print the resut of the operation
The buttons of the calclator have to be organized in the way shown in the down figure:
Using the GridLayout and BorderLayout layout managers I couldnt get the desired result
How can this be solved ?
The code I wrote is below
import java.awt.GridLayout;
import java.awt.BorderLayout;
import javax.swing.*;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class calculator {
public static JTextField field;
public static String pStr="";
// Create an array containing the buttons texts
public static final String[][] BUTTON_TEXTS = {
{" ", " ", "d", " c"},
{"7", "8", "9", "+"},
{"4", "5", "6", "-"},
{"1", "2", "3", "*"},
{"0", ".", "/", "="}
};
// Create the button hnadler
private static class ButtonHandler implements ActionListener{
private static int clicksNumber = 0;
private String c;
public void numberButtonsAction(JButton a) {
this.c = a.getText();
}
public void actionPerformed(ActionEvent e){
clicksNumber ++ ;
pStr +=((JButton) e.getSource()).getText();
System.out.println(pStr);
field.setText(pStr);
}
}
//Create Font used in caluclator
public static final Font BTN_FONT = new Font(Font.SANS_SERIF, Font.ITALIC, 15);
public static void main(String[] args){
// create the field in which the operations are printed
JTextField text = new JTextField();
text.setSize(20, 500);
field = text;
text.setFont(BTN_FONT); // Set the field font
JLabel myLabel = new JLabel("Se7002");
// Create the grid that will contain the buttons
JPanel btnPanel = new JPanel(new GridLayout(BUTTON_TEXTS.length,
BUTTON_TEXTS[0].length));
// Create and Fill grid with buttons
for(int i=0 ;i<BUTTON_TEXTS.length ; i++){
for(int j=0 ; j< BUTTON_TEXTS[0].length ; j++){
JButton btn = new JButton(BUTTON_TEXTS[i][j]);
btn.setFont(BTN_FONT);
btn.setSize(60,90);
btnPanel.add(btn);
ButtonHandler listener = new ButtonHandler();
btn.addActionListener(listener);
}
}
//Create the content of the calculator
JPanel content = new JPanel(new BorderLayout());
content.add(text,BorderLayout.PAGE_START);
content.add(btnPanel,BorderLayout.CENTER);
content.add(myLabel,BorderLayout.SOUTH);
JFrame CalcTest = new JFrame("Calculator");
CalcTest.setContentPane(content);
CalcTest.setSize(300,350);
CalcTest.setLocation(100, 100);
CalcTest.setVisible(true);
}
}
Here's the Calculator GUI I came up with:
I made a few changes to your code.
I removed almost all of the static methods and variables.
I started the Java Swing GUI on the Event Dispatch thread by calling the SwingUtilities invokeLater method in the main method.
I created a Button and Buttons (Java object) class so I could define the calculator buttons in one place.
I used the GridBagLayout to position the calculator buttons. I used the FlowLayout to position the JTextArea. I used the BorderLayout to put the JTextArea JPanel and the calculator buttons JPanel in the JFrame. I removed all absolute positioning and spacing.
I formatted and organized the code so it would be easier to read and modify.
I put the generation of the JTextArea and the calculator buttons into 2 separate methods.
I didn't do anything with the action listener.
Here's the code.
package com.ggl.testing;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class Calculator implements Runnable {
private static final Font BTN_FONT = new Font(Font.SANS_SERIF, Font.ITALIC,
15);
private Buttons buttons;
private JTextArea textArea;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Calculator());
}
public Calculator() {
buttons = new Buttons();
}
#Override
public void run() {
JFrame calcTest = new JFrame("Calculator");
calcTest.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
calcTest.add(createTextPanel(), BorderLayout.NORTH);
calcTest.add(createButtonPanel(), BorderLayout.SOUTH);
calcTest.pack();
calcTest.setLocationByPlatform(true);
calcTest.setVisible(true);
}
private JPanel createTextPanel() {
JPanel panel = new JPanel();
// Create the field in which the operations are printed
textArea = new JTextArea(2, 15);
textArea.setEditable(false);
textArea.setFont(BTN_FONT); // Set the field font
panel.add(textArea);
return panel;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
ButtonHandler buttonHandler = new ButtonHandler();
for (Button button : buttons.getButtons()) {
JButton jButton = new JButton(button.getLabel());
jButton.addActionListener(buttonHandler);
jButton.setFont(BTN_FONT);
addComponent(panel, jButton, button.getGridx(), button.getGridy(),
button.getGridwidth(), button.getGridheight(),
button.getInsets(), GridBagConstraints.LINE_START,
GridBagConstraints.BOTH);
}
return panel;
}
private void addComponent(Container container, Component component,
int gridx, int gridy, int gridwidth, int gridheight, Insets insets,
int anchor, int fill) {
GridBagConstraints gbc = new GridBagConstraints(gridx, gridy,
gridwidth, gridheight, 1.0D, 1.0D, anchor, fill, insets, 0, 0);
container.add(component, gbc);
}
private class Buttons {
private List<Button> buttons;
public Buttons() {
Insets leftTopInsets = new Insets(10, 10, 4, 4);
Insets topInsets = new Insets(10, 0, 4, 4);
Insets rightTopInsets = new Insets(10, 0, 4, 10);
Insets leftInsets = new Insets(0, 10, 4, 4);
Insets normalInsets = new Insets(0, 0, 4, 4);
Insets rightInsets = new Insets(0, 0, 4, 10);
Insets leftBottomInsets = new Insets(0, 10, 10, 4);
Insets bottomInsets = new Insets(0, 0, 10, 4);
Insets rightBottomInsets = new Insets(0, 0, 10, 10);
this.buttons = new ArrayList<>(18);
this.buttons.add(new Button("7", 0, 0, 1, 1, leftTopInsets));
this.buttons.add(new Button("8", 1, 0, 1, 1, topInsets));
this.buttons.add(new Button("9", 2, 0, 1, 1, topInsets));
this.buttons.add(new Button("/", 3, 0, 1, 1, topInsets));
this.buttons.add(new Button("C", 4, 0, 1, 1, rightTopInsets));
this.buttons.add(new Button("4", 0, 1, 1, 1, leftInsets));
this.buttons.add(new Button("5", 1, 1, 1, 1, normalInsets));
this.buttons.add(new Button("6", 2, 1, 1, 1, normalInsets));
this.buttons.add(new Button("*", 3, 1, 1, 1, normalInsets));
this.buttons.add(new Button("<-", 4, 1, 1, 1, rightInsets));
this.buttons.add(new Button("1", 0, 2, 1, 1, leftInsets));
this.buttons.add(new Button("2", 1, 2, 1, 1, normalInsets));
this.buttons.add(new Button("3", 2, 2, 1, 1, normalInsets));
this.buttons.add(new Button("-", 3, 2, 1, 1, normalInsets));
this.buttons.add(new Button("=", 4, 2, 1, 2, rightBottomInsets));
this.buttons.add(new Button("0", 0, 3, 2, 1, leftBottomInsets));
this.buttons.add(new Button(",", 2, 3, 1, 1, bottomInsets));
this.buttons.add(new Button("+", 3, 3, 1, 1, bottomInsets));
}
public List<Button> getButtons() {
return buttons;
}
}
private class Button {
private final String label;
private final int gridx;
private final int gridy;
private final int gridwidth;
private final int gridheight;
private final Insets insets;
public Button(String label, int gridx, int gridy, int gridwidth,
int gridheight, Insets insets) {
this.label = label;
this.gridx = gridx;
this.gridy = gridy;
this.gridwidth = gridwidth;
this.gridheight = gridheight;
this.insets = insets;
}
public String getLabel() {
return label;
}
public int getGridx() {
return gridx;
}
public int getGridy() {
return gridy;
}
public int getGridwidth() {
return gridwidth;
}
public int getGridheight() {
return gridheight;
}
public Insets getInsets() {
return insets;
}
}
// Create the button handler
private class ButtonHandler implements ActionListener {
private int clicksNumber = 0;
private String c;
public void numberButtonsAction(JButton a) {
this.c = a.getText();
}
public void actionPerformed(ActionEvent e) {
clicksNumber++;
String pStr = ((JButton) e.getSource()).getText();
System.out.println(pStr);
}
}
}
Related
I'm going to develop a Calculator program in Java, I used GridBagLayout, I want put a big "=" button at the bottom right, but that button's height won't expend to the last space as expected, my major code is pasted as below, please help to advise how to figure that:
my problem one is like this
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import org.omg.CORBA.PUBLIC_MEMBER;
public class MyCalculater {
private Frame frame = new Frame("My-Calculator");
private GridBagConstraints gBagConstraints = new GridBagConstraints();
private GridBagLayout gBagLayout = new GridBagLayout();
private Panel screen = new Panel();
private Panel arithSymbolArea = new Panel();
private Panel digitalArea = new Panel();
private JButton[] digitalButtons = new JButton[10];
public void init() {
// Put a screen for output
screen.add(new TextField(40));
frame.add(screen, BorderLayout.NORTH);
// To put the Arith symbols
arithSymbolArea.setLayout(new GridLayout(6, 4));
frame.add(arithSymbolArea);
digitalArea.setLayout(gBagLayout);
initDigitalArea();
frame.add(digitalArea, BorderLayout.EAST);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
super.windowClosing(e);
System.exit(0);
}
});
frame.pack();
frame.setVisible(true);
}
private void initDigitalArea() {
JButton mc = new JButton("mc");
JButton mplus = new JButton("m+");
JButton mminus = new JButton("m-");
JButton mr = new JButton("mr");
JButton ac = new JButton("AC");
JButton pn = new JButton("+/-");
JButton divide = new JButton("÷");
JButton times = new JButton("×");
JButton plus = new JButton("+");
JButton minus = new JButton("-");
JButton equal = new JButton("=");
JButton dot = new JButton(".");
for (int i = 0; i < 10; i++) {
digitalButtons[i] = new JButton(String.valueOf(i));
}
gBagConstraints.fill = GridBagConstraints.BOTH;
gBagConstraints.weightx = 1;
addButton(mc);
addButton(mplus);
addButton(mminus);
gBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
addButton(mr);
gBagConstraints.gridwidth = 1;
gBagConstraints.gridheight = 1;
addButton(ac);
addButton(pn);
addButton(divide);
gBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
addButton(times);
gBagConstraints.gridwidth = 1;
gBagConstraints.gridheight = 1;
addButton(digitalButtons[7]);
addButton(digitalButtons[8]);
addButton(digitalButtons[9]);
gBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
addButton(minus);
gBagConstraints.gridwidth = 1;
gBagConstraints.gridheight = 1;
addButton(digitalButtons[4]);
addButton(digitalButtons[5]);
addButton(digitalButtons[6]);
gBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
addButton(plus);
gBagConstraints.gridwidth = 1;
gBagConstraints.gridheight = 1;
addButton(digitalButtons[1]);
addButton(digitalButtons[2]);
addButton(digitalButtons[3]);
gBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
gBagConstraints.gridheight = 2;
addButton(equal);
gBagConstraints.gridheight = 1;
gBagConstraints.gridwidth = 2;
addButton(digitalButtons[0]);
gBagConstraints.gridwidth = 1;
addButton(dot);
}
private void addButton(JButton button) {
gBagLayout.setConstraints(button, gBagConstraints);
digitalArea.add(button);
}
public static void main(String[] args) {
new MyCalculater().init();
}
private void calculate() {
}
class DigitalButton extends JButton {
public DigitalButton() {
// TODO Auto-generated constructor stub
this.setBackground(new Color(0, 0, 0));
}
}
class ArithSymbol extends JButton {
public ArithSymbol() {
// TODO Auto-generated constructor stub
this.setBackground(new Color(128, 128, 128));
}
}
}
Try this one
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
public class MyCalculater
{
private static final Insets insets = new Insets(0, 0, 0, 0);
private Frame frame = new Frame("My-Calculator");
private GridBagConstraints gBagConstraints = new GridBagConstraints();
private GridBagLayout gBagLayout = new GridBagLayout();
private Panel screen = new Panel();
private Panel arithSymbolArea = new Panel();
private Panel digitalArea = new Panel();
private JButton[] digitalButtons = new JButton[10];
public void init() {
// Put a screen for output
screen.add(new TextField(40));
frame.add(screen, BorderLayout.NORTH);
// To put the Arith symbols
arithSymbolArea.setLayout(new GridLayout(6, 4));
frame.add(arithSymbolArea);
digitalArea.setLayout(gBagLayout);
initDigitalArea();
frame.add(digitalArea, BorderLayout.EAST);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
super.windowClosing(e);
System.exit(0);
}
});
frame.pack();
frame.setVisible(true);
}
private void initDigitalArea() {
JButton mc = new JButton("mc");
JButton mplus = new JButton("m+");
JButton mminus = new JButton("m-");
JButton mr = new JButton("mr");
JButton ac = new JButton("AC");
JButton pn = new JButton("+/-");
JButton divide = new JButton("÷");
JButton times = new JButton("×");
JButton plus = new JButton("+");
JButton minus = new JButton("-");
JButton equal = new JButton("=");
JButton dot = new JButton(".");
for (int i = 0; i < 10; i++) {
digitalButtons[i] = new JButton(String.valueOf(i));
}
addComponent(mc, 0, 0, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(mplus, 1, 0, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(mminus, 2, 0, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(mr, 3, 0, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(ac, 0, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(pn, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(divide, 2, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(times, 3, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(digitalButtons[7], 0, 2, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(digitalButtons[8], 1, 2, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(digitalButtons[9], 2, 2, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(minus, 3, 2, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(digitalButtons[4], 0, 3, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(digitalButtons[5], 1, 3, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(digitalButtons[6], 2, 3, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(plus, 3, 3, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(digitalButtons[1], 0, 4, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(digitalButtons[2], 1, 4, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(digitalButtons[3], 2, 4, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(equal, 3, 4, 1, 2, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(digitalButtons[0], 0, 5, 2, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
addComponent(dot, 2, 5, 1, 2, GridBagConstraints.CENTER, GridBagConstraints.BOTH);
}
private void addComponent(JButton button, int gridx, int gridy,
int gridwidth, int gridheight, int anchor, int fill) {
GridBagConstraints gbc = new GridBagConstraints(gridx, gridy, gridwidth, gridheight, 1.0, 1.0,
anchor, fill, insets, 0, 0);
gBagConstraints = gbc;
addButton(button);
}
private void addButton(JButton button) {
gBagLayout.setConstraints(button, gBagConstraints);
digitalArea.add(button);
}
public static void main(String[] args) {
new MyCalculater().init();
}
private void calculate() {
}
class DigitalButton extends JButton {
public DigitalButton() {
// TODO Auto-generated constructor stub
this.setBackground(new Color(0, 0, 0));
}
}
class ArithSymbol extends JButton {
public ArithSymbol() {
// TODO Auto-generated constructor stub
this.setBackground(new Color(128, 128, 128));
}
}
}
I am trying to create a layout where I have two panels with borders around them. I would like the rectangular borders to be of equal size. I would also like the JTextField in the bottom panel to be of that smaller width.
The problem is that, whenever I fill the bottom panel horizontally (using GridBagConstraints.HORIZONTAL), the checkbox and label inside that panel become misaligned with the checkbox and label in the panel above it.
I was hoping an experienced developer could offer insight into how I could make the two JPanels and their rectangular borders equal in size with one another, while also having their checkboxes and labels aligned.
Here is what it looks like now:
Here is code to reproduce the problem:
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.Border;
public class Example
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable() {
public void run() {
try
{
MyFrame frame = new MyFrame();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
}
class MyFrame
{
private JFrame frame;
private MyDialog dialog;
public MyFrame()
{
frame = new JFrame();
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
dialog = new MyDialog(frame);
}
}
class MyDialog
{
private JDialog dialog;
private JPanel mainPanel,
panel1,
inputPanel1,
panel2,
inputPanel2;
private JLabel titleLabel,
label1,
label2;
private JCheckBox checkBox1,
checkBox2;
private JTextField textField1,
textField2;
public MyDialog(JFrame frame)
{
dialog = new JDialog(frame, true);
buildPanel();
dialog.add(mainPanel);
dialog.pack();
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
}
private void buildPanel()
{
mainPanel = new JPanel(new GridBagLayout());
titleLabel = new JLabel("Title");
checkBox1 = new JCheckBox("checkBox1");
label1 = new JLabel("label1:");
textField1 = new JTextField(15);
inputPanel1 = new JPanel(new GridBagLayout());
inputPanel1.setBorder(BorderFactory.createEmptyBorder(0, 17, 0, 0)); // indent the label and textfield
inputPanel1.add(label1, getConstraints(0, 0, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
inputPanel1.add(textField1, getConstraints(1, 0, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
panel1 = new JPanel(new GridBagLayout());
Border border1 = BorderFactory.createEtchedBorder();
panel1.setBorder(border1);
panel1.add(checkBox1, getConstraints(0, 0, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
panel1.add(inputPanel1, getConstraints(0, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
checkBox2 = new JCheckBox("checkBox2");
label2 = new JLabel("label2:");
textField2 = new JTextField(8);
inputPanel2 = new JPanel(new GridBagLayout());
inputPanel2.setBorder(BorderFactory.createEmptyBorder(0, 17, 0, 0)); // indent the label and textfield
inputPanel2.add(label2, getConstraints(0, 0, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
inputPanel2.add(textField2, getConstraints(1, 0, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
panel2 = new JPanel(new GridBagLayout());
Border border2 = BorderFactory.createEtchedBorder();
panel2.setBorder(border2);
panel2.add(checkBox2, getConstraints(0, 0, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
panel2.add(inputPanel2, getConstraints(0, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
mainPanel.add(titleLabel, getConstraints(0, 0, 2, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE));
mainPanel.add(panel1, getConstraints(0, 1, 2, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
mainPanel.add(panel2, getConstraints(0, 2, 2, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
// When I fill panel2 horizontally, the checkbox becomes misaligned with the above checkbox:
//mainPanel.add(panel2, getConstraints(0, 2, 2, 1, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL));
}
private GridBagConstraints getConstraints(int gridx, int gridy, int gridwidth, int gridheight, int anchor, int fill)
{
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.ipadx = 0;
gbc.ipady = 0;
gbc.gridx = gridx;
gbc.gridy = gridy;
gbc.gridwidth = gridwidth;
gbc.gridheight = gridheight;
gbc.anchor = anchor;
gbc.fill = fill;
return gbc;
}
}
What I did was
Make your inputPanelX have FlowLayout with FlowLayout.LEADING instead of using GirdBagLayout for them.
inputPanel1 = new JPanel(new FlowLayout(FlowLayout.LEADING));
And the scond one I just made the same Dimension as the first one
inputPanel2 = new JPanel(new FlowLayout(FlowLayout.LEADING)){
Dimension dim = new Dimension(inputPanel1.getPreferredSize());
public Dimension getPreferredSize(){
return new Dimension(dim);
}
};
That's all I changed. See full code below
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.Border;
public class Example
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable() {
public void run() {
try
{
MyFrame frame = new MyFrame();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
}
class MyFrame
{
private JFrame frame;
private MyDialog dialog;
public MyFrame()
{
frame = new JFrame();
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
dialog = new MyDialog(frame);
}
}
class MyDialog
{
private JDialog dialog;
private JPanel mainPanel,
panel1,
inputPanel1,
panel2,
inputPanel2;
private JLabel titleLabel,
label1,
label2;
private JCheckBox checkBox1,
checkBox2;
private JTextField textField1,
textField2;
public MyDialog(JFrame frame)
{
dialog = new JDialog(frame, true);
buildPanel();
dialog.add(mainPanel);
dialog.pack();
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
}
private void buildPanel()
{
mainPanel = new JPanel(new GridBagLayout());
titleLabel = new JLabel("Title");
checkBox1 = new JCheckBox("checkBox1");
label1 = new JLabel("label1:");
textField1 = new JTextField(15);
inputPanel1 = new JPanel(new FlowLayout(FlowLayout.LEADING));
inputPanel1.setBorder(BorderFactory.createEmptyBorder(0, 17, 0, 0)); // indent the label and textfield
inputPanel1.add(label1);
inputPanel1.add(textField1);
panel1 = new JPanel(new GridBagLayout());
Border border1 = BorderFactory.createEtchedBorder();
panel1.setBorder(border1);
panel1.add(checkBox1, getConstraints(0, 0, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
panel1.add(inputPanel1, getConstraints(0, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
checkBox2 = new JCheckBox("checkBox2");
label2 = new JLabel("label2:");
textField2 = new JTextField(8);
inputPanel2 = new JPanel(new FlowLayout(FlowLayout.LEADING)){
Dimension dim = new Dimension(inputPanel1.getPreferredSize());
public Dimension getPreferredSize(){
return new Dimension(dim);
}
};
inputPanel2.setBorder(BorderFactory.createEmptyBorder(0, 17, 0, 0)); // indent the label and textfield
inputPanel2.add(label2, getConstraints(0, 0, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
inputPanel2.add(textField2, getConstraints(1, 0, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
panel2 = new JPanel(new GridBagLayout());
Border border2 = BorderFactory.createEtchedBorder();
panel2.setBorder(border2);
panel2.add(checkBox2, getConstraints(0, 0, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
panel2.add(inputPanel2, getConstraints(0, 1, 1, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
mainPanel.add(titleLabel, getConstraints(0, 0, 2, 1, GridBagConstraints.CENTER, GridBagConstraints.NONE));
mainPanel.add(panel1, getConstraints(0, 1, 2, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
mainPanel.add(panel2, getConstraints(0, 2, 2, 1, GridBagConstraints.WEST, GridBagConstraints.NONE));
// When I fill panel2 horizontally, the checkbox becomes misaligned with the above checkbox:
//mainPanel.add(panel2, getConstraints(0, 2, 2, 1, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL));
}
private GridBagConstraints getConstraints(int gridx, int gridy, int gridwidth, int gridheight, int anchor, int fill)
{
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.ipadx = 0;
gbc.ipady = 0;
gbc.gridx = gridx;
gbc.gridy = gridy;
gbc.gridwidth = gridwidth;
gbc.gridheight = gridheight;
gbc.anchor = anchor;
gbc.fill = fill;
return gbc;
}
}
I have a JTextPane sandwiched between 2 JLabels - is there a known reason why the cursor shows through if i have it on the left most part of the textpane but not on the right?
Here is the code to better demonstrate what i mean:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
public class Testing {
/**
* #param args
*/
public static void main(String[] args) {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel cp = new JPanel(new BorderLayout());
f.setContentPane(cp);
final SubPanel subPanel = new SubPanel();
cp.add(subPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel(new FlowLayout());
buttonPanel.add(new JLabel("Align"));
final JComboBox alignCB = new JComboBox(new String[] {"left", "centre", "right"});
alignCB.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
subPanel.align((String) alignCB.getSelectedItem());
}
});
buttonPanel.add(alignCB);
buttonPanel.add(new JLabel("Justify"));
final JComboBox justifyCB = new JComboBox(new String[] {"left", "centre", "right"});
justifyCB.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
subPanel.justify((String) justifyCB.getSelectedItem());
}
});
buttonPanel.add(justifyCB);
JTextField tf = new JTextField("TF");
tf.setBorder(null);
buttonPanel.add(tf);
cp.add(buttonPanel, BorderLayout.NORTH);
f.pack();
f.setSize(new Dimension(300,300));
f.setLocation(300, 300);
f.setVisible(true);
}
public static class SubPanel extends JPanel {
JPanel innerPanel = new JPanel(new GridBagLayout());
TextPaneWidget[] tps = new TextPaneWidget[3];
public SubPanel() {
// setBorder(BorderFactory.createLineBorder(Color.RED));
setBorder(null);
// innerPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
innerPanel.setBorder(null);
for (int i = 0; i < tps.length; i++) {
tps[i] = new TextPaneWidget();
}
int gridy = 0;
for (TextPaneWidget tp : tps) {
innerPanel.add(tp, new GridBagConstraints(0,gridy, 1,1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0), 0, 0));
gridy++;
}
setLayout(new GridBagLayout());
add(innerPanel, new GridBagConstraints(0,0, 1,1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
}
public void align(String alignment) {
System.out.println("Align: " + alignment);
int anchor = GridBagConstraints.CENTER;
if ("right".equals(alignment)) {
anchor = GridBagConstraints.EAST;
} else if ("left".equals(alignment)) {
anchor = GridBagConstraints.WEST;
}
GridBagLayout gbl = (GridBagLayout) getLayout();
gbl.setConstraints(innerPanel, new GridBagConstraints(0,0, 1,1, 1.0, 0.0, anchor, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
revalidate();
repaint();
}
public void justify(String justification) {
System.out.println("Justify: " + justification);
for (TextPaneWidget tp : tps) {
tp.justify(justification);
}
}
}
public static class MyDocument extends DefaultStyledDocument {
#Override
public void insertString(int offset, String text, AttributeSet attributeSet) throws BadLocationException {
SimpleAttributeSet attrs = new SimpleAttributeSet(attributeSet);
StyleConstants.setForeground(attrs, Color.WHITE);
StyleConstants.setBackground(attrs, Color.RED);
super.insertString(offset, text, attrs);
}
}
public static class TextPaneWidget extends JPanel {
JTextPane tp = new JTextPane();
JLabel lSpace = new JLabel(" ");
JLabel rSpace = new JLabel(" ");
public TextPaneWidget() {
// setBorder(BorderFactory.createLineBorder(Color.GREEN));
setBorder(null);
Font font = new Font("monospaced", Font.BOLD, 13);
tp.setBorder(null);
tp.setDocument(new MyDocument());
tp.setFont(font);
tp.setText("Text");
tp.setOpaque(true);
setLayout(new GridBagLayout());
lSpace.setBackground(Color.MAGENTA);
lSpace.setOpaque(true);
lSpace.setBorder(null);
add(lSpace, new GridBagConstraints(0,0, 1,1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.VERTICAL, new Insets(0,0,0,0), 0, 0));
add(tp, new GridBagConstraints(1,0, 1,1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
rSpace.setBackground(Color.MAGENTA);
rSpace.setOpaque(true);
rSpace.setBorder(null);
add(rSpace, new GridBagConstraints(2,0, 1,1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(0,0,0,0), 0, 0));
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
tp.setCaretPosition((e.getX() < tp.getX()) ? 0 : tp.getText().length());
tp.requestFocusInWindow();
}
});
lSpace.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
tp.setCaretPosition(0);
tp.requestFocusInWindow();
}
});
rSpace.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
tp.setCaretPosition(tp.getText().length());
tp.requestFocusInWindow();
}
});
}
public void justify(String justification) {
double leftWeight = 0.5;
double rightWeight = 0.5;
if ("right".equals(justification)) {
leftWeight = 1.0;
rightWeight = 0.0;
} else if ("left".equals(justification)) {
leftWeight = 0.0;
rightWeight = 1.0;
}
GridBagLayout gbl = (GridBagLayout) getLayout();
gbl.setConstraints(lSpace, new GridBagConstraints(0,0, 1,1, leftWeight, 0.0, GridBagConstraints.EAST, GridBagConstraints.VERTICAL, new Insets(0,0,0,0), 0, 0));
gbl.setConstraints(rSpace, new GridBagConstraints(2,0, 1,1, rightWeight, 0.0, GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(0,0,0,0), 0, 0));
revalidate();
repaint();
}
}
}
I think I understand what's happening. Thanks for providing the code.
When you define a JTextPane, the default border is a 3 pixel empty border. This empty border provides a place for the text pane cursor to show when the cursor is at the rightmost position. The cursor is at the rightmost position to allow characters to be typed at the end of a line of characters.
When you define a null border, which is the same as a 0 pixel empty border, there's no place for the text pane cursor to be drawn when it's in the rightmost position.
In order to see the cursor in the rightmost position, you have to define an empty border with at least 1 right pixel. If you want it to be more visually appealing, include 1 left pixel.
tp.setBorder(BorderFactory.createEmptyBorder(0,1,0,1));
You have to define an empty border, because an empty border is the only Border that does not paint. A Border that paints will paint over the text pane cursor in the rightmost position.
So, you are required to use an empty border with at least one right pixel for a JTextPane to display the rightmost cursor.
Edited to add:
When you're using the GridBagLayout, a method like this one reduces the number of parameters that you have to deal with when you add a component.
protected void addComponent(Container container, Component component,
int gridx, int gridy, int gridwidth, int gridheight,
Insets insets, int anchor, int fill) {
GridBagConstraints gbc = new GridBagConstraints(gridx, gridy,
gridwidth, gridheight, 1.0D, 1.0D, anchor, fill, insets, 0, 0);
container.add(component, gbc);
}
Setting the background to the following fixes this...
tp.setBackground(Color.RED);
tp.setOpaque(true);
I've created a few GUI applications in Java before, and every time I'm really just messing around until the thing does what I want it to do, using snippits from several GUI examples I find on the web. Recently I read some more about good practices when writing a GUI in Java using Swing, but still some things are unclear to me. Let me first describe what I want to do in my next project so that we can use that as an example:
I'd like to create an executable application that gives a user the ability to load images, perform some actions on these images and save the project. There should be a main image viewer at the core with a simple navigator below it to switch between the loaded images. There should be panels with buttons that perform operations on an image (for example a button 'pick background color from image') and these operations should optionally be accessible from a toolbar or a menu.
I know that for example the GUI should be started from the Event Dispatch Thread and that I can use a SwingWorker for timeconsuming operations. Also I learned that by using Actions I can separate functionality from state and create one Action for both a panel button, a toolbar button and a menu item.
What I don't understand is how all these things communicate with each other, and where I put what. For example: do I maintain the state of my program (so which image is currently displayed, what settings are set) in a separate model and put a reference to this model in my main window class? And what about the controllers? Do I keep a reference to the models in the controllers are well? And when I did some calculation on an image, do I update the image in the gui from the controller, or from the gui itself using a simple repaint?
I guess the main problem I have is that I don't really understand how to let the different parts of my program communicate. A GUI consists of lots of parts, and then there are all these Actions and Listeners, models, controllers, and all of these need to interact somehow. I keep adding references to almost everything in all of these objects, but it makes everything extremely messy.
Another example I found on the web:
http://www.devdaily.com/java/java-action-abstractaction-actionlistener
I understand how this works, what I don't understand is how to actually change the "Would have done the 'Cut' action." into the actual cut action. Let's say it involves cutting a part out of my image in the viewer, would I have passed the image to the action? And if this process would take long, would I have created a new SwingWorker inside the action? And then how would I let the SwingWorker update the GUI while calculating? Would I pass a reference of the GUI to the SwingWorker such that it can update it from time to time?
Does anyone have a good example on how to do this or maybe some tips on how to correctly learn this, because I'm at a bit of a loss. There's just so much information and so many different ways to do things, and I really want to learn how to create scalable applications with clean code. Is there maybe a good open-source project with not too much code that very nicely demonstrates a GUI like what I described so that I can learn from that?
I've built a few Swing and SWT GUI's. What I've found is that a GUI requires its own model - view (MV) structure. The application controller interacts with the GUI model, rather than the GUI components.
Basically, I build a Java bean for every Swing JPanel in my GUI. The GUI components interact with the Java bean, and the application controller interacts with the Java bean(s).
Here's a Spirograph GUI that I created.
Here's the Java bean that manages the Spirograph parameters.
import java.awt.Color;
public class ControlModel {
protected boolean isAnimated;
protected int jpanelWidth;
protected int outerCircle;
protected int innerCircle;
protected int penLocation;
protected int penSize;
protected Color penColor;
protected Color backgroundColor;
public ControlModel() {
init();
this.penColor = Color.BLUE;
this.backgroundColor = Color.WHITE;
}
public void init() {
this.jpanelWidth = 512;
this.outerCircle = 1000;
this.innerCircle = 520;
this.penLocation = 400;
this.penSize = 2;
this.isAnimated = true;
}
public int getOuterCircle() {
return outerCircle;
}
public void setOuterCircle(int outerCircle) {
this.outerCircle = outerCircle;
}
public int getInnerCircle() {
return innerCircle;
}
public void setInnerCircle(int innerCircle) {
this.innerCircle = innerCircle;
}
public int getPenLocation() {
return penLocation;
}
public void setPenLocation(int penLocation) {
this.penLocation = penLocation;
}
public int getPenSize() {
return penSize;
}
public void setPenSize(int penSize) {
this.penSize = penSize;
}
public boolean isAnimated() {
return isAnimated;
}
public void setAnimated(boolean isAnimated) {
this.isAnimated = isAnimated;
}
public Color getPenColor() {
return penColor;
}
public void setPenColor(Color penColor) {
this.penColor = penColor;
}
public Color getBackgroundColor() {
return backgroundColor;
}
public void setBackgroundColor(Color backgroundColor) {
this.backgroundColor = backgroundColor;
}
public int getJpanelWidth() {
return jpanelWidth;
}
public int getJpanelHeight() {
return jpanelWidth;
}
}
Edited to add the Control Panel class.
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;
import com.ggl.spirograph.model.ControlModel;
public class ControlPanel {
protected static final Insets entryInsets = new Insets(0, 10, 4, 10);
protected static final Insets titleInsets = new Insets(0, 10, 20, 10);
protected ControlModel model;
protected DrawingPanel drawingPanel;
protected JButton drawButton;
protected JButton stopButton;
protected JButton resetButton;
protected JButton foregroundColorButton;
protected JButton backgroundColorButton;
protected JLabel message;
protected JPanel panel;
protected JTextField outerCircleField;
protected JTextField innerCircleField;
protected JTextField penLocationField;
protected JTextField penSizeField;
protected JTextField penFadeField;
protected JToggleButton animationToggleButton;
protected JToggleButton fastToggleButton;
protected static final int messageLength = 100;
protected String blankMessage;
public ControlPanel(ControlModel model) {
this.model = model;
this.blankMessage = createBlankMessage();
createPartControl();
setFieldValues();
setColorValues();
}
public void setDrawingPanel(DrawingPanel drawingPanel) {
this.drawingPanel = drawingPanel;
}
protected String createBlankMessage() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < messageLength / 4; i++) {
sb.append(" ");
}
return sb.toString();
}
protected void createPartControl() {
panel = new JPanel();
panel.setLayout(new GridBagLayout());
int gridy = 0;
JLabel title = new JLabel("Spirograph Parameters");
title.setHorizontalAlignment(SwingConstants.CENTER);
addComponent(panel, title, 0, gridy++, 4, 1, titleInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
resetButton = new JButton("Reset Default Parameters");
resetButton.setHorizontalAlignment(SwingConstants.CENTER);
resetButton.addActionListener(new ResetButtonListener());
addComponent(panel, resetButton, 0, gridy++, 4, 1, entryInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
JLabel outerCircleLabel = new JLabel("Outer circle radius:");
outerCircleLabel.setHorizontalAlignment(SwingConstants.LEFT);
addComponent(panel, outerCircleLabel, 0, gridy, 2, 1, entryInsets,
GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);
outerCircleField = new JTextField(5);
outerCircleField.setHorizontalAlignment(SwingConstants.LEFT);
addComponent(panel, outerCircleField, 2, gridy++, 2, 1, entryInsets,
GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);
JLabel innerCircleLabel = new JLabel("Inner circle radius:");
innerCircleLabel.setHorizontalAlignment(SwingConstants.LEFT);
addComponent(panel, innerCircleLabel, 0, gridy, 2, 1, entryInsets,
GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);
innerCircleField = new JTextField(5);
innerCircleField.setHorizontalAlignment(SwingConstants.LEFT);
addComponent(panel, innerCircleField, 2, gridy++, 2, 1, entryInsets,
GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);
JLabel penLocationLabel = new JLabel("Pen location radius:");
penLocationLabel.setHorizontalAlignment(SwingConstants.LEFT);
addComponent(panel, penLocationLabel, 0, gridy, 2, 1, entryInsets,
GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);
penLocationField = new JTextField(5);
penLocationField.setHorizontalAlignment(SwingConstants.LEFT);
addComponent(panel, penLocationField, 2, gridy++, 2, 1, entryInsets,
GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);
JLabel penSizeLabel = new JLabel("Pen size:");
penSizeLabel.setHorizontalAlignment(SwingConstants.LEFT);
addComponent(panel, penSizeLabel, 0, gridy, 2, 1, entryInsets,
GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);
penSizeField = new JTextField(5);
penSizeField.setHorizontalAlignment(SwingConstants.LEFT);
addComponent(panel, penSizeField, 2, gridy++, 2, 1, entryInsets,
GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);
message = new JLabel(blankMessage);
message.setForeground(Color.RED);
message.setHorizontalAlignment(SwingConstants.LEFT);
addComponent(panel, message, 0, gridy++, 4, 1, titleInsets,
GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);
title = new JLabel("Drawing Speed");
title.setHorizontalAlignment(SwingConstants.CENTER);
addComponent(panel, title, 0, gridy++, 4, 1, titleInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 4, 0));
animationToggleButton = new JToggleButton("Animated");
animationToggleButton.setSelected(model.isAnimated());
animationToggleButton.setHorizontalAlignment(SwingConstants.CENTER);
animationToggleButton.addActionListener(new DrawingSpeedListener(
animationToggleButton));
buttonPanel.add(animationToggleButton);
fastToggleButton = new JToggleButton("Fast");
fastToggleButton.setSelected(!model.isAnimated());
fastToggleButton.setHorizontalAlignment(SwingConstants.CENTER);
fastToggleButton.addActionListener(new DrawingSpeedListener(
fastToggleButton));
buttonPanel.add(fastToggleButton);
addComponent(panel, buttonPanel, 0, gridy++, 4, 1, titleInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
title = new JLabel("Drawing Colors");
title.setHorizontalAlignment(SwingConstants.CENTER);
addComponent(panel, title, 0, gridy++, 4, 1, titleInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
buttonPanel = new JPanel(new GridLayout(1, 2, 4, 0));
foregroundColorButton = new JButton("Pen");
foregroundColorButton.setHorizontalAlignment(SwingConstants.CENTER);
foregroundColorButton.addActionListener(new ColorSelectListener(
foregroundColorButton));
buttonPanel.add(foregroundColorButton);
backgroundColorButton = new JButton("Paper");
backgroundColorButton.setHorizontalAlignment(SwingConstants.CENTER);
backgroundColorButton.addActionListener(new ColorSelectListener(
backgroundColorButton));
buttonPanel.add(backgroundColorButton);
addComponent(panel, buttonPanel, 0, gridy++, 4, 1, titleInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
title = new JLabel("Drawing Controls");
title.setHorizontalAlignment(SwingConstants.CENTER);
addComponent(panel, title, 0, gridy++, 4, 1, titleInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
buttonPanel = new JPanel(new GridLayout(1, 2, 4, 0));
drawButton = new JButton("Draw");
drawButton.setHorizontalAlignment(SwingConstants.CENTER);
drawButton.addActionListener(new DrawButtonListener());
buttonPanel.add(drawButton);
stopButton = new JButton("Stop");
stopButton.setHorizontalAlignment(SwingConstants.CENTER);
stopButton.addActionListener(new StopButtonListener());
buttonPanel.add(stopButton);
addComponent(panel, buttonPanel, 0, gridy++, 4, 1, titleInsets,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
}
protected void addComponent(Container container, Component component,
int gridx, int gridy, int gridwidth, int gridheight,
Insets insets, int anchor, int fill) {
GridBagConstraints gbc = new GridBagConstraints(gridx, gridy,
gridwidth, gridheight, 1.0, 1.0, anchor, fill, insets, 0, 0);
container.add(component, gbc);
}
protected void setFieldValues() {
outerCircleField.setText(Integer.toString(model.getOuterCircle()));
innerCircleField.setText(Integer.toString(model.getInnerCircle()));
penLocationField.setText(Integer.toString(model.getPenLocation()));
penSizeField.setText(Integer.toString(model.getPenSize()));
}
protected void setColorValues() {
foregroundColorButton.setForeground(model.getBackgroundColor());
foregroundColorButton.setBackground(model.getPenColor());
backgroundColorButton.setForeground(model.getPenColor());
backgroundColorButton.setBackground(model.getBackgroundColor());
}
public JPanel getPanel() {
return panel;
}
public class ResetButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
model.init();
setFieldValues();
}
}
public class StopButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent arg0) {
drawingPanel.stop();
}
}
public class DrawButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
message.setText(blankMessage);
int ocTest = isNumeric(outerCircleField.getText());
int icTest = isNumeric(innerCircleField.getText());
int plTest = isNumeric(penLocationField.getText());
int psTest = isNumeric(penSizeField.getText());
boolean isInvalid = false;
if (psTest < 0) {
message.setText("Pen size is not a valid integer");
isInvalid = true;
}
if (plTest < 0) {
message.setText("Pen location radius is not a valid integer");
isInvalid = true;
}
if (icTest < 0) {
message.setText("Inner circle radius is not a valid integer");
isInvalid = true;
}
if (ocTest < 0) {
message.setText("Outer circle radius is not a valid integer");
isInvalid = true;
}
if (isInvalid) {
return;
}
if (ocTest > 1000) {
message.setText("The outer circle cannot be larger than 1000");
isInvalid = true;
}
if (ocTest <= icTest) {
message.setText("The inner circle must be smaller than the outer circle");
isInvalid = true;
}
if (icTest <= plTest) {
message.setText("The pen location must be smaller than the inner circle");
isInvalid = true;
}
if (isInvalid) {
return;
}
model.setOuterCircle(ocTest);
model.setInnerCircle(icTest);
model.setPenLocation(plTest);
model.setPenSize(psTest);
drawingPanel.draw(model.isAnimated());
}
protected int isNumeric(String field) {
try {
return Integer.parseInt(field);
} catch (NumberFormatException e) {
return Integer.MIN_VALUE;
}
}
}
public class DrawingSpeedListener implements ActionListener {
JToggleButton selectedButton;
public DrawingSpeedListener(JToggleButton selectedButton) {
this.selectedButton = selectedButton;
}
#Override
public void actionPerformed(ActionEvent arg0) {
if (selectedButton.equals(animationToggleButton)) {
model.setAnimated(true);
} else {
model.setAnimated(false);
}
animationToggleButton.setSelected(model.isAnimated());
fastToggleButton.setSelected(!model.isAnimated());
}
}
public class ColorSelectListener implements ActionListener {
JButton selectedButton;
public ColorSelectListener(JButton selectedButton) {
this.selectedButton = selectedButton;
}
#Override
public void actionPerformed(ActionEvent arg0) {
if (selectedButton.equals(foregroundColorButton)) {
Color initialColor = model.getPenColor();
Color selectedColor = JColorChooser.showDialog(drawingPanel,
"Select pen color", initialColor);
if (selectedColor != null) {
model.setPenColor(selectedColor);
}
} else if (selectedButton.equals(backgroundColorButton)) {
Color initialColor = model.getBackgroundColor();
Color selectedColor = JColorChooser.showDialog(drawingPanel,
"Select paper color", initialColor);
if (selectedColor != null) {
model.setBackgroundColor(selectedColor);
}
}
setColorValues();
}
}
}
I am developing the logic to build a good password strength checker for my login form,but the problem is how to express strength of password entered ? I am using java and I am using this approach:
using JProgressBar as strength meter,it changes color when focus from JPasswordField is lost or when a key is released in JPasswordField (this gives quicker response).
Can I use Swing Worker on this to make it better ? I have never used it so can anybody help me with that if it is best way.
Please forgive me for long sentences.
See Image below:
no SwingWorker doesn't make me sence in this case, that's just and about DocumentListener
NOTICE: this example not about How to check password strenght, just how to listening for changes from JPasswordField and redirect output to the JProgressBar
import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class TextLabelMirror {
private JPanel mainPanel = new JPanel();
private JPasswordField field = new JPasswordField(20);
private JLabel label = new JLabel();
private JLabel labelLength = new JLabel();
private JProgressBar progressBar = new JProgressBar(0, 20);
public TextLabelMirror() {
field.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void changedUpdate(DocumentEvent e) {
updateLabel(e);
}
#Override
public void insertUpdate(DocumentEvent e) {
updateLabel(e);
}
#Override
public void removeUpdate(DocumentEvent e) {
updateLabel(e);
}
private void updateLabel(DocumentEvent e) {
String text = field.getText();//just example getText() is Depreciated !!!
label.setText(text);
labelLength.setText(" Psw Lenght -> " + text.length());
if (text.length() < 1) {
progressBar.setValue(0);
} else {
progressBar.setValue(text.length());
}
}
});
mainPanel.setLayout(new GridLayout(4, 0, 10, 0));
mainPanel.add(field);
mainPanel.add(label);
mainPanel.add(labelLength);
mainPanel.add(progressBar);
}
public JComponent getComponent() {
return mainPanel;
}
private static void createAndShowUI() {
JFrame frame = new JFrame("Password Strength Checker");
frame.getContentPane().add(new TextLabelMirror().getComponent());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowUI();
}
});
}
}
Same idea as mKorbel, but with color:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PasswordChecker extends JPanel {
private static final Color[] PB_COLORS = {Color.red, Color.yellow, Color.green};
private static final int MAX_LENGTH = 15;
private JPasswordField pwField1 = new JPasswordField(10);
private JPasswordField pwField2 = new JPasswordField(10);
private JProgressBar progBar = new JProgressBar();
private int ins = 10;
public PasswordChecker() {
pwField1.addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent e) {
pwField1FocusLost(e);
}
});
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1.0, 10,
GridBagConstraints.WEST, GridBagConstraints.BOTH,
new Insets(ins, ins, ins, ins), 0, 0);
add(new JLabel("Password"), gbc);
gbc = new GridBagConstraints(1, 0, 1, 1, 1.0, 10,
GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL,
new Insets(ins, ins, ins, ins), 0, 0);
add(pwField1, gbc);
gbc = new GridBagConstraints(0, 1, 1, 1, 1.0, 10,
GridBagConstraints.WEST, GridBagConstraints.BOTH,
new Insets(ins, ins, ins, ins), 0, 0);
add(new JLabel("Confirm Password"), gbc);
gbc = new GridBagConstraints(1, 1, 1, 1, 1.0, 10,
GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL,
new Insets(ins, ins, ins, ins), 0, 0);
add(pwField2, gbc);
gbc = new GridBagConstraints(0, 2, 1, 1, 1.0, 10,
GridBagConstraints.WEST, GridBagConstraints.BOTH,
new Insets(ins, ins, ins, ins), 0, 0);
add(new JLabel("Strength"), gbc);
gbc = new GridBagConstraints(1, 2, 1, 1, 1.0, 10,
GridBagConstraints.EAST, GridBagConstraints.BOTH,
new Insets(ins, ins, ins, ins), 0, 0);
add(progBar, gbc);
}
private void pwField1FocusLost(FocusEvent e) {
// simple check, just checks length
char[] pw = pwField1.getPassword();
int value = (pw.length * 100) / MAX_LENGTH;
value = (value > 100) ? 100 : value;
progBar.setValue(value);
int colorIndex = (PB_COLORS.length * value) / 100;
progBar.setForeground(PB_COLORS[colorIndex]);
}
private static void createAndShowUI() {
JFrame frame = new JFrame("Password Checker");
frame.getContentPane().add(new PasswordChecker());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}