为了账号安全,请及时绑定邮箱和手机立即绑定

带有 Graphics.draw 的 JComponents

带有 Graphics.draw 的 JComponents

HUX布斯 2022-05-25 09:52:20
我正在尝试使用 JPanel 制作一个简单的游戏。我正在使用 Graphics Draw 来显示所有信息,包括文本,但我需要添加用户输入。我正在考虑将 JTextField 与绝对定位一起使用以使其与正在绘制的内容一起工作,但我听说绝对定位不是设置 JPanel 的好方法。有没有更好的方法在同一个面板中同时使用图形绘制和 JComponents?
查看完整描述

2 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

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

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

您还可以将布局管理器添加到绘图 JPanel,然后使用布局将组件添加到此。请记住,如果您在绘图 JPanel 顶部添加任何 JPanel,则添加的 JPanel 应该是透明的,即myPanel.setOpaque(false)应该在它们上调用,以便下面的绘图显示出来。

例如——运行这个程序来看看我的意思:

//img1.sycdn.imooc.com//628d8bed000147c706010630.jpg

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();

如果我想向绘图面板添加组件,我首先给它一个布局,然后添加组件。例如,有一个 JPanel 保存了调用的 JSlider sliderPanel,我使用 BorderLayout 添加到 DrawingPanel 实例:


drawingPanel.setLayout(new BorderLayout());

drawingPanel.add(sliderPanel, BorderLayout.PAGE_START);

这会将滑块面板添加到绘图面板的顶部。


但还要注意,我必须先使 sliderPanel 不透明:


JPanel sliderPanel = new JPanel(new GridLayout(0, 1, 4, 4));

sliderPanel.add(hue1Slider);

sliderPanel.add(hue2Slider);


sliderPanel.setOpaque(false);

我还使 JSlider 本身不透明,以便底层绘图显示:


// ......


hue1Slider.setOpaque(false);


// ......


hue2Slider.setOpaque(false);


查看完整回答
反对 回复 2022-05-25
?
心有法竹

TA贡献1866条经验 获得超5个赞

JTextfield这是使用布局管理器在面板上组合用户输入和绘画的基本 mcve :


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

    }

}

//img1.sycdn.imooc.com//628d8c080001072603840486.jpg

查看完整回答
反对 回复 2022-05-25
  • 2 回答
  • 0 关注
  • 67 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信