1

I am still really new to Java, and coding as a whole so please excuse my newby question.

I am trying to make a calendar, except rather than have in a normal 6 x 7 layout etc. I want it in month view displayed horizontally.

This is what I have so far. I have tried changing the column and rows as well as the frame width but I then cant get the pane to disply properly in horizintal fashion.

Any help appreciated.

package Calendar_Test;

/*Contents of CalendarProgran.class */
//Import packages
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;

public class Test_Code {

    static JLabel lblMonth, lblYear;
    static JButton btnPrev, btnNext;
    static JTable tblCalendar;
    static JComboBox<String> cmbYear;
    static JFrame frmMain;
    static Container pane;
    static DefaultTableModel mtblCalendar; //Table model  
    static JScrollPane stblCalendar; //The scrollpane  
    static JPanel pnlCalendar;
    static int realYear, realMonth, realDay, currentYear, currentMonth;

    public static void main(String args[]) {
        //Look and feel  
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException e) {
        } catch (InstantiationException e) {
        } catch (IllegalAccessException e) {
        } catch (UnsupportedLookAndFeelException e) {
        }

        //Prepare frame  
        frmMain = new JFrame("Key Dates Timeline"); //Create frame  
        frmMain.setSize(330, 375); //Set size to 400x400 pixels  
        pane = frmMain.getContentPane(); //Get content pane  
        pane.setLayout(null); //Apply null layout  
        frmMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Close when X is clicked  

        //Create controls  
        lblMonth = new JLabel("January");
        lblYear = new JLabel("Change year:");
        cmbYear = new JComboBox<String>();
        btnPrev = new JButton("<<");
        btnNext = new JButton(">>");
        mtblCalendar = new DefaultTableModel() {

            /**
            *
            */
            private static final long serialVersionUID = 1L;

            public boolean isCellEditable(int rowIndex, int mColIndex) {
                return false;
            }
        };
        tblCalendar = new JTable(mtblCalendar);
        stblCalendar = new JScrollPane(tblCalendar);
        pnlCalendar = new JPanel(null);

        //Set border  
        pnlCalendar.setBorder(BorderFactory.createTitledBorder("Calendar"));

        //Register action listeners  
        btnPrev.addActionListener(new btnPrev_Action());
        btnNext.addActionListener(new btnNext_Action());
        cmbYear.addActionListener(new cmbYear_Action());

        //Add controls to pane  
        pane.add(pnlCalendar);
        pnlCalendar.add(lblMonth);
        pnlCalendar.add(lblYear);
        pnlCalendar.add(cmbYear);
        pnlCalendar.add(btnPrev);
        pnlCalendar.add(btnNext);
        pnlCalendar.add(stblCalendar);

        //Set bounds  
        pnlCalendar.setBounds(0, 0, 320, 335);
        lblMonth.setBounds(160 - lblMonth.getPreferredSize().width / 2, 25, 100, 25);
        lblYear.setBounds(10, 305, 80, 20);
        cmbYear.setBounds(230, 305, 80, 20);
        btnPrev.setBounds(10, 25, 50, 25);
        btnNext.setBounds(260, 25, 50, 25);
        stblCalendar.setBounds(10, 50, 300, 250);

        //Make frame visible  
        frmMain.setResizable(false);
        frmMain.setVisible(true);

        //Get real month/year  
        GregorianCalendar cal = new GregorianCalendar(); //Create calendar  
        realDay = cal.get(GregorianCalendar.DAY_OF_MONTH); //Get day  
        realMonth = cal.get(GregorianCalendar.MONTH); //Get month  
        realYear = cal.get(GregorianCalendar.YEAR); //Get year  
        currentMonth = realMonth; //Match month and year  
        currentYear = realYear;

        //Add headers  
        String[] headers = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; //All headers  
        for (int i = 0; i < 7; i++) {
            mtblCalendar.addColumn(headers[i]);
        }

        tblCalendar.getParent().setBackground(tblCalendar.getBackground()); //Set background  

        //No resize/reorder  
        tblCalendar.getTableHeader().setResizingAllowed(false);
        tblCalendar.getTableHeader().setReorderingAllowed(false);

        //Single cell selection  
        tblCalendar.setColumnSelectionAllowed(true);
        tblCalendar.setRowSelectionAllowed(true);
        tblCalendar.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        //Set row/column count  
        tblCalendar.setRowHeight(38);
        mtblCalendar.setColumnCount(7);
        mtblCalendar.setRowCount(6);

        //Populate table  
        for (int i = realYear - 100; i <= realYear + 100; i++) {
            cmbYear.addItem(String.valueOf(i));
        }

