简体   繁体   中英

Why won't my shapes draw on the JFrame?

I'm trying to get a specific shape to draw based on what the user clicks. Every other method in the program is working fine. Here is a picture of what shows up currently: 这是图片

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import java.awt.*;
import java.awt.event.*;

public class Gui3 extends JFrame {
    private JPanel mousepanel;
    private JLabel statusbar;
    private JList list;
    private static String[] colornames = {"black","blue","red","white"};
    private static Color[] colors = {Color.BLACK, Color.BLUE,Color.RED,Color.WHITE};
    private JCheckBox cb;
    private JCheckBox rect;
    private JCheckBox oval;
    private JCheckBox drawBox;
    private boolean changeColor = true;
    private boolean ableToDraw = true;

    public Gui3(){
        super("The title");

        list = new JList(colornames);
        list.setVisibleRowCount(4);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.setFixedCellHeight(15);
        list.setFixedCellWidth(100);
        add(new JScrollPane(list), BorderLayout.WEST);
        list.addListSelectionListener(
                new ListSelectionListener(){
                    public void valueChanged(ListSelectionEvent event){
                        if(changeColor==true){
                        mousepanel.setBackground(colors[list.getSelectedIndex()]);
                        }
                        else{

                        }
                    }
                }
            );
        rect= new JCheckBox("Draw a rectangle");
        oval= new JCheckBox("Draw a oval");
        cb = new JCheckBox("Not able to change the color");
        drawBox = new JCheckBox("Not able to draw shapes");
        mousepanel = new JPanel();
        mousepanel.setBackground(Color.WHITE);
        add(mousepanel, BorderLayout.CENTER);
        add(drawBox, BorderLayout.EAST);
        add(cb, BorderLayout.NORTH);
        mousepanel.add(rect,BorderLayout.EAST);
        mousepanel.add(oval,BorderLayout.WEST);


        statusbar = new JLabel("Default");
        add(statusbar, BorderLayout.SOUTH); 


        HandlerClass handler = new HandlerClass();
        mousepanel.addMouseListener(handler);
        mousepanel.addMouseMotionListener(handler);
        cb.addItemListener(handler);
        drawBox.addItemListener(handler);
    }   
    private class HandlerClass implements MouseListener, MouseMotionListener,ItemListener
        {
        @Override
        public void mouseClicked(MouseEvent event) {
            statusbar.setText(String.format("Clicked at %d, %d", event.getX(),event.getY()));

This is where what is selected is used to decided what to draw. It works by passing parameters to a method is the drawShape class; shown down below.

if(ableToDraw==true){
                if(rect.isSelected()&&oval.isSelected()){
                    DrawShapes shapes = new DrawShapes();
                    shapes.whatToDraw(false,false);
                        }
                    }
                else if(rect.isSelected()){
                    DrawShapes shapes = new DrawShapes();
                    shapes.whatToDraw(true, false);
                    shapes.setPosition(event.getX(), event.getY());
                    add(shapes);

                }
                else if(oval.isSelected()){
                    DrawShapes shapes = new DrawShapes();
                    shapes.whatToDraw(false, true);
                    shapes.setPosition(event.getX(), event.getY());
                    add(shapes);
                }
                else{
                    DrawShapes shapes = new DrawShapes();
                    shapes.whatToDraw(false,false);
                }
            }
            @Override
            public void mousePressed(MouseEvent event){
                statusbar.setText("You pressed down the mouse");
            }

            @Override
            public void mouseReleased(MouseEvent event){
                statusbar.setText("You released the button");
            }
            @Override
            public void mouseEntered(MouseEvent event){
                statusbar.setText("You entered the area");

            }
            @Override
            public void mouseExited(MouseEvent event){
                statusbar.setText("The mouse has left the window");

            }
            //These are mouse motion events
            @Override
            public void mouseDragged(MouseEvent event){
                statusbar.setText("You are dragging the mouse");
            }
            @Override
            public void mouseMoved(MouseEvent event){
                statusbar.setText("You are moving the mouse");
            }
            @Override
            public void itemStateChanged(ItemEvent event){
                if(cb.isSelected()){
                    changeColor=false;
                }
                else{
                    changeColor=true;
                }
                if(drawBox.isSelected()){
                    ableToDraw=false;
                }
                else{
                    ableToDraw=true;
                }
            }

        }
    }

This is the drawShapes class

  import java.awt.*;
    import javax.swing.*;
    public class DrawShapes extends JPanel {
        private int x,y;
        private boolean ovals,rects;
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            if(ovals==false&&rects==true){
            g.setColor(Color.BLUE);
            g.fillRect(x,y,15,15);}
            else if(ovals==true&&rects==false){
                g.setColor(Color.BLUE);
                g.fillOval(x, y, 30, 15);
            }
            else{

            }
        }
        public void setPosition(int newX, int newY) {
            this.x = newX;
            this.y = newY;
            repaint();
        }

            public void whatToDraw(boolean newrects, boolean newovals){
                this.ovals=newovals;
                this.rects=newrects;
                repaint();


        }
    }

I would guess the problem is that you don't override the getPreferredSize() method of your DrawShapes class so there is nothing to paint. So you need to override the getPreferredSize() to return the actual size of your shape which in your case would appear to be (x + 30, y + 15) for your ovals and (x + 15, y + 15) rectangles.

You really should have separate classes for rectangles and ovals. Using if/else statements is not a good design and is not very flexible if you decide to add a "triangle" shape as your logic gets much more complicated.

However even if you do that you won't get what you expect because I'm guessing you add the DrawShapes component to a panel which by default is using a FlowLayout. So your shapes will just be displayed in a row on the panel, not where you click on the panel.

If you want the component to appear where you click then you need to set the size of the oval component to (30, 15) and the location of the component to (x, y). The painting of the shape would then be done at (0, 0) so the painting is relative to the component, not the panel. Then you need to set the layout of panel to null, so you can manually position each shape based on its location.

The other option is to not use real components, but just draw the shape onto a panel. Check out Custom Painting Approaches for examples of the two common ways incremental painting. It shows two different ways to do this depending on your exact requirement.

The examples show how to add Rectangles and you click/drag the mouse. So you need to modify the code to support different types of Shapes.

First I had to create a single instance of the drawShapes class, as stated by another user. Then the other part was that I messed up the logic, you should be able to draw only when ableToDraw==false meaning the button saying "not able to draw" isn't selected. That was bad naming on my part. Once that is done the code works fine.

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