为什么这个JTable在重新涂漆时减少了一半?

时间:2012-09-27 15:58:36

标签: java swing jtable

请帮我调试代码。我正在使用JTable创建日历,但每当我按下一个或上一个按钮时,日历都不会正确重新绘制。它被“切成两半”,然后另一个按下它就消失了。我尝试过不同的方法来解决这个问题,但我真的不知道。

以下是代码:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.util.*;
import java.lang.*;

public class NewCalendar extends JFrame
{
    private JFrame frame = new JFrame();
    private Object[] colNames = {"Sun","Mon","Tue","Wed","Thurs","Fri","Sat"};
    private Object[][] days = new Object[6][7];

    private JLabel lblMonth, lblYear;
    private JButton btnPrev, btnNext, pinBoard, addEntry;
    private Container pane;
    private JPanel pnlCalendar;
    private JComboBox cmbYear;
    private int realYear, realMonth, realDay, currYear, currMonth;
    GregorianCalendar calx = new GregorianCalendar();
    GregorianCalendar cal;
    JScrollPane scroll;
    JTable table;
    TableModel model;
    int row;
    int column;

    public NewCalendar()
    {
        realDay = calx.get(GregorianCalendar.DAY_OF_MONTH);
        realMonth = calx.get(GregorianCalendar.MONTH);
        realYear = calx.get(GregorianCalendar.YEAR);

        //cal = new GregorianCalendar(2012, 10, 27);
        //cal = new GregorianCalendar(realYear, 9, realDay);
        cal = new GregorianCalendar(realYear, realMonth+1, realDay);

        GregorianCalendar cald = new GregorianCalendar(realYear, realMonth, realDay);

        int nod = cald.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);
        int som = cal.get(GregorianCalendar.DAY_OF_WEEK);


        System.out.println(realYear + " " + realMonth + " " + realDay);
        currYear = realYear;
        currMonth = realMonth;
        for( int i=1; i<=nod; i++ )
        {
            row = new Integer((i+som-2)/7);
            column = (i+som-2)%7;
            days[row][column] = new Integer(i);
        }
        TableModel model = new DefaultTableModel(days, colNames)
        {
            private static final long serialVersionUID = 1L;
            public boolean isCellEditable(int row, int column)
            {
                return days[row][column] != null;
            }
        };

        table = new JTable(model);
        table.setRowHeight(38);
        table.setColumnSelectionAllowed(true);
        table.setRowSelectionAllowed(true);
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        for(int i=0; i<7; i++)
        {
            table.getColumnModel().getColumn(i).setCellEditor(new ClientsTableRenderer(new JCheckBox()));
        }

        table.getTableHeader().setReorderingAllowed(false);

        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        table.setShowHorizontalLines(true);
        table.setShowVerticalLines(true);

        scroll = new JScrollPane(table);
        /*frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout( new BorderLayout() );
        frame.pack();
        frame.add(scroll);
        frame.setLocation(150,150);
        frame.setVisible(true);
        frame.setSize(325,450);
        frame.setResizable(false);*/

        this.setTitle("Calendar");
        this.setSize(325,450);
        pane = this.getContentPane();
        pane.setLayout(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
        this.setResizable(false);


        //create controls
        lblMonth = new JLabel("January");
        lblYear = new JLabel("Change year: ");
        cmbYear = new JComboBox();
        btnPrev = new JButton("<<");
        btnNext = new JButton(">>");
        pinBoard = new JButton("Go to Pin Board");
        addEntry = new JButton("Add Entry");
        pnlCalendar = new JPanel(null);

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

        //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(scroll);
        pnlCalendar.add(lblMonth);
        pnlCalendar.add(lblYear);
        pnlCalendar.add(cmbYear);
        pnlCalendar.add(btnPrev);
        pnlCalendar.add(btnNext);
        pnlCalendar.add(pinBoard);
        pnlCalendar.add(addEntry);


        //set bounds
        pnlCalendar.setBounds(0,0,500,500);
        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);
        pinBoard.setBounds(10,340,300,25);
        addEntry.setBounds(10,380, 300, 25);
        scroll.setBounds(10,50,300,250);
        refreshCalendar( currMonth, currYear); //refresh calendar
    }

    public void refreshCalendar( int month, int year )
    {
        String[] months = {"January","February","March","April","May","June","July","August","September","October","November","December"};
        int nod, som; //number of days, start of month
        btnPrev.setEnabled(true);
        btnNext.setEnabled(true);
        days = new Object[6][7];
        if( month == 0 && year <= realYear-100)
            btnPrev.setEnabled(false);
        if( month == 11 && year >= realYear+100 )
            btnNext.setEnabled(false);
        lblMonth.setText(months[month]); //refresh month label
        lblMonth.setBounds(160-lblMonth.getPreferredSize().width/2, 25,180,25); //re-align label with calendar
        cmbYear.setSelectedItem(String.valueOf(year));
        cal = new GregorianCalendar(year, month, 1);
        System.out.println("refreshed: " + year + " " + month + " 1");
        nod = cal.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);
        som = cal.get(GregorianCalendar.DAY_OF_WEEK);
        for( int i=1; i<=nod; i++ )
        {
            row = new Integer((i+som-2)/7);
            column = (i+som-2)%7;
            days[row][column] = new Integer(i);
        }

        for(int i = 0; i < 6; i++)
        {
            for(int j = 0; j < 7; j++)
            {
                if(days[i][j] == null) System.out.print(" ");
                else System.out.print(days[i][j]+"");
                System.out.print("\t");
            }
            System.out.println();
        }

        TableModel model1 = new DefaultTableModel(days, colNames)
        {
            private static final long serialVersionUID = 1L;
            public boolean isCellEditable(int row, int column)
            {
                return days[row][column] != null;
            }
        };


        JTable table1 = new JTable(model1);
        table1.setRowHeight(38);
        table1.setColumnSelectionAllowed(true);
        table1.setRowSelectionAllowed(true);
        table1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        for(int i=0; i<7; i++)
        {
            table1.getColumnModel().getColumn(i).setCellEditor(new ClientsTableRenderer(new JCheckBox()));
        }

        table1.getTableHeader().setReorderingAllowed(false);

        table1.setPreferredScrollableViewportSize(table.getPreferredSize());
        table1.setShowHorizontalLines(true);
        table1.setShowVerticalLines(true);

        JScrollPane scroll1 = new JScrollPane(table1);
        // scroll = scroll1;
        pnlCalendar.removeAll();
        pnlCalendar.add(scroll1);
        pnlCalendar.add(lblMonth);
        pnlCalendar.add(lblYear);
        pnlCalendar.add(cmbYear);
        pnlCalendar.add(btnPrev);
        pnlCalendar.add(btnNext);
        pnlCalendar.add(pinBoard);
        pnlCalendar.add(addEntry);
        pnlCalendar.revalidate();
        // pnlCalendar.repaint();
        // pane.repaint();
    }

    public static void main( String[] args ) throws Exception
    {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        /*EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                new NewCalendar();
            }
        });*/

        new NewCalendar();
    }

