【问题标题】:JAVA I use a JButton[] Array in a method to add multiple buttons - method works in class constructor but not when used as a pressed button actionJAVA 我在添加多个按钮的方法中使用 JButton[] 数组 - 方法在类构造函数中有效,但在用作按下按钮操作时无效
【发布时间】:2020-01-12 17:41:22
【问题描述】:

我有一个问题,我无法克服它...... 我正在使用 swing 用 Ja​​va 编写程序。该程序将用于从显示的日历中选择一天并输入您的工作时间(例如 8:00 - 16:00),然后该程序将计算您在一个月内工作了多少小时并计算您的薪水。

我已经编写了一些代码,因此在启动程序时您会看到当前月份的表示。我想添加一个ActionListener到一个按钮,它将日历的外观重新排列到上个月。我想使用生成当前月份但发送不同参数(上个月日期)的相同方法。

为了测试它,我在ActionListener 上使用了该方法(所以当我启动它时,我看到空白表单,按下该按钮后它会显示当前方法),问题是什么都没有发生。 . 当我把它放在我的类的构造函数中时,该方法工作正常,但当它用作执行的操作时不起作用,我不知道为什么。

我希望你能帮助我弄清楚,也许告诉我我在哪里犯了错误以及我能做些什么。这是我的爱好,我没有任何专业的编程经验。

我的代码:

package zadanie;

import javax.swing.*;
import java.awt.*;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;

class Panel extends JPanel {

