sethu
sethu

Reputation: 8431

java swing DatePicker done wrong using a JTextField and want to change

I had initially built a DatePicker. A Calendar Dialog will open next to a JTextField as soon as a person clicks on the JtextField. If a person wants to type the date instead of selecting the date, then he would have first close the open dialog and then type the date.

Here's how it looks:

public class DateTextField extends JTextField implements Observer {

public void update(Observable o, Object arg) {
    Calendar calendar = (Calendar) arg;
    DatePicker dp = (DatePicker) o;
    setText(dp.formatDate(calendar));
}

public DateTextField() {
    final Observer obs = this;
    final JTextField tf = this;
    this.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseReleased(MouseEvent e) {
            if(tf.isEditable()){
                DatePicker dp = new DatePicker(obs);
                Date selectedDate = dp.parseDate(tf.getText());
                dp.setSelectedDate(selectedDate);
                dp.start(tf);
            }
        }
    });
}

I havent shown the DatePicker class because that's not the issue here. The issue is, it was very irritating for a person to close the Calendar dialog everytime to type the date. Instead what I wanted to do was keep a button on the side of the JtextField and only if the person clicks on the button would the dialog pop up.

But to do that I would need the DatePicker to extend a JPanel class and I could layout the JTextfield and the JButton side by side. But unfortunately, the DatePicker class extends JtextField and all over my application I am expecting DatePicker to be a JtextField. There are casts from JComponent to JTextfield and calls to get and setText() on this DatePicker.

If I have to change DatePicker to extend form JPanel then it would break my application everywhere. I was wondering if I can somehow dress up the JTextfield to show the button on the side maybe by painting it or something? Is this is possible?

Upvotes: 0

Views: 2256

Answers (3)

sethu
sethu

Reputation: 8431

For anyone wanting to see how later on.. the code is listed below. You override paint and draw the image on the left hand corner of the text field. Then implement the mouseClicked to only response if the image has been clicked. Also implement a mouse motion listener to change the cursor to a hand pointer if its on the image and a text cursor if it is not.

public class DateTextField extends JTextField implements Observer {

public void update(Observable o, Object arg) {
    Calendar calendar = (Calendar) arg;
    DatePicker dp = (DatePicker) o;
    setText(dp.formatDate(calendar));
}

public DateTextField() {
    final Observer obs = this;
    final JTextField tf = this;
    this.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            if(tf.isEditable()){
                Point p = e.getPoint();
                if(p.x>=getWidth()-22 && p.x <getWidth()
                        && p.y<=getHeight()) {
                    DatePicker dp = new DatePicker(obs);
                    Date selectedDate = dp.parseDate(tf.getText());
                    dp.setSelectedDate(selectedDate);
                    dp.start(tf);
                }
            }
        }
    });

    this.addMouseMotionListener(new MouseMotionAdapter() {
        @Override
        public void mouseMoved(MouseEvent e) {
            Point p = e.getPoint();
            if(p.x>=getWidth()-22 && p.x <getWidth()
                    && p.y<=getHeight()) {
                DateTextField.this.setCursor(new Cursor(Cursor.HAND_CURSOR));
            }else {
                DateTextField.this.setCursor(new Cursor(Cursor.TEXT_CURSOR));
            }
        }
    });
}

public DateTextField(String text) {
    this();
    this.setText(text);
}

@Override
public void paint(Graphics g) {
    super.paint(g);
    try {
        BufferedImage img = ImageIO.read(new File(DateTextField.class.getResource("/images/calendar.png").getFile()));
        int x=getWidth()-22;
        g.drawImage(img,x,1,20,getHeight()-2,null);
    }catch (IOException e) {
        e.printStackTrace();
    }
}
}

Upvotes: 0

mKorbel
mKorbel

Reputation: 109823

1) public class DateTextField extends JSpinner implements Observer {

2) JSpinner with SpinnerDateModel, then there no issue with parsing from/to another instance

3) use JWindow for popup, there place 7x7 JLabels or JButtons

Upvotes: 1

Ostap Andrusiv
Ostap Andrusiv

Reputation: 4907

I guess, you should override paintComponent method and change MouseListener a bit. Something like this:

    protected void paintComponent(Graphics g) {  
        super.paintComponent(g);  
        int y = (getHeight() - image.getHeight())/2;  
        g.drawImage(image, x, y, this);  
    }  

and somehow track e.getX() e.getY() coordiantes of the event in your MouseListener.

Upvotes: 1

Related Questions