有没有更好的方法来设置JPanel图形的初始位置?) [英] Is there a better way to set an initial position for a JPanel graphic?)

查看:168
本文介绍了有没有更好的方法来设置JPanel图形的初始位置?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Liang的Java编程简介(第7版)的第15章中,他介绍了一个在JPanel上制作(2-D)球的程序,并在点击放大/缩小按钮。我修改了程序,它也可以1)放大/缩小球,如果用户点击/选项+点击,2)允许你通过按一下按钮选择球的颜色,3)允许你移动通过用鼠标拖动圈子。



最后一个修改是什么让我麻烦了一段时间,因为我想把球放在一开始,然后允许用户用鼠标移动球。我想出的解决方案是使paintComponent方法仅在第一次绘制时设置相对于getWidth()和getHeight()的球的x坐标和y坐标。为此,我向BallCanvas类添加了一个paintCount变量,并创建了一个if语句,以便它只会在第一次执行。当我试图弄清楚如何做到这一点,我看到其他解决方案,如这里给出的:为什么我无法访问我的面板的getWidth()和getHeight()函数?,但我发现我的解决方案更简单。



所以问题是:我是否认为坏的编码风格?专业程序员会否嘲笑这个解决方案?还是可以吗?



更重要的是,有没有一个更好的(但也是相对简单的)这样做,不涉及设置一个计数器?



以下是相关的代码段:



BallCanvas的开始: p>

  public static class BallCanvas extends JPanel {

private int radius = 20;
私人颜色color = Color.BLACK;
private int ballX;
private int ballY;
private int paintCount = 0;

...

移动方法(响应MouseDragged事件):

  public void move(MouseEvent e){

ballX = e.getX()半径;
ballY = e.getY() - radius;
repaint();

}

paintComponent方法:

  protected void paintComponent(Graphics g){

super.paintComponent(g);
g.setColor(color);
if(paintCount< 1){
ballX = getWidth()/ 2 - radius;
ballY = getHeight()/ 2 - radius;
}
g.fillOval(ballX,ballY,2 * radius,2 * radius);
paintCount ++;

}

完整程序:

  //参考:Liang的Java编程简介

import javax.swing。*;
import java.awt。*;
import java.awt.event。*;

public class ControlBall extends JFrame {

private JButton jbtRed = new JButton(Red);
private JButton jbtGreen = new JButton(Green);
private JButton jbtBlue = new JButton(Blue);
private JButton jbtBlack = new JButton(Black);
private BallCanvas canvas = new BallCanvas();
private JMenuBar menuBar = new JMenuBar();
private JMenu menu = new JMenu(Edit);
private JMenuItem miEnlarge = new JMenuItem(Enlarge);
private JMenuItem miShrink = new JMenuItem(Shrink);

public ControlBall(){

menuBar.add(menu);
menu.add(miEnlarge);
menu.add(miShrink);

JPanel panel = new JPanel();
panel.add(jbtRed);
panel.add(jbtGreen);
panel.add(jbtBlue);
panel.add(jbtBlack);

this.add(canvas,BorderLayout.CENTER);
this.add(panel,BorderLayout.SOUTH);
this.add(menuBar,BorderLayout.NORTH);

jbtRed.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.RED);
}
});

jbtGreen.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.GREEN);
}
});

jbtBlue.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.BLUE);
}
});

jbtBlack.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.BLACK);
}
});

miEnlarge.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
canvas.enlarge();
}
}) ;

miShrink.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
canvas.shrink();
}
}) ;

canvas.addMouseListener(new MouseListener(){
public void mouseClicked(MouseEvent e){
canvas.changeSize(e);
}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
});

canvas.addMouseMotionListener(new MouseMotionAdapter(){

public void mouseDragged(MouseEvent e){

canvas.move(e);

}
});

}

public static void main(String [] args){

JFrame frame = new ControlBall();
frame.setTitle(ControlBall);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,200);
frame.setVisible(true);

}

