【问题标题】:In Java Swing, how can I use JSliders to set x and y values for a shape?在 Java Swing 中,如何使用 JSlider 为形状设置 x 和 y 值?
【发布时间】:2022-09-24 11:16:11
【问题描述】:

我正在尝试制作一个使用 2 个 JSlider 的 GUI; 1个垂直和1个水平。我希望他们分别返回 x 和 y 值。我能够得到 x 和 y 值,但我不知道如何使用它们,所以我可以画一个圆。

    import javax.swing.JSlider;
    import java.awt.*;
    public class MyFrame extends javax.swing.JFrame {
        private javax.swing.JPanel canvas;
        private javax.swing.JComboBox<String> colorBox;
        private javax.swing.JSlider horizontalSlider, verticalSlider;
        private javax.swing.JButton state;
        public MyFrame() {
            initComponents();
        }
        private void initComponents() {
    
            canvas = new javax.swing.JPanel();
            horizontalSlider = new javax.swing.JSlider();
            verticalSlider = new javax.swing.JSlider();
            colorBox = new javax.swing.JComboBox<>();
            state = new javax.swing.JButton();
            int diameter = 30;
            Color color;
    
            setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    
            canvas.setBackground(new java.awt.Color(250, 250, 250));
    
            javax.swing.GroupLayout canvasLayout = new javax.swing.GroupLayout(canvas);
            canvas.setLayout(canvasLayout);
            canvasLayout.setHorizontalGroup(
                    canvasLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGap(0, 0, Short.MAX_VALUE)
            );
            canvasLayout.setVerticalGroup(
                    canvasLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGap(0, 0, Short.MAX_VALUE)
            );
    
            horizontalSlider.addChangeListener(new javax.swing.event.ChangeListener() {
                public void stateChanged(javax.swing.event.ChangeEvent evt) {
                    horizontalSliderStateChanged(evt);
                }
            });
    
            verticalSlider.setOrientation(javax.swing.JSlider.VERTICAL);
            verticalSlider.addChangeListener(new javax.swing.event.ChangeListener() {
                public void stateChanged(javax.swing.event.ChangeEvent evt) {
                    verticalSliderStateChanged(evt);
                }
            });
    
            colorBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { \"Red\", \"Orange\", \"Yellow\", \"Green\" }));
    
            state.setText(\"Show\");
            state.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    stateActionPerformed(evt);
                }
            });
    
        

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup()
                                .addGap(7, 7, 7)
                                .addComponent(verticalSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(18, 18, 18)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(horizontalSlider, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addComponent(canvas, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addGroup(layout.createSequentialGroup()
                                                .addComponent(colorBox, javax.swing.GroupLayout.PREFERRED_SIZE, 400, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 92, Short.MAX_VALUE)
                                                .addComponent(state, javax.swing.GroupLayout.PREFERRED_SIZE, 157, javax.swing.GroupLayout.PREFERRED_SIZE)))
                                .addContainerGap())
        );
        layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup()
                                .addContainerGap()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                        .addComponent(verticalSlider, javax.swing.GroupLayout.DEFAULT_SIZE, 475, Short.MAX_VALUE)
                                        .addComponent(canvas, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                                .addGap(18, 18, 18)
                                .addComponent(horizontalSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(27, 27, 27)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(colorBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addComponent(state))
                                .addContainerGap(31, Short.MAX_VALUE))
    );

pack();

}// </editor-fold>

                        
    
        private void stateActionPerformed(java.awt.event.ActionEvent evt) {
            // TODO add your handling code here:
        }
    
        public void horizontalSliderStateChanged(javax.swing.event.ChangeEvent evt) {
            horizontalSlider = (JSlider) evt.getSource();
            int coordinateX = horizontalSlider.getValue();
            System.out.println(\"X: \" + coordinateX);
        }
    
        public void verticalSliderStateChanged(javax.swing.event.ChangeEvent evt) {
            verticalSlider = (JSlider) evt.getSource();
            int coordinateY = verticalSlider.getValue();
            System.out.println(\"Y: \" + coordinateY);
        }
    
        private void colorBoxActionPerformed(java.awt.event.ActionEvent evt,Color color) {
            if(colorBox.getSelectedItem() == \"Red\") {
                color = Color.RED;
                repaint();
            }
        }
    
        public void draw(Graphics2D g) {
            g.fillOval(horizontalSlider.getValue(),verticalSlider.getValue(),30, 30);
            //g.setColor(color.getColor);
        }
    
    }

关于我的问题,我没有什么要问或说的了,我只是不能提交这个问题,因为代码比没有的多。 所以这是另一个问题......我如何使用 JComboBox 根据选择的颜色来改变圆圈的颜色?

  • 首先,您需要学习如何进行自定义绘画。然后您可以添加逻辑以使用组合框和滑块。查看Custom Painting Approaches 中的几个示例。
  • 这实际上有很多内容 - 早在我构建 MVC 区域管理器 (sourceforge.net/p/tus/code/HEAD/tree/tjacobs/ui/shape) 的那一天,您可能想要查看,但无论如何,您可能需要一个用于您的 Shapes 的模型,一个用于显示它们的视图,以及用于单击和以其他方式操作它们的控制器。

标签: java swing


【解决方案1】:

介绍

使用 GUI 构建器会造成难以扩展和维护的代码混乱。从长远来看,学习如何在不使用 GUI 构建器的情况下有效地使用 Swing 要容易得多。 Oracle 有一个有用的教程,Creating a GUI With Swing。跳过使用 NetBeans IDE 学习摇摆部分。

我无法让您的代码在我的 IDE 中运行,因此我继续创建了以下 GUI。

顶行显示圆的中心点并允许您选择颜色。两个JSliders 允许您选择圆的中心点x 和中心点y。比例分别从 0 到宽度和高度。该代码使您无法选择绘图边界之外的中心点JPanel

由于y值JSlider底部有最小值,所以我在画圆的时候把y值倒过来了。换句话说,不是正常的 y 值随着您向下绘制而增加,而是 y 值随着您向上绘制而增加。

JSliders 与绘图 JPanel 不完全对应。由于这是一个示例,我并不太担心视觉差异。

如果您最大化 GUI 或更改 GUI 的大小,JSliders 的比例会相应更改。如果您的圆圈在绘图 JPanel 的新尺寸之外,则中心点会更改,因此圆圈位于新尺寸之内。

解释

当我创建一个 Swing GUI 时,我使用model-view-controller 模式。这种模式使我能够分离我的关注点并一次专注于应用程序的一个部分。

通常,您首先创建模型。该模型由一个或多个普通的 Java getter/setter 类组成。该视图是您的JFrameJPanels。控制器是每个单独的 Swing 侦听器。

对于这个JSlider 示例,我创建了两个模型类、两个视图类和三个控制器类。由于所有的控制器类都很小,我将它们设为匿名类。

事实证明,这个应用程序相当复杂。这将需要一个很好的解释。

模型

对于这个JSlider 示例,我创建了两个模型类,JSliderExampleModelColorModel

JSliderExampleModel 是主要的模型类。它包含ColorModels 的数组、绘图JPanel 维度以及圆的中心点和半径。 ColorModels 的数组用于 JComboBox。半径在模型中,因为我们需要该值来防止JSlider 值超出绘图JPanel 的边界。

ColorModel 类包含一个 String 颜色名称和一个 Color 颜色。这使我们可以在JComboBox 中显示颜色名称,同时将实际的Color 用于填充绘图JPanel 中的圆圈。

看法

所有 Swing 应用程序都必须以调用 SwingUtilities invokeLater 方法开始。此方法可确保在 Event Dispatch Thread 上创建和执行 Swing 组件。

JFrame 有一个默认的BorderLayout,我曾经放置四个JPanels。在单独的方法或类中创建JFrameJPanels 是个好主意。这有助于保持视图代码井井有条,并使代码更易于阅读和遵循。

JFrame的创建方法必须调用的是一个特定的命令. JSliderExample 类的 run 方法具有我用于大部分 Swing JFrames 的顺序。

我创建了四个JPanels;显示JPanel,绘图JPanel,以及两个JSliderJPanels。绘图JPanel 是一个单独的类。其他三个JPanels 是主视图类中的方法。

显示器JPanel 显示圆中心点并包含JComboBox,允许用户选择圆颜色。显示JPanel 使用FlowLayout 将所有Swing 组件放在一行上。我使用的唯一“技巧”是在圆中心点和颜色选择之间添加Box 水平支柱(空格)。这使 GUI 看起来更好一些。

绘图JPanel 扩展JPanel 并覆盖paintComponent 方法。 super.paintComponent 必须首先调用以维护 Swing 绘制链。 paintComponent 方法绘制圆。

我反转 Y 值,使圆图对应于 Y JSlider

我在paintComponent 方法中得到了图纸JPanel 的实际大小,并将其保存在模型中。这允许用户最大化和最小化 GUI,以及改变 GUI 的大小。

JSliderJPanels 都使用BorderLayout。我添加了JLabel 并向JSliders 添加了刻度线和值。我将JSliders 从零开始,因此标签是整数,即使代码阻止您选择绘图JPanel 之外的值。

控制器

我为每个JSliders 创建了一个ChangeListener,为JComboBox 创建了一个ActionListener。因为我创建了一个应用程序模型,所以这些 Swing 侦听器非常简单。

ChangeListeners 测试滑块移动并等待滑块停止重新绘制圆圈。

代码

这是完整的可运行代码。我将附加类作为内部类创建,以便我可以将代码作为一个块发布。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class JSliderExample implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new JSliderExample());
    }

    private final DrawingPanel drawingPanel;

    private final JSliderExampleModel model;

    private JComboBox<ColorModel> colorComboBox;

    private final JPanel xSliderPanel, ySliderPanel;

    private JSlider xSlider, ySlider;

    private JTextField xField, yField;

    public JSliderExample() {
        this.model = new JSliderExampleModel();
        this.drawingPanel = new DrawingPanel(this, model);
        this.xSliderPanel = createHorizontalSliderPanel();
        this.ySliderPanel = createVerticalSliderPanel();
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("JSlider Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createDisplayPanel(), BorderLayout.NORTH);
        frame.add(drawingPanel, BorderLayout.CENTER);
        frame.add(xSliderPanel, BorderLayout.SOUTH);
        frame.add(ySliderPanel, BorderLayout.EAST);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createDisplayPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));

        JLabel label = new JLabel("Center point:");
        panel.add(label);

        label = new JLabel("x:");
        panel.add(label);

        xField = new JTextField(5);
        xField.setEditable(false);
        panel.add(xField);

        label = new JLabel("y:");
        panel.add(label);

        yField = new JTextField(5);
        yField.setEditable(false);
        panel.add(yField);

        panel.add(Box.createHorizontalStrut(15));

        label = new JLabel("Color:");
        panel.add(label);

        colorComboBox = new JComboBox<>(model.getColors());
        colorComboBox.setSelectedIndex(0);
        colorComboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                model.setCircleColor(
                        (ColorModel) colorComboBox.getSelectedItem());
                repaint();
            }
        });
        panel.add(colorComboBox);

        updateDisplayPanel();

        return panel;
    }

    private JPanel createHorizontalSliderPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));

        JLabel label = new JLabel("Center x value");
        panel.add(label, BorderLayout.NORTH);

        Dimension d = model.getDrawingAreaDimension();
        Point p = model.getCenterPoint();
        xSlider = new JSlider(JSlider.HORIZONTAL, 0, d.width, p.x);
        xSlider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent event) {
                JSlider source = (JSlider) event.getSource();
                if (!source.getValueIsAdjusting()) {
                    int x = (int) source.getValue();
                    updateCenterX(source, x);
                }
            }
        });
        xSlider.setMajorTickSpacing(50);
        xSlider.setMinorTickSpacing(10);
        xSlider.setPaintTicks(true);
        xSlider.setPaintLabels(true);

        panel.add(xSlider, BorderLayout.CENTER);

        return panel;
    }

    private JPanel createVerticalSliderPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));

        JLabel label = new JLabel("Center y value");
        panel.add(label, BorderLayout.NORTH);

        Dimension d = model.getDrawingAreaDimension();
        Point p = model.getCenterPoint();
        ySlider = new JSlider(JSlider.VERTICAL, 0, d.height, p.y);
        ySlider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent event) {
                JSlider source = (JSlider) event.getSource();
                if (!source.getValueIsAdjusting()) {
                    int y = (int) source.getValue();
                    updateCenterY(source, y);
                }
            }
        });
        ySlider.setMajorTickSpacing(50);
        ySlider.setMinorTickSpacing(10);
        ySlider.setPaintTicks(true);
        ySlider.setPaintLabels(true);
        panel.add(ySlider, BorderLayout.CENTER);

        return panel;
    }

    public void updateDisplayPanel() {
        Point p = model.getCenterPoint();
        xField.setText(String.format("%,d", p.x));
        yField.setText(String.format("%,d", p.y));
    }

    public void updateSliders() {
        Dimension d = model.getDrawingAreaDimension();
        Point p = model.getCenterPoint();
        xSlider.setMaximum(d.width);
        ySlider.setMaximum(d.height);

        xSliderPanel.revalidate();
        xSliderPanel.repaint();
        ySliderPanel.revalidate();
        ySliderPanel.repaint();
    }

    private void updateCenterX(JSlider source, int x) {
        Dimension d = model.getDrawingAreaDimension();
        Point p = model.getCenterPoint();
        int radius = model.getRadius();

        x = Math.max(radius, x);
        x = Math.min(d.width - radius, x);
        source.setValue(x);

        model.setCenterPoint(new Point(x, p.y));
        updateDisplayPanel();
        repaint();
    }

    private void updateCenterY(JSlider source, int y) {
        Dimension d = model.getDrawingAreaDimension();
        Point p = model.getCenterPoint();
        int radius = model.getRadius();

        y = Math.max(radius, y);
        y = Math.min(d.height - radius, y);
        source.setValue(y);

        model.setCenterPoint(new Point(p.x, y));
        updateDisplayPanel();
        repaint();
    }

    public void repaint() {
        drawingPanel.repaint();
    }

    public class DrawingPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        private final JSliderExample view;

        private final JSliderExampleModel model;

        public DrawingPanel(JSliderExample view, JSliderExampleModel model) {
            this.view = view;
            this.model = model;
            this.setPreferredSize(model.getDrawingAreaDimension());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Dimension drawingAreaDimension = this.getSize();
            model.setDrawingAreaDimension(drawingAreaDimension);
            view.updateSliders();

            ColorModel colorModel = model.getCircleColor();
            g.setColor(colorModel.getColor());
            Dimension d = model.getDrawingAreaDimension();
            Point p = model.getCenterPoint();
            int radius = model.getRadius();
            int diameter = radius + radius;
            g.fillOval(p.x - radius, d.height - p.y - radius, diameter,
                    diameter);
        }

    }

    public class JSliderExampleModel {

        private final int radius;

        private ColorModel circleColor;

        private final ColorModel[] colors;

        private Dimension drawingAreaDimension;

        private Point centerPoint;

        public JSliderExampleModel() {
            this.drawingAreaDimension = new Dimension(400, 300);
            this.centerPoint = new Point(200, 150);
            this.radius = 32;

            this.colors = new ColorModel[4];
            this.colors[0] = new ColorModel("Blue", Color.blue);
            this.colors[1] = new ColorModel("Green", Color.green);
            this.colors[2] = new ColorModel("Red", Color.red);
            this.colors[3] = new ColorModel("Yellow", Color.yellow);
            this.circleColor = colors[0];
        }

        public ColorModel getCircleColor() {
            return circleColor;
        }

        public void setCircleColor(ColorModel circleColor) {
            this.circleColor = circleColor;
        }

        public Dimension getDrawingAreaDimension() {
            return drawingAreaDimension;
        }

        public void setDrawingAreaDimension(Dimension drawingAreaDimension) {
            this.drawingAreaDimension = drawingAreaDimension;
        }

        public Point getCenterPoint() {
            return centerPoint;
        }

        public void setCenterPoint(Point centerPoint) {
            this.centerPoint = centerPoint;
        }

        public ColorModel[] getColors() {
            return colors;
        }

        public int getRadius() {
            return radius;
        }

    }

    public class ColorModel {

        private final Color color;

        private final String colorName;

        public ColorModel(String colorName, Color color) {
            this.colorName = colorName;
            this.color = color;
        }

        public Color getColor() {
            return color;
        }

        public String getColorName() {
            return colorName;
        }

        @Override
        public String toString() {
            return colorName;
        }

    }

}

【讨论】:

    猜你喜欢
    • 2019-03-03
    • 1970-01-01
    • 1970-01-01
    • 2015-05-13
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    相关资源
    最近更新 更多