    private JButton[] buttonArray = new JButton[42];
    private JButton nextButton, previousButton;
    private JLabel monthYear;
    private Color buttonColor = new Color(116, 185, 255);
    private Color buttonColorInactive = new Color(255,255,255);
    private Color sundey = new Color(0, 184, 148);
    private Color saturday = new Color(85, 239, 196);
    private Color labelColor = new Color(255, 211, 42);
    private LocalDate dateNow = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());

    Panel(){
        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        add(getMonthLabel());
        add(getWeekDaysPanel());
        add(Box.createRigidArea(new Dimension(0,5)));
        add(getMonthPanel());
        calendarGenerator();
        getWeekDaysPanel().setAlignmentX(Component.CENTER_ALIGNMENT);
        getMonthPanel().setAlignmentX(Component.CENTER_ALIGNMENT);
    }

    private JComponent getMonthPanel(){
        JPanel monthPanel = new JPanel();
        monthPanel.setLayout(new GridLayout(6,7));
        monthPanel.setMaximumSize(new Dimension(710,460));
        monthPanel.setPreferredSize(new Dimension(710,460));
        monthPanel.setMaximumSize(new Dimension(710,460));

        //Loop that in every iteration creates a "b" button set it properties and to a "p" panel and a buttonArray.
        for (int i=0; i<42; i++){
            JButton b = new JButton();
                b.setMaximumSize(new Dimension(95,70));
                b.setPreferredSize(new Dimension(95,70));
                b.setMaximumSize(new Dimension(95,70));
                b.setBorderPainted(false);
                b.setRolloverEnabled(false);
                b.setVisible(true);
            JPanel p = new JPanel();
            p.add(b);
            buttonArray[i] = b;
            monthPanel.add(p);
        }
        return monthPanel;
    }
    // Similar to getMonthPanel method - it adds a 7 labels with the names of the days
    private JComponent getWeekDaysPanel(){
        JPanel daysPanel = new JPanel();
            daysPanel.setBackground(labelColor);
            daysPanel.setMinimumSize(new Dimension(700,35));
            daysPanel.setPreferredSize(new Dimension(700,35));
            daysPanel.setMaximumSize(new Dimension(700,35));
        String[] daysList = {"pn.", "wt.", "śr.", "czw.", "pt.", "sob.", "niedz."};

        for (int i = 0; i < 7; i++){
            JLabel e = new JLabel("", JLabel.CENTER);
                e.setMinimumSize(new Dimension(95,25));
                e.setPreferredSize(new Dimension(95,25));
                e.setMaximumSize(new Dimension(95,25));
                e.setLayout(new GridLayout(1,7));
                e.setText(daysList[i]);
                daysPanel.add(e);
        }
        return daysPanel;
    }
    // a method that adds a two buttons (to switch to previous and next month) and a label that displays the displayed month and year
    private JComponent getMonthLabel(){
        JPanel monthLabel = new JPanel();
            monthLabel.setMinimumSize(new Dimension(700,45));
            monthLabel.setPreferredSize(new Dimension(700,45));
            monthLabel.setMaximumSize(new Dimension(700,45));
            monthLabel.setBackground(buttonColorInactive);
            monthLabel.revalidate();
        nextButton = new JButton();
            ImageIcon nIcon = new ImageIcon("n.png");
            nextButton.setMinimumSize(new Dimension(25,25));
            nextButton.setPreferredSize(new Dimension(25,25));
            nextButton.setMaximumSize(new Dimension(25,25));
            nextButton.setIcon(nIcon);
            nextButton.setBorderPainted(false);
            nextButton.setBackground(new Color(255,255,255));
//            nextButton.addActionListener();
        previousButton = new JButton();
            ImageIcon pIcon = new ImageIcon("p.png");
            previousButton.setMinimumSize(new Dimension(25,25));
            previousButton.setPreferredSize(new Dimension(25,25));
            previousButton.setMaximumSize(new Dimension(25,25));
            previousButton.setIcon(pIcon);
            previousButton.setBorderPainted(false);
            previousButton.setBackground(new Color(255,255,255));

        monthYear = new JLabel("MIESIĄC_ROK", JLabel.CENTER);
            monthYear.setMinimumSize(new Dimension(620,25));
            monthYear.setPreferredSize(new Dimension(620,25));
            monthYear.setMaximumSize(new Dimension(620,25));

        monthLabel.add(previousButton);
        monthLabel.add(monthYear);
        monthLabel.add(nextButton);

        return monthLabel;
    }
    // A method that change the appearance of the buttons in the "buttonArray" so the whole thing looks like calendar of the month
    private void calendarGenerator(){
        int noOfDays = dateNow.lengthOfMonth(); /// getting number of days in a month
        int firstDayIndex = (dateNow.getDayOfWeek().getValue() - 1); // gettin the value (number) of the first day of month (it is decreased because getValue starts with 1 and buttonArray with 0)
        int dayNo = 1; // variable that is used to set number of day in the setText() method of button
        int month = (dateNow.getMonth().getValue() - 1); // variable that has a number of the previous month, that is why I decreased it by 1
        int year = dateNow.getYear(); // getting current year

            if (month == 0){ // safety - when the month variable hits 0 it is set for December (no 12) and year is decreased by 1
                month = 12;
                year --;
            }

        LocalDate previousMonthDate = LocalDate.of(year, month, 1); // a new variable for the previous month
        int dayNo2 = previousMonthDate.lengthOfMonth() - (firstDayIndex - 1);  // getting number of days of the previous mont (similar to dayNo but it responsible for the previous month during displaying

        for (int i = 0; i < firstDayIndex; i++){ // loop that fill days in buttons that represent previous month
            buttonArray[i].setText(""+dayNo2);
            buttonArray[i].setVisible(true);
            buttonArray[i].setEnabled(false);
            buttonArray[i].setBackground(buttonColorInactive);
            dayNo2++;
        }


        for (int i = firstDayIndex; i < noOfDays + firstDayIndex; i++){ // loop that fill days in buttons that represent current month
            buttonArray[i].setText(""+dayNo);
            buttonArray[i].setVisible(true);

            if (i == 6 || i == 13 || i == 20 || i == 27 || i == 34 || i == 41){

                buttonArray[i].setBackground(sundey);
            }
            else if (i == 5 || i == 12 || i == 19 || i == 26 || i == 33 || i == 40){
                buttonArray[i].setBackground(saturday);
            }
            else{
                buttonArray[i].setBackground(buttonColor);
            }
            monthYear.setText(""+translate(dateNow.getMonth().getValue())+" "+year); // "translate()" method is used for translating month names from English to my native language
            dayNo++;
        }

        dayNo = 1; // setting dayNo 1 because next month always starts with 1

        for (int i = (noOfDays + firstDayIndex); i < 42; i++){ // loop that fills the rest, empty buttons that represent next month
            buttonArray[i].setText(""+ dayNo);
            buttonArray[i].setVisible(true);
            buttonArray[i].setEnabled(false);
            buttonArray[i].setBackground(buttonColorInactive);
            dayNo++;
        }
    }

    // Method for translating English names to my native Language
    private String translate(int a){
        String monthInPolish = "";
        switch (dateNow.getMonth()){
            case JANUARY: monthInPolish = "Styczeń"; break;
            case FEBRUARY: monthInPolish = "Luty"; break;
            case MARCH: monthInPolish = "Marzec"; break;
            case APRIL: monthInPolish = "Kwiecień"; break;
            case MAY: monthInPolish = "Maj"; break;
            case JUNE: monthInPolish = "Czerwiec"; break;
            case JULY: monthInPolish = "Lipiec"; break;
            case AUGUST: monthInPolish = "Sierpień"; break;
            case SEPTEMBER: monthInPolish = "Wrzesień"; break;
            case OCTOBER: monthInPolish = "Październik"; break;
            case NOVEMBER: monthInPolish = "Listopad"; break;
            case DECEMBER: monthInPolish = "Grudzień"; break;
        }
        return monthInPolish;
    }
}