public static class BallCanvas扩展JPanel {

private int radius = 20;
私人颜色color = Color.BLACK;
private int ballX;
private int ballY;
private int paintCount = 0;

public BallCanvas(){

System.out.println(getWidth()++ getHeight());

}

public BallCanvas(int initialRadius){

radius = initialRadius;

}

public void setColor(Color color){

this.color = color;
repaint();

}

public void changeSize(MouseEvent e){

int numClicks = e.getClickCount();

if(e.isAltDown()){
if(radius> = 6){
this.radius - = 5 * numClicks;
} else {
// do nothing
}
} else {

this.radius + = 5 * numClicks;
}

repaint();

}

public void enlarge(){

this.radius + = 5;
repaint();

}

public void shrink(){

if(radius> = 10){
this.radius - = 5 ;
}
repaint();
}

public void move(MouseEvent e){

ballX = e.getX() - radius;
ballY = e.getY() - radius;
repaint();

}

protected void paintComponent(Graphics g){

super.paintComponent(g);
g.setColor(color);
if(paintCount< 1){
ballX = getWidth()/ 2 - radius;
ballY = getHeight()/ 2 - radius;
}
g.fillOval(ballX,ballY,2 * radius,2 * radius);
paintCount ++;

}

}

}


解决方案

值得注意的几件事:




  • 覆盖 getPreferredSize() 以建立面板的初始几何。


  • 调用 pack() 然后设置位置&


  • 使用 Action 来封装菜单和控件共享的代码。


  • 使用适配器。


  • 使用初始线程正确。


  • 看到这个 Q& A ,从几个角度审视了一个相关的例子。




< img src =https://i.stack.imgur.com/iwscr.pngalt =image>

  import javax.swing。*; 
import java.awt。*;
import java.awt.event。*;

public class ControlBall extends JFrame {

private JButton jbtRed = new JButton(Red);
private JButton jbtGreen = new JButton(Green);
private JButton jbtBlue = new JButton(Blue);
private JButton jbtBlack = new JButton(Black);
private BallCanvas canvas = new BallCanvas();
private JMenuBar menuBar = new JMenuBar();
private JMenu menu = new JMenu(Edit);
private JMenuItem miEnlarge = new JMenuItem(Enlarge);
private JMenuItem miShrink = new JMenuItem(Shrink);

public ControlBall(){

menuBar.add(menu);
menu.add(miEnlarge);
menu.add(miShrink);

JPanel panel = new JPanel();
panel.add(jbtRed);
panel.add(jbtGreen);
panel.add(jbtBlue);
panel.add(jbtBlack);

this.add(canvas,BorderLayout.CENTER);
this.add(panel,BorderLayout.SOUTH);
this.add(menuBar,BorderLayout.NORTH);

jbtRed.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.RED);
}
});

jbtGreen.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.GREEN);
}
});

jbtBlue.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.BLUE);
}
});

jbtBlack.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
canvas.setColor(Color.BLACK);
}
});

miEnlarge.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
canvas.enlarge();
}
});

miShrink.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
canvas.shrink();
}
});

canvas.addMouseListener(new MouseAdapter(){
@Override
public void mouseClicked(MouseEvent e){
canvas.changeSize(e);
}

@Override
public void mouseDragged(MouseEvent e){
canvas.move(e);
}
});
}

public static void main(String [] args){

EventQueue.invokeLater(new Runnable(){
@Override
public void run(){
JFrame frame = new ControlBall();
frame.setTitle(ControlBall);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
框架.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});

}

public static class BallCanvas extends JPanel {

private static final int SIZE = 400;
private int radius = 20;
私人颜色color = Color.BLACK;
private int ballX = SIZE / 2 - radius;
private int ballY = SIZE / 2 - radius;

public BallCanvas(){
System.out.println(getWidth()++ getHeight());
}

public BallCanvas(int initialRadius){
radius = initialRadius;
}

public void setColor(Color color){
this.color = color;
repaint();
}

public void changeSize(MouseEvent e){

int numClicks = e.getClickCount();

if(e.isAltDown()){
if(radius> = 6){
this.radius - = 5 * numClicks;
} else {
// do nothing
}
} else {

this.radius + = 5 * numClicks;
}

repaint();

}

public void enlarge(){

this.radius + = 5;
repaint();

}

public void shrink(){

if(radius> = 10){
this.radius - = 5 ;
}
repaint();
}

public void move(MouseEvent e){

ballX = e.getX() - radius;
ballY = e.getY() - radius;
repaint();

}

@Override
protected void paintComponent(Graphics g){

super.paintComponent(g);
g.setColor(color);
g.fillOval(ballX,ballY,2 *半径,2 *半径);

}

@Override
public Dimension getPreferredSize(){
return new Dimension(SIZE,SIZE);
}
}
}


