【问题标题】:How to repaint a Panel from inside如何从内部重新绘制面板
【发布时间】:2015-03-22 21:34:58
【问题描述】:

所以我有一个使用边框布局的日历 GUI。有一个带有月份和年份组合框的标题(北)。当我在月份组合框中选择一个项目时,例如六月,它将更新日历并重新绘制中心(中心有 42 个 JButton)。中心是一个装满按钮的 JPanel。这些按钮很难显示当天的事件(尽可能多地列出信息)。

我的问题是重新绘制面板并拉伸框架。当我拉伸框架时,由于某种原因,中心面板会重复。当我调用 revalidate 时,它​​会继续重复。

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

public class cPan extends JPanel implements ChangeListener
{
String date;
public HashMap<String, ArrayList<Event>> haM;
DataModel data;
JButton dayB;
MyCalendar cal;

public cPan(MyCalendar c, HashMap<String, ArrayList<Event>> hm, DataModel d)
{
    haM = hm;
    data = d;
    cal = c;
}

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    int year = cal.get(Calendar.YEAR);
    int month = cal.get(Calendar.MONTH);
    System.out.println(month);
    int day = cal.get(Calendar.DAY_OF_MONTH);
    int daysInMonth = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
    Calendar calForDay = Calendar.getInstance();
    calForDay.set(Calendar.DATE, day);
    calForDay.set(Calendar.MONTH, month);
    calForDay.set(Calendar.YEAR, year);
    calForDay.set(Calendar.DAY_OF_MONTH, 1);
    Date firstDayOfMonth = calForDay.getTime();
    int counter = 0;
    SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
    String fDOM = sdf.format(firstDayOfMonth);

    //print empty buttons
    if(fDOM.equalsIgnoreCase("SUNDAY")) {counter = 1;}
    if(fDOM.equalsIgnoreCase("MONDAY")) {counter = 2;}
    if(fDOM.equalsIgnoreCase("TUESDAY")) {counter = 3;}
    if(fDOM.equalsIgnoreCase("WEDNESDAY")) {counter = 4;}
    if(fDOM.equalsIgnoreCase("THURSDAY")) {counter = 5;}
    if(fDOM.equalsIgnoreCase("FRIDAY")) {counter = 6;}
    if(fDOM.equalsIgnoreCase("SATURDAY")) {counter = 7;}
    setLayout(new GridLayout(7,7));
    DAYS[] arrOfDays = DAYS.values();
    for(DAYS s : arrOfDays)
    {
        dayB = new JButton(s.name());
        dayB.setBackground(new Color(255, 204, 153 , 255));
        add(dayB);
    }
    for (int j = 1; j < counter; j++)
    {
        dayB.setBackground(new Color(255, 229, 204, 255));
        dayB = new JButton("");
        add(dayB);
    }
    //print day buttons
    for(int i = 1; i <= daysInMonth; i++)
    {
        String dayNum = String.valueOf(i);
        String monthNum = String.valueOf(month + 1);
        String yearNum = String.valueOf(year);
        String dayNum2 = dayNum;
        if(dayNum.length() == 1)
        {
            dayNum2 = "0" + dayNum;
        }
        if(String.valueOf(month).length() == 1)
        {
            monthNum = "0" + monthNum;
        }
        date = yearNum + monthNum + dayNum2;

        dayB = new JButton(dayNum);
        if(i == day)
        {
            dayB.setBackground(new Color(153, 255, 153, 255));
        }
        else if(haM.containsKey(date))
        {
            dayB.setBackground(new Color(255, 255, 153, 255));
        }
        else
        {
            dayB.setBackground(new Color(255, 229, 204, 255));
        }
        dayB.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                DayFrame dayF = new DayFrame(date, haM);
            }
        });
        add(dayB);
        counter++;
    }
    //print empty buttons
    for(int i = counter; i <= 42; i++)
    {
        dayB = new JButton("");
        dayB.setBackground(new Color(255, 229, 204, 255));
        add(dayB);
    }
}

public void stateChanged(ChangeEvent e) {
    System.out.println("Something is going on in statechange");
    cal.set(Calendar.MONTH, 10); // only did this to test it out
    cPan.this.revalidate();
    cPan.this.repaint();
}
}

【问题讨论】:

  • 您的paintComponent 方法正在做许多它不应该做的事情,例如创建和放置组件。它应该只绘画和绘画。
  • 您如何建议重做面板?很想学习。

标签: java swing jpanel jbutton repaint


【解决方案1】:

您的paintComponent 方法正在做许多它不应该做的事情,例如创建和放置组件。它应该只绘画和绘画。

我建议您将组件放入类的构造函数内的 GUI 中,然后再次使用 paintComponent 进行绘画,仅此而已。如果要显示日历,请考虑将每天显示为 JPanel,该 JPanel 包含在使用 GridLayout 的 JPanel 中。 DayPanel 可以在其自己的类中以重构信息。

另外,你应该重命名你的类,因为按照惯例,类名应该以大写字母开头,所以像 CalendarPanel 这样的名字会更好。

【讨论】:

  • 每一天都必须是交互式的,以显示有关所选日期的更多事件。 JLabels 可以用来交互吗??
  • @RogerRabbits:或者你可以让每一天都成为它自己的 JPanel,并让它保存一个 JList 事件。有很多方法可以剥这只兔子的皮(对不起)。此外,您当前的上述类应重新分解为更小的组成类,以减少其不必要的复杂性。
  • 满是鳗鱼:非常双关!组成类会是内部类吗?所以建议你在中心有一个JPanel。此面板将包含多个其他面板,代表一个月中的日子?
  • @RogerRabbits:不,组成类将是独立类。是的。
猜你喜欢
  • 2012-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-02
  • 1970-01-01
  • 2012-12-11
  • 1970-01-01
相关资源
最近更新 更多