Несколько JPanel не печатаются перед фоном - PullRequest
0 голосов
/ 29 июня 2019

Я хотел создать календарь, который создает себя динамически в зависимости от месяца, на котором он основан.Сначала я создал фон, который будет использоваться в любые месяцы, и его размеры составляют 700x500 (700/7 для каждого дня и 500/5 для каждого месяца, но 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();
    }
}

Что я делаю не так?Почему ничего не печатается?Благодаря.

1 Ответ

1 голос
/ 29 июня 2019

Вы, кажется, забыли, что JFrame использует BorderLayout для своего менеджера компоновки. Скорее всего, вам следует добавить свои JPanels дня в другой JPanel, который использует GridLayout, а также помнить, что JPanels дня будет рисоваться относительно своей собственной локальной системы координат, и поэтому каждый JPanel дня, вероятно, должен рисовать свой прямоугольник в том же месте, начиная с 0 , 0, не относительно содержащего контейнера.

Если вы хотите, чтобы одна JPanel была фоновой JPanel, то ее следует добавить к JFrame в позиции BorderLayout.CENTER. Дайте ему GridLayout, и добавьте к нему ваши Day JPanels и все необходимые JLabels (пустые, если вам нужны пустые квадраты). Также, возможно, 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);
    }
}

Для простого примера:

enter image description here

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;
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...