具有Graphics.draw的JComponents

时间:2019-01-27 15:24:40

标签: java swing jpanel

我正在尝试使用JPanel制作一个简单的游戏。

我正在使用Graphics Draw显示所有信息,包括文本,但是我需要添加用户输入。

我当时正在考虑将JTextField与绝对定位一起使用,以使其与所绘制的内容一起使用,但是我听说绝对定位不是设置JPanel的好方法。

是否有更好的方法在同一面板中同时使用图形绘画和JComponents?

2 个答案:

答案 0 :(得分:1)

解决方案:使用布局管理器

为什么不简单地将图形JPanel由另一个使用BorderLayout并保存在BorderLayout.CENTER位置的JPanel来保存。然后,您可以将JTextField或其他控件组件放在外部JPanel中的其他位置。

还可以将布局管理器添加到图形JPanel,然后使用布局在其上添加组件。只需记住,如果在图形JPanel的顶部添加任何JPanels,则添加的JPanels应该是透明的,也就是说,应在它们上面调用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);
    }

}

在此代码示例中,我绘制了一个名为class DrawingPanel的JPanel,并在另一个主JPanel中使用了GradientPaintEg类:

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

如果要将组件添加到DrawingPanel,请先为其提供布局,然后添加组件。例如,有一个JPanel包含名为sliderPanel的JSliders,我使用BorderLayout将其添加到DrawingPanel实例中:

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

这会将sliderPanel添加到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);

答案 1 :(得分:0)

这是使用布局管理器在面板上将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