我说的方法叫calendarGenerator() 感谢您的努力!

这是我在构造函数中使用该方法时的样子

这是我在构造函数中不使用该方法时的样子

编辑:我添加了在构造函数中使用calendarGenerator() 方法以及不使用该方法时的外观图片。当按下按钮时,在该表单中使用该方法(如上所示),我想看看我的方法是否正确(我知道我可以发送参数并因此使用它来切换月份)。所以我从构造函数中删除了calendarGenerator() 方法(第二张图片显示了没有它的程序看起来如何)并将其放入按钮的 ActionPerformed 方法(那个黑色箭头)。我以为当我按下按钮时,窗口会改变外观,所以它看起来像第一张图片,但只有上面标签上的文字没有改变其他任何东西,我仍然不知道为什么。

【问题讨论】:

  • 无关:要翻译成您的母语,请使用return dateNow.getMonth().getDisplayName(TextStyle.FULL_STANDALONE, Locale.forLanguageTag("pl-PL"));
  • 1) 见Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?(是的。) 2) 获取图像的一种方法是热链接到this Q&A 中看到的图像。例如。 This answer 指向嵌入在 this question 中的图像的热链接。
  • 糟糕的标题。重写以总结您的特定技术问题。
  • 顺便提一下:Month 枚举已经存在,它的getDisplayName 会自动本地化为波兰语等语言。底部不需要你的translate 方法。

标签: java swing for-loop actionlistener


【解决方案1】:

更改calendarGenerator,使其接受一个参数,该参数是您要生成的月份中的任意日期:

private void calendarGenerator(LocalDate dateInMonth){
    int noOfDays = dateInMonth.lengthOfMonth(); /// getting number of days in a month
    .........
}

要生成当前月份,请通过calendarGenerator(dateNow);调用它
下个月生成:calendarGenerator(dateNow.plusMonths(1));

以下是mre(1)演示如何使用修改后的方法:

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

class Panel extends JPanel {

    private JPanel monthPanel;
    private JLabel monthYear;
    private final static Color buttonColor = new Color(116, 185, 255), buttonColorInactive = new Color(255,255,255),
                  sundey = new Color(0, 184, 148),  saturday = new Color(85, 239, 196), labelColor = new Color(255, 211, 42);
    private final static int DAYS=7, WEEKS =6;
    private final LocalDate dateNow = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
    private LocalDate calendarDate;
    private final JButton[] buttonArray = new JButton[DAYS*WEEKS];

    Panel(){
        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        add(getMonthLabel());
        add(getWeekDaysPanel());
        add(Box.createRigidArea(new Dimension(0,5)));
        makeMonthPanel();
        add(monthPanel);
        calendarGenerator(dateNow);
    }

    private void makeMonthPanel(){

        monthPanel = new JPanel();
        monthPanel.setLayout(new GridLayout(WEEKS,DAYS));
        monthPanel.setPreferredSize(new Dimension(710,460));
        monthPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
        //Loop that in every iteration creates a "b" button set it properties and to a "p" panel and a buttonArray.
        for (int i=0; i< DAYS * WEEKS; i++){
            JButton b = new JButton();
            b.setPreferredSize(new Dimension(95,70));
            b.setBorderPainted(false);
            b.setRolloverEnabled(false);
            JPanel p = new JPanel();
            p.add(b);
            buttonArray[i] = b;
            monthPanel.add(p);
        }
    }

    // Similar to getMonthPanel method - it adds a 7 labels with the names of the days
    private JComponent getWeekDaysPanel(){
        JPanel daysPanel = new JPanel();
        daysPanel.setBackground(labelColor);
        daysPanel.setPreferredSize(new Dimension(700,35));
        String[] daysList = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};