In Chapter 15 of Liang's Intro to Java Programming (7th ed.), he introduces a program to make a (2-D) ball on a JPanel and enlarge it upon clicking enlarge/shrink buttons. I've modified the program so that it also 1) enlarges/shrinks the ball if the user clicks/option+clicks, 2) allows you to pick the color of the ball by pressing a button, and 3) allows you to move the circle by dragging it with your mouse.

The last modification is what was giving me trouble for a while, because I wanted to center the ball at the beginning, but then allow the user to move the ball around with the mouse. The solution I came up with was to have the paintComponent method only set the x- and y-coordinates of the ball relative to getWidth() and getHeight() the first time it paints. To do that, I added a paintCount variable to the BallCanvas class and made an if statement so that it would only execute the first time around. When I was trying to figure out how to do this initially, I saw other solutions, like the ones given here: Why can't I access my panel's getWidth() and getHeight() functions? , but I find my solution much simpler.

So the question is: is what I did considered bad coding style? Would a professional programmer scoff at this solution? Or is it OK?

More importantly, is there a better (but also, relatively simple) way to do this that doesn't involve setting up a counter?

Here are the relevant bits of code:

The beginning of BallCanvas:

public static class BallCanvas extends JPanel {

    private int radius = 20;
    private Color color = Color.BLACK;
    private int ballX;
    private int ballY;
    private int paintCount = 0;

    ...

The move method (which responds to a MouseDragged event):

public void move(MouseEvent e){

        ballX = e.getX() - radius;
        ballY = e.getY() - radius;
        repaint();

}

The paintComponent method:

protected void paintComponent(Graphics g){

        super.paintComponent(g);
        g.setColor(color);
        if(paintCount < 1){
            ballX = getWidth()/2 - radius;
            ballY = getHeight()/2 - radius;
        }
        g.fillOval(ballX, ballY, 2*radius, 2*radius);
        paintCount++;

}

Full program:

// Reference: Liang's Intro to Java Programming

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ControlBall extends JFrame{

    private JButton jbtRed = new JButton("Red");
    private JButton jbtGreen = new JButton("Green");
    private JButton jbtBlue = new JButton("Blue");
    private JButton jbtBlack = new JButton("Black");
    private BallCanvas canvas = new BallCanvas();
    private JMenuBar menuBar = new JMenuBar();
    private JMenu menu = new JMenu("Edit");
    private JMenuItem miEnlarge = new JMenuItem("Enlarge");
    private JMenuItem miShrink = new JMenuItem("Shrink");

    public ControlBall(){

        menuBar.add(menu);
        menu.add(miEnlarge);
        menu.add(miShrink);

        JPanel panel = new JPanel();
        panel.add(jbtRed);
        panel.add(jbtGreen);
        panel.add(jbtBlue);
        panel.add(jbtBlack);

        this.add(canvas, BorderLayout.CENTER);
        this.add(panel, BorderLayout.SOUTH);
        this.add(menuBar, BorderLayout.NORTH);

        jbtRed.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e){
                canvas.setColor(Color.RED);
            }
        });

        jbtGreen.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e){
                canvas.setColor(Color.GREEN);
            }
        });

        jbtBlue.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e){
                canvas.setColor(Color.BLUE);
            }
        });

        jbtBlack.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e){
                canvas.setColor(Color.BLACK);
            }
        });

        miEnlarge.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e){ 
                canvas.enlarge();
            }
        });

        miShrink.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e){ 
                canvas.shrink();
            }
        });

        canvas.addMouseListener(new MouseListener() {
            public void mouseClicked(MouseEvent e){
                canvas.changeSize(e);
            }
            public void mousePressed(MouseEvent e){}
            public void mouseReleased(MouseEvent e){}
            public void mouseEntered(MouseEvent e){}
            public void mouseExited(MouseEvent e){}
        });

        canvas.addMouseMotionListener(new MouseMotionAdapter() {

            public void mouseDragged(MouseEvent e) {

                canvas.move(e);

            }
        });

    }

    public static void main(String[] args){

        JFrame frame = new ControlBall();
        frame.setTitle("ControlBall");
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 200);
        frame.setVisible(true);

    }

    public static class BallCanvas extends JPanel {

        private int radius = 20;
        private Color color = Color.BLACK;
        private int ballX;
        private int ballY;
        private int paintCount = 0;

        public BallCanvas(){

            System.out.println(getWidth() + " " + getHeight());

        }

        public BallCanvas(int initialRadius){

            radius = initialRadius;

        }

        public void setColor(Color color){

            this.color = color;
            repaint();

        }

        public void changeSize(MouseEvent e){

            int numClicks = e.getClickCount();

            if(e.isAltDown()){
                if(radius >= 6){
                    this.radius -= 5*numClicks;
                } else{
                    // do nothing
                }
            } else{

                this.radius += 5*numClicks;
            }

            repaint();

        }

        public void enlarge(){

            this.radius += 5;
            repaint();

        }

        public void shrink(){

            if(radius >= 10){
                this.radius -= 5;
            }
            repaint();
        } 

        public void move(MouseEvent e){

            ballX = e.getX() - radius;
            ballY = e.getY() - radius;
            repaint();

        }

        protected void paintComponent(Graphics g){

            super.paintComponent(g);
            g.setColor(color);
            if(paintCount < 1){
                ballX = getWidth()/2 - radius;
                ballY = getHeight()/2 - radius;
            }
            g.fillOval(ballX, ballY, 2*radius, 2*radius);
            paintCount++;

        }

    }

}