        //Refresh calendar  
        refreshCalendar(realMonth, realYear); //Refresh calendar  
    }

    public static void refreshCalendar(int month, int year) {
        //Variables  
        String[] months = {
            "January", "February", "March", "April", "May", "June", "July",
            "August", "September", "October", "November", "December"};
        int nod, som; //Number Of Days, Start Of Month  

        //Allow/disallow buttons  
        btnPrev.setEnabled(true);
        btnNext.setEnabled(true);
        if (month == 0 && year <= realYear - 10) {
            btnPrev.setEnabled(false);
        } //Too early  
        if (month == 11 && year >= realYear + 100) {
            btnNext.setEnabled(false);
        } //Too late  
        lblMonth.setText(months[month]); //Refresh the month label (at the top)  
        lblMonth.setBounds(160 - lblMonth.getPreferredSize().width / 2, 25, 180, 25); //Re-align label with calendar  
        cmbYear.setSelectedItem(String.valueOf(year)); //Select the correct year in the combo box  

        //Clear table  
        for (int i = 0; i < 6; i++) {
            for (int j = 0; j < 7; j++) {
                mtblCalendar.setValueAt(null, i, j);
            }
        }

        //Get first day of month and number of days  
        GregorianCalendar cal = new GregorianCalendar(year, month, 1);
        nod = cal.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);
        som = cal.get(GregorianCalendar.DAY_OF_WEEK);

        //Draw calendar  
        for (int i = 1; i <= nod; i++) {
            int row = new Integer((i + som - 2) / 7);
            int column = (i + som - 2) % 7;
            mtblCalendar.setValueAt(i, row, column);
        }

        //Apply renderers  
        tblCalendar.setDefaultRenderer(tblCalendar.getColumnClass(0), new tblCalendarRenderer());
    }

    static class tblCalendarRenderer extends DefaultTableCellRenderer {

        /**
        *
        */
        private static final long serialVersionUID = 1L;

        public Component getTableCellRendererComponent(JTable table, Object
            value, boolean selected, boolean focused, int row, int column) {
            super.getTableCellRendererComponent(
                table, value, selected, focused, row, column);
            if (column == 0 || column == 6) { //Week-end  
                setBackground(new Color(255, 220, 220));
            } else { //Week  
                setBackground(new Color(255, 255, 255));
            }
            if (value != null) {
                if (Integer.parseInt(value.toString()) == realDay
                    && currentMonth == realMonth && currentYear == realYear) { //Today  
                    setBackground(new Color(220, 220, 255));
                }
            }
            setBorder(null);
            setForeground(Color.black);
            return this;
        }
    }

    static class btnPrev_Action implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            if (currentMonth == 0) { //Back one year  
                currentMonth = 11;
                currentYear -= 1;
            } else { //Back one month  
                currentMonth -= 1;
            }
            refreshCalendar(currentMonth, currentYear);
        }
    }

    static class btnNext_Action implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            if (currentMonth == 11) { //Foward one year  
                currentMonth = 0;
                currentYear += 1;
            } else { //Foward one month  
                currentMonth += 1;
            }
            refreshCalendar(currentMonth, currentYear);
        }
    }

    static class cmbYear_Action implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            if (cmbYear.getSelectedItem() != null) {
                String b = cmbYear.getSelectedItem().toString();
                currentYear = Integer.parseInt(b);
                refreshCalendar(currentMonth, currentYear);
            }
        }
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
Eagle Eye
  • 47
  • 1
  • 5

2 Answers2

1

If you used a 4x3 GridLayout (one line per quarter of year) with each cell containing a nested 6x7 GridLayout(to hold the values of the days/month title I think it would work much better. You could even go as far as nesting these both inside some other container to hold your buttons and whatnot.

As MadProgrammer pointed out if you use a null layout and change the font, frame size, etc things are going to go wonky, quick.

Jared Beekman
  • 320
  • 2
  • 10
1

Your requirements are pretty basic. Given the fact that you're already using a JTable you simply need to supply a new TableModel to the view....

Now, this MASSIVELY simple, but the concept should get you started...

public class CalendarTableModel extends AbstractTableModel {

    private Calendar cal;

    public CalendarTableModel() {
        this(new Date());
    }

    public CalendarTableModel(Date date) {
        setMonthByDate(date);
    }

    public void setMonthByDate(Date date) {

        cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, 1);

        fireTableStructureChanged();

    }

    @Override
    public String getColumnName(int column) {

        String name = null;

        if (cal != null) {

            Calendar tmp = Calendar.getInstance();
            tmp.setTime(cal.getTime());
            tmp.set(Calendar.DAY_OF_MONTH, column + 1);

            int date = tmp.get(Calendar.DAY_OF_MONTH);
            int dow = tmp.get(Calendar.DAY_OF_WEEK);

            switch (dow) {

                case Calendar.MONDAY:
                    name = "Mon";
                    break;
                case Calendar.TUESDAY:
                    name = "Tue";
                    break;
                case Calendar.WEDNESDAY:
                    name = "Wed";
                    break;
                case Calendar.THURSDAY:
                    name = "Thr";
                    break;
                case Calendar.FRIDAY:
                    name = "Fri";
                    break;
                case Calendar.SATURDAY:
                    name = "Sat";
                    break;
                case Calendar.SUNDAY:
                    name = "Sun";
                    break;

            }

            name += " " + date;

        }

        return name;

    }

    @Override
    public int getRowCount() {
        return 10;
    }

    @Override
    public int getColumnCount() {

        return cal == null ? 0 : cal.getMaximum(Calendar.DAY_OF_MONTH);

    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {

        return null;

    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Hi MadProgrammer, Thanks for the code sample, much appreciated. So you are saying that this code needs to be included in the section of my code that handles the look and feel? Cheers. – Eagle Eye Jan 25 '13 at 00:39