        for (int i = 0; i < daysList.length ; i++){
            JLabel e = new JLabel("", JLabel.CENTER);
            e.setPreferredSize(new Dimension(95,25));
            e.setText(daysList[i]);
            daysPanel.add(e);
        }
        return daysPanel;
    }
    // a method that adds a two buttons (to switch to previous and next month) and a label that displays the displayed month and year
    private JComponent getMonthLabel(){

        JPanel monthLabel = new JPanel();
        monthLabel.setBackground(buttonColorInactive);

        JButton nextButton = new JButton(">");;
        nextButton.setBorderPainted(false);
        nextButton.setBackground(new Color(255,255,255));
        nextButton.addActionListener(e -> calendarGenerator(calendarDate.plusMonths(1)));

        JButton previousButton = new JButton("<");
        previousButton.setBorderPainted(false);
        previousButton.setBackground(new Color(255,255,255));
        previousButton.addActionListener(e -> calendarGenerator(calendarDate.minusMonths(1)));

        monthYear = new JLabel("MIESIĄC_ROK", JLabel.CENTER);
        monthYear.setPreferredSize(new Dimension(620,25));

        monthLabel.add(previousButton);
        monthLabel.add(monthYear);
        monthLabel.add(nextButton);

        return monthLabel;
    }

    // A method that change the appearance of the buttons in the "buttonArray" so the whole thing looks like calendar of the month
    private void calendarGenerator(LocalDate dateInMonth){
        calendarDate = dateInMonth;
        int noOfDays = dateInMonth.lengthOfMonth(); /// getting number of days in a month
        int firstDayIndex = dateInMonth.getDayOfWeek().getValue() - 1; // gettin the value (number) of the first day of month (it is decreased because getValue starts with 1 and buttonArray with 0)
        int dayNo = 1; // variable that is used to set number of day in the setText() method of button
        int month = dateInMonth.getMonth().getValue() - 1; // variable that has a number of the previous month, that is why I decreased it by 1
        int year = dateInMonth.getYear(); // getting current year

        if (month == 0){ // safety - when the month variable hits 0 it is set for December (no 12) and year is decreased by 1
            month = 12;
            year --;
        }

        LocalDate previousMonthDate = LocalDate.of(year, month, 1); // a new variable for the previous month
        int dayNo2 = previousMonthDate.lengthOfMonth() - (firstDayIndex - 1);  // getting number of days of the previous mont (similar to dayNo but it responsible for the previous month during displaying


        for (int i = 0; i < firstDayIndex; i++){ // loop that fill days in buttons that represent previous month
            buttonArray[i].setText(""+dayNo2);
            buttonArray[i].setEnabled(false);
            buttonArray[i].setBackground(buttonColorInactive);
            dayNo2++;
        }


        for (int i = firstDayIndex; i < noOfDays + firstDayIndex; i++){ // loop that fill days in buttons that represent current month
            buttonArray[i].setText(""+dayNo);
            buttonArray[i].setVisible(true);

            if (i == 6 || i == 13 || i == 20 || i == 27 || i == 34 || i == 41){

                buttonArray[i].setBackground(sundey);
            }
            else if (i == 5 || i == 12 || i == 19 || i == 26 || i == 33 || i == 40){
                buttonArray[i].setBackground(saturday);
            }
            else{
                buttonArray[i].setBackground(buttonColor);
            }
            monthYear.setText(""+dateInMonth.getMonth()+" "+year);
            dayNo++;
        }

        dayNo = 1; // setting dayNo 1 because next month always starts with 1

        for (int i = noOfDays + firstDayIndex; i < 42; i++){ // loop that fills the rest, empty buttons that represent next month
            buttonArray[i].setText(""+ dayNo);
            buttonArray[i].setVisible(true);
            buttonArray[i].setEnabled(false);
            buttonArray[i].setBackground(buttonColorInactive);
            dayNo++;
        }

        monthPanel.revalidate();
    }

    public static void main(String[] args) {

        JFrame frame=new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel calendarPane = new Panel();
        frame.getContentPane().add(calendarPane);
        frame.pack();
        frame.setVisible(true);
    }
}


(1) 发布问题和答案时请考虑mre。要实现它,请删除所有不必要的内容(如本例中的翻译)以显示问题。 mre 应该证明问题,而不一定是您的应用程序。

【讨论】:

  • 我认为以上回答了你的问题。我添加了代码来演示它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-29
  • 2023-01-03
  • 1970-01-01
  • 2012-03-05
  • 2015-06-11
  • 2019-11-15
  • 1970-01-01
相关资源
最近更新 更多