解决方案

Several things merit attention:

  • Override getPreferredSize() to establish the panel's initial geometry.

  • Use that geometry to establish the ball's initial position.

  • Invoke pack() and then set the location & visibility.

  • Use Action to encapsulate code shared by menus and controls.

  • Use adapters consistently.

  • Use initial threads correctly.

  • See this Q&A, which examines a related example from several perspectives.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ControlBall extends JFrame {

    private JButton jbtRed = new JButton("Red");
    private JButton jbtGreen = new JButton("Green");
    private JButton jbtBlue = new JButton("Blue");
    private JButton jbtBlack = new JButton("Black");
    private BallCanvas canvas = new BallCanvas();
    private JMenuBar menuBar = new JMenuBar();
    private JMenu menu = new JMenu("Edit");
    private JMenuItem miEnlarge = new JMenuItem("Enlarge");
    private JMenuItem miShrink = new JMenuItem("Shrink");

    public ControlBall() {

        menuBar.add(menu);
        menu.add(miEnlarge);
        menu.add(miShrink);

        JPanel panel = new JPanel();
        panel.add(jbtRed);
        panel.add(jbtGreen);
        panel.add(jbtBlue);
        panel.add(jbtBlack);

        this.add(canvas, BorderLayout.CENTER);
        this.add(panel, BorderLayout.SOUTH);
        this.add(menuBar, BorderLayout.NORTH);

        jbtRed.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                canvas.setColor(Color.RED);
            }
        });

        jbtGreen.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                canvas.setColor(Color.GREEN);
            }
        });

        jbtBlue.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                canvas.setColor(Color.BLUE);
            }
        });

        jbtBlack.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                canvas.setColor(Color.BLACK);
            }
        });

        miEnlarge.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                canvas.enlarge();
            }
        });

        miShrink.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                canvas.shrink();
            }
        });

        canvas.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                canvas.changeSize(e);
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                canvas.move(e);
            }
        });
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new ControlBall();
                frame.setTitle("ControlBall");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });

    }

    public static class BallCanvas extends JPanel {

        private static final int SIZE = 400;
        private int radius = 20;
        private Color color = Color.BLACK;
        private int ballX = SIZE / 2 - radius;
        private int ballY = SIZE / 2 - radius;

        public BallCanvas() {
            System.out.println(getWidth() + " " + getHeight());
        }

        public BallCanvas(int initialRadius) {
            radius = initialRadius;
        }

        public void setColor(Color color) {
            this.color = color;
            repaint();
        }

        public void changeSize(MouseEvent e) {

            int numClicks = e.getClickCount();

            if (e.isAltDown()) {
                if (radius >= 6) {
                    this.radius -= 5 * numClicks;
                } else {
                    // do nothing
                }
            } else {

                this.radius += 5 * numClicks;
            }

            repaint();

        }

        public void enlarge() {

            this.radius += 5;
            repaint();

        }

        public void shrink() {

            if (radius >= 10) {
                this.radius -= 5;
            }
            repaint();
        }

        public void move(MouseEvent e) {

            ballX = e.getX() - radius;
            ballY = e.getY() - radius;
            repaint();

        }

        @Override
        protected void paintComponent(Graphics g) {

            super.paintComponent(g);
            g.setColor(color);
            g.fillOval(ballX, ballY, 2 * radius, 2 * radius);

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(SIZE, SIZE);
        }
    }
}

这篇关于有没有更好的方法来设置JPanel图形的初始位置?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