我想创建一个日历,该日历根据其所基于的月份动态地创建自己。首先,我创建了一个可以在任何月份使用的背景,其尺寸为700x500(每天700/7,从每月开始为500/5,但是2月28日(周一开始)的星期一有5行周)。我是用这句话做的:
public class Graph {
private final int sizeX = 700;
private final int sizeY = 500;
private Calendar calendar;
public Graph(Calendar calendar) {
this.calendar = calendar;
JFrame frame = new JFrame();
graph(frame);
}
public void graph(JFrame frame) {
buildBackground(frame);
}
private void buildBackground(JFrame frame) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(sizeX, sizeY);
JPanel panel = new Background(sizeX, sizeY);
frame.add(panel);
frame.validate();
frame.repaint();
}
}
public class Background extends JPanel {
private int sizeX;
private int sizeY;
public Background(int sizeX, int sizeY) {
this.sizeX = sizeX;
this.sizeY = sizeY;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.DARK_GRAY);
g.fillRect(0, 0, sizeX, sizeY);
}
}
并且可以正常工作,可以正确创建深灰色背景。当我尝试创建表示日期的小矩形时,就会出现问题。我设计了一个类,要在特定的坐标上表示这些矩形:
public class DayRectangle extends JPanel {
private int posX;
private int posY;
private int day;
public DayRectangle(int posX, int posY, int day) {
this.posX = posX;
this.posY = posY;
this.day = day;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect(posX, posY, 60, 60);
}
public Dimension getPreferredSize() {
return new Dimension (60, 60);
}
@Override
public String toString() {
return String.format("(%d,%d):%d", posX, posY, day);
}
}
已正确创建矩形的坐标,因为这是ArrayList
中DayRectangle
的内容:
[(20,20):1, (120,20):2, (220,20):3, (320,20):4, (420,20):5, (520,20):6, (620,20):7, (20,120):8, (120,120):9, (220,120):10, (320,120):11, (420,120):12, (520,120):13, (620,120):14, (20,220):15, (120,220):16, (220,220):17, (320,220):18, (420,220):19, (520,220):20, (620,220):21, (20,320):22, (120,320):23, (220,320):24, (320,320):25, (420,320):26, (520,320):27, (620,320):28, (20,420):29, (120,420):30, (220,420):31]
它们从(20, 20)
开始,因为我想在这些矩形之间留一些空隙。
主要问题是执行此代码时没有打印矩形:
public void graph(JFrame frame) {
buildBackground(frame);
frame.getGraphics().setColor(Color.WHITE);
JPanel panel;
for (DayRectangle d : arraylist) {
panel = d;
frame.add(panel);
frame.repaint();
}
}
我在做什么错?为什么什么都不打印?谢谢。
答案 0 :(得分:1)
您似乎忘记了JFrame使用BorderLayout作为其布局管理器。相反,您应该将您的Day JPanels添加到另一个使用GridLayout的JPanel中,并且还要记住,Day JPanels将相对于它们自己的局部坐标系进行绘制,因此每个Day JPanel都应该在同一位置绘制其矩形,从0开始,0,而不是相对于包含的Container。
如果要将一个JPanel用作背景JPanel,则应将其添加到BorderLayout.CENTER位置的JFrame中。给它一个GridLayout,并向其中添加Day JPanels以及所需的所有JLabel(如果需要空正方形,则为空)。另外,如果希望背景图像或颜色显示出来,则Day可能需要不透明。
例如
public class DayRectangle extends JPanel {
private static Color RECT_COLOR = Color.LIGHT_GRAY;
private static final int PREF_W = 60;
private static final int GAP = 4;
private int posX;
private int posY;
private int day;
public DayRectangle(int posX, int posY, int day) {
this.posX = posX; // not sure that you need this
this.posY = posY; // ditto
this.day = day;
// if you desire a background to show throw
// setOpaque(false);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(RECT_COLOR);
g.fillRect(GAP, GAP, PREF_W - 2 * GAP, PREF_W - 2 * GAP);
}
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_W);
}
@Override
public String toString() {
return String.format("(%d,%d):%d", posX, posY, day);
}
}
举一个简单的例子:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.*;
@SuppressWarnings("serial")
public class ExampleGrid extends JPanel {
public ExampleGrid() {
JPanel mainGrid = new JPanel();
mainGrid.setLayout(new GridLayout(0, 7));
// just to show a little off-set of the days
mainGrid.add(new JLabel());
mainGrid.add(new JLabel());
mainGrid.add(new JLabel());
// now fill the calendar
for (int i = 0; i < 30; i++) {
mainGrid.add(new DayRectangle(i + 1));
}
JLabel monthLabel = new JLabel("JULY", SwingConstants.CENTER);
monthLabel.setFont(monthLabel.getFont().deriveFont(Font.BOLD, 36f));
// label the days of the week at the top
String[] daysOfWk = { "Sun", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat" };
JPanel daysOfWkPanel = new JPanel(new GridLayout(1, 7));
for (String dayOfWk : daysOfWk) {
daysOfWkPanel.add(new JLabel(dayOfWk, SwingConstants.CENTER));
}
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(monthLabel, BorderLayout.PAGE_START);
topPanel.add(daysOfWkPanel, BorderLayout.CENTER);
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(mainGrid, BorderLayout.CENTER);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// not sure what you want to do here
}
private static void createAndShowGui() {
ExampleGrid mainPanel = new ExampleGrid();
JFrame frame = new JFrame("Example Grid");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
@SuppressWarnings("serial")
class DayRectangle extends JPanel {
private static Color RECT_COLOR = Color.LIGHT_GRAY;
private static final int PREF_W = 60;
private static final int GAP = 4;
private static final float FNT_SZ = 20f;
private int day;
public DayRectangle(int day) {
this.day = day;
setLayout(new GridBagLayout());
JLabel label = new JLabel("" + day);
label.setFont(label.getFont().deriveFont(Font.BOLD, FNT_SZ));
add(label);
// if you desire a background to show throw
// setOpaque(false);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(RECT_COLOR);
g.fillRect(GAP, GAP, PREF_W - 2 * GAP, PREF_W - 2 * GAP);
}
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_W);
}
public int getDay() {
return day;
}
}