简体   繁体   中英

In Java Swing, how can I use JSliders to set x and y values for a shape?

I am trying to make a GUI that uses 2 JSliders; 1 vertical and 1 horizontal. I want them to return the x and y value respectively. I was able to get the x and y values, I just can't figure out how to use them so I can draw a circle.

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

I don't have anything more to ask or say about my question, I just can't submit this question because there is more code than not. So here is another question... How could I use a JComboBox to change the color of the circle based on what color is selected?

Introduction

Using a GUI builder creates a code mess that's hard to expand and hard to maintain. It's a lot easier, in the long run, to learn how to use Swing effectively without using a GUI builder. Oracle has a helpful tutorial, Creating a GUI With Swing . Skip the Learning Swing with the NetBeans IDE section.

I couldn't get your code to run in my IDE, so I went ahead and created the following GUI.

JSlider 示例

The top line displays the circle center point and allows you to select a color. The two JSliders allow you to select the center point x and the center point y of the circle. The scale goes from 0 to width and height, respectively. The code keeps you from selecting a center point outside the bounds of the drawing JPanel .

Since the y value JSlider has the minimum value on the bottom, I inverted the y value when drawing the circle. In other words, instead of the normal y values increasing as you draw downward, the y values increase as you draw upward.

The JSliders don't precisely correspond with the drawing JPanel. Since this is an example, I wasn't too worried about the visual discrepancy.

If you maximize the GUI or change the size of the GUI, the scales of the JSliders change accordingly. If your circle is outside the new dimension of the drawing JPanel, the center point is changed so the circle is inside the new dimension.

Explanation

When I create a Swing GUI, I use the model-view-controller pattern. This pattern allows me to separate my concerns and focus on one part of the application at a time.

Generally, you create the model first. The model consists of one or more plain Java getter/setter classes. The view is your JFrame and JPanels . The controllers are each individual Swing listener.

For this JSlider example, I created two model classes, two view classes, and four controller classes. Since all the controller classes are small, I made them anonymous classes.

This application turned out to be fairly complex. It's going to require a good bit of explanation.

Model

For this JSlider example, I created two model classes, JSliderExampleModel and ColorModel .

JSliderExampleModel is the main model class. It holds an array of ColorModels , the drawing JPanel dimension, and the center point and radius of the circle. The array of ColorModels is for the JComboBox . The radius is in the model because we need the value to keep the JSlider values from going outside the bounds of the drawing JPanel .

The ColorModel class holds a String color name and a Color color. This allows us to display the color name in the JComboBox while having the actual Color for filling in the circle in the drawing JPanel .

View

All Swing applications must start with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread .

The JFrame has a default BorderLayout , which I used to place four JPanels . It's a good idea to create the JFrame and JPanels in separate methods or classes. This helps keep the view code organized and makes the code easier to read and follow.

The JFrame creation methods must be called in a specific order . The run method of the JSliderExample class has the order I use for most of my Swing JFrames .

I created four JPanels ; the display JPanel , the drawing JPanel , and the two JSlider JPanels . The drawing JPanel is a separate class. The other three JPanels are methods in the main view class.

The display JPanel displays the circle center point and contains the JComboBox that allows the user to select a circle color. The display JPanel uses a FlowLayout to place all the Swing components on one line. The only "trick" I used was to add a Box horizontal strut (space) in between the circle center point and the color selection. This makes the GUI look a little nicer.

The drawing JPanel extends JPanel and overrides the paintComponent method. The super.paintComponent call must be first to maintain the Swing paint chain. The paintComponent method draws the circle.

I invert the Y value so that the circle drawing corresponds with the Y JSlider .

The JSlider JPanels both use a BorderLayout . I added a JLabel and added tick marks and values to the JSliders . I start the JSliders at zero so the labels are round numbers, even though the code keeps you from selecting values outside the drawing JPanel .

Controller

I created a ChangeListener for each of the JSliders and an ActionListener for the JComboBox . I also created a ComponentListener for the JFrame . Because I created an application model, these Swing listeners turned out to be fairly simple.

The ChangeListeners test for the slider moving and wait until the slider stops to redraw the circle.

I get the actual size of the drawing JPanel in the JFrame ComponentListener and save it in the model. This allows the user to maximize and minimize the GUI, as well as change the size of the GUI.

Code

Here's the complete runnable code. I made the additional classes inner classes so I could post the code as one block.

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 java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

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(model);
        this.xSliderPanel = createHorizontalSliderPanel();
        this.ySliderPanel = createVerticalSliderPanel();
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("JSlider Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent event) {
                Dimension drawingAreaDimension = drawingPanel.getSize();
                model.setDrawingAreaDimension(drawingAreaDimension);
                updateSliders();
            }
        });

        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 JSliderExampleModel model;

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

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

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

    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM