海绵宝宝撒
解决方案:使用布局管理器为什么不简单地让另一个 JPanel 持有绘图 JPanel,一个使用 BorderLayout 并保持在该BorderLayout.CENTER位置的 JPanel。然后,您可以将 JTextField 或其他控件组件放置在外部 JPanel 中的其他位置。您还可以将布局管理器添加到绘图 JPanel,然后使用布局将组件添加到此。请记住,如果您在绘图 JPanel 顶部添加任何 JPanel,则添加的 JPanel 应该是透明的,即myPanel.setOpaque(false)应该在它们上调用,以便下面的绘图显示出来。例如——运行这个程序来看看我的意思: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);
心有法竹
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); }}