class ClientsTableRenderer extends DefaultCellEditor
{
    private JButton button;
    private String label;
    private boolean clicked;
    private int row, col;
    private JTable table;

    public ClientsTableRenderer(JCheckBox checkBox)
    {
        super(checkBox);
        button = new JButton();
        button.setOpaque(true);
        button.addActionListener(new ActionListener()
        {
            public void actionPerformed( ActionEvent e )
            {
                fireEditingStopped();
            }
        });
    }

    public Component getTableCellEditorComponent( JTable table, Object value, boolean isSelected, int row, int column)
    {
        this.table = table;
        this.row = row;
        this.col = column;
        button.setForeground(Color.black);
        button.setBackground(UIManager.getColor("Button background"));
        label = (value == null) ? "" : value.toString();
        button.setText(label);
        clicked = true;
        return button;
    }

    public Object getCellEditorValue()
    {
        if(clicked)
        {
            //this is what happens when a cell is clicked
            JOptionPane.showMessageDialog( button, "Column with Value: "+table.getValueAt(row,col)+" - Clicked!\n Row: "+row+" Column: "+col);
        }
        clicked = false;
        return new String(label);
    }

    public boolean stopCellEditing()
    {
        clicked = false;
        return super.stopCellEditing();
    }

    protected void fireEditingStopped()
    {
        super.fireEditingStopped();
    }
}

class btnPrev_Action implements ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        if( currMonth == 0 )
        {
            currMonth = 11;
            currYear -= 1;
        }
        else
        {
            currMonth -= 1;
        }

        refreshCalendar(currMonth, currYear);
    }
}

class btnNext_Action implements ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        if( currMonth == 11 )
        {
            currMonth = 0;
            currYear += 1;
        }
        else
        {
            currMonth += 1;
        }

        refreshCalendar(currMonth, currYear);
    }
}

class cmbYear_Action implements ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        if( cmbYear.getSelectedItem() != null )
        {
            String b = cmbYear.getSelectedItem().toString();
            currYear = Integer.parseInt(b);
            //ssrefreshCalendar(currMonth, currYear);
        }
        else
        {
            currMonth -= 1;
        }

        refreshCalendar(currMonth, currYear);
    }
}

}

3 个答案:

答案 0 :(得分:3)

几点意见:

  • 应在event dispatch thread上构建和操作仅 的Swing GUI对象。

    public static void main(String[] args) throws Exception {
        EventQueue.invokeLater(new Runnable() {
    
            @Override
            public void run() {
                new NewCalendar();
            }
        });
    }
    
  • 不要使用setBounds();使用layout manager;您的组件在我的平台上显示为truncated

  • 不要替换 refreshCalendar()中的表格;只需更新TableModel;当模型触发相关事件时,侦听JTable视图将自动刷新。

答案 1 :(得分:1)

如果添加/删除组件,重绘是不够的,因为组件需要重新排序。这可以通过在致电validate()之前致电repaint()来完成。

答案 2 :(得分:-1)

您好。试试这个Code man。我想知道有多少人使用过这个:D

        package dafs;

        /*Contents of CalendarProgran.class */


        //Import packages
        import javax.swing.*;
        import javax.swing.event.*;
        import javax.swing.table.*;
        import java.awt.*;
        import java.awt.event.*;
        import java.util.*;

        public class CalendarProgram{
            static JLabel lblMonth, lblYear;
            static JButton btnPrev, btnNext;
            static JTable tblCalendar;
            static JComboBox 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 ("Gestionnaire de clients"); //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();
                btnPrev = new JButton ("<<");
                btnNext = new JButton (">>");
                mtblCalendar = new DefaultTableModel(){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{
                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);
                    }
                }
            }
        }