Компоненты с Graphics.draw - PullRequest
0 голосов
/ 27 января 2019

Я пытаюсь сделать простую игру с использованием JPanel.

Я использую Graphics Draw для отображения всей информации, включая текст, но мне нужно добавить пользовательский ввод.

Я думал об использовании JTextField с абсолютным позиционированием, чтобы заставить его работать с тем, что рисуется, но я слышал, что абсолютное позиционирование не является хорошим способом настройки JPanel.

Есть ли лучший способ использовать графическую краску и JComponents на одной панели?

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Вот базовая схема объединения ввода пользователя в JTextfield и рисования на панели с помощью менеджера раскладки:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

class DrawingPanel extends JPanel {

    private final JButton update;
    private final JTextField input;
    private final static int W = 300, H = 350, RADIUS = 100, GAP = 50;
    private String text;

    public DrawingPanel() {

        setPreferredSize(new Dimension(W, H));
        setOpaque(false);
        setLayout(new BorderLayout());
        update = new JButton("Update");
        update.addActionListener(e->update());
        add(update, BorderLayout.PAGE_START);
        input  = new JTextField();
        add(input, BorderLayout.PAGE_END);
        text = "Enter text and press button";
    }

    private void update() {
        text = input.getText();
        input.setText("");
        repaint();
    }

    @Override
    public void paintComponent(final Graphics g) {
        super.paintComponents(g);
        final int width = getWidth();
        final int height = getHeight();
        g.setColor(Color.RED);
        g.fillOval(width/2 - RADIUS, height/2 - RADIUS, RADIUS*2, RADIUS*2);
        g.setColor(Color.BLUE);
        g.drawString(text, height/2 - RADIUS - GAP, GAP);
    }

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(()->makeGui());
    }

    private static void  makeGui() {
        JFrame frame = new JFrame();
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(new DrawingPanel());
        frame.pack();
        frame.setVisible(true);
    }
}

enter image description here

0 голосов
/ 27 января 2019

Решение: используйте менеджеры компоновки

Почему бы просто не держать чертеж JPanel в руках другого JPanel, который использует BorderLayout и удерживается в позиции BorderLayout.CENTER.Затем вы можете поместить JTextFields или другие компоненты управления во внешнюю JPanel в другие позиции.

Вы также можете добавить диспетчер компоновки в JPanel чертежа и затем добавить в него компоненты, используя компоновку.Просто помните, что если вы добавляете JPanels поверх рисунка JPanel, добавленные JPanel должны быть прозрачными, то есть myPanel.setOpaque(false) должны вызываться для них, чтобы рисунок снизу просвечивал.

Например -запустите эту программу, чтобы увидеть, что я имею в виду:

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class GradientPaintEg extends JPanel {
    private DrawingPanel drawingPanel = new DrawingPanel();
    private JSlider hue1Slider = new JSlider(0, 100, 0);
    private JSlider hue2Slider = new JSlider(0, 100, 0);

    public GradientPaintEg() {
        Color color = drawingPanel.getColor1();
        float[] hsb = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null);
        int value = (int) (hsb[0] * 100);
        hue1Slider.setValue(value);

        color = drawingPanel.getColor2();
        hsb = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null);
        value = (int) (hsb[0] * 100);
        hue2Slider.setValue(value);

        hue1Slider.setMajorTickSpacing(20);
        hue1Slider.setMinorTickSpacing(5);
        hue1Slider.setPaintTicks(true);
        hue1Slider.setPaintLabels(true);
        hue1Slider.setPaintTrack(true);
        hue1Slider.addChangeListener(new SliderListener(hue1Slider, drawingPanel, true));
        hue1Slider.setOpaque(false);

        hue2Slider.setMajorTickSpacing(20);
        hue2Slider.setMinorTickSpacing(5);
        hue2Slider.setPaintTicks(true);
        hue2Slider.setPaintLabels(true);
        hue2Slider.setPaintTrack(true);
        hue2Slider.addChangeListener(new SliderListener(hue2Slider, drawingPanel, false));
        hue2Slider.setOpaque(false);

        JPanel sliderPanel = new JPanel(new GridLayout(0, 1, 4, 4));
        sliderPanel.add(hue1Slider);
        sliderPanel.add(hue2Slider);

        sliderPanel.setOpaque(false);

        setLayout(new BorderLayout());
        // if you want to add the slider panel to the main JPanel:
        // add(sliderPanel, BorderLayout.PAGE_START);
        add(drawingPanel);

        // if you want to add the sliderPanel to the drawing JPanel
        drawingPanel.setLayout(new BorderLayout());
        drawingPanel.add(sliderPanel, BorderLayout.PAGE_START);
    }

    private class SliderListener implements ChangeListener {
        private JSlider slider;
        private DrawingPanel drawingPanel;
        private boolean color1Listener;

        public SliderListener(JSlider slider, DrawingPanel drawingPanel, boolean color1Listener) {
            this.slider = slider;
            this.drawingPanel = drawingPanel;
            this.color1Listener = color1Listener;
        }

        @Override
        public void stateChanged(ChangeEvent e) {
            int value = slider.getValue();
            float hue = value / 100f;
            Color c = Color.getHSBColor(hue, 1f, 1f);
            if (color1Listener) {
                drawingPanel.setColor1(c);
            } else {
                drawingPanel.setColor2(c);
            }
        }
    }

    private static void createAndShowGui() {
        GradientPaintEg mainPanel = new GradientPaintEg();

        JFrame frame = new JFrame("GradientPaintEg");
        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());
    }
}

class DrawingPanel extends JPanel {
    private static final int PREF_W = 600;
    private static final int PREF_H = PREF_W;
    private static final float X2 = 20;
    private static final float Y2 = X2;
    private Color color1 = Color.RED;
    private Color color2 = Color.BLUE;

    public Color getColor1() {
        return color1;
    }

    public void setColor1(Color color1) {
        this.color1 = color1;
        repaint();
    }

    public Color getColor2() {
        return color2;
    }

    public void setColor2(Color color2) {
        this.color2 = color2;
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setPaint(new GradientPaint(0, 0, color1, X2, Y2, color2, true));
        g2.fillRect(0, 0, getWidth(), getHeight());
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

}

В этом примере кода у меня есть JPanel, который рисует, называется class DrawingPanel ииспользуйте в другой основной JPanel класс GradientPaintEg:

public class GradientPaintEg extends JPanel {
    private DrawingPanel drawingPanel = new DrawingPanel();

Если я хочу добавить компоненты в DrawingPanel, я сначала назначаю ему макет, а затем добавляю компонент (ы).Например, есть JPanel, который содержит JSliders с именем sliderPanel, который я добавляю к экземпляру DrawingPanel с помощью BorderLayout:

drawingPanel.setLayout(new BorderLayout());
drawingPanel.add(sliderPanel, BorderLayout.PAGE_START);

Это добавляет панель-слайдера в верхнюю часть DrawingPanel.

Но также обратите внимание, что сначала я должен сделать sliderPanel непрозрачным:

JPanel sliderPanel = new JPanel(new GridLayout(0, 1, 4, 4));
sliderPanel.add(hue1Slider);
sliderPanel.add(hue2Slider);

sliderPanel.setOpaque(false);

Я также сделал непрозрачными сами JSliders, чтобы нижележащий рисунок просвечивал:

// ......

hue1Slider.setOpaque(false);

// ......

hue2Slider.setOpaque(false);
...