有没有更好的方法来设置 JPanel 图形的初始位置?)

2023-12-12

在梁的第15章中Java 编程简介(第七版),他介绍了一个程序,可以在 JPanel 上制作一个(2-D)球,并通过单击放大/缩小按钮来放大它。我修改了程序,以便它还可以 1)在用户单击/选项+单击时放大/缩小球,2)允许您通过按下按钮来选择球的颜色,3)允许您移动球用鼠标拖动圆圈。

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

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

更重要的是,是否有更好(但也相对简单)的方法来做到这一点,而不涉及设置计数器?

以下是相关代码:

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;

    ...

move 方法(响应 MouseDragged 事件):

public void move(MouseEvent e){

        ballX = e.getX() - radius;
        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++;

}

完整程序:

// 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++;

        }

    }

}

有几点值得注意:

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

  • 使用该几何形状来确定球的初始位置。

  • Invoke pack() and then设置位置和可见性。

  • Use Action封装菜单和控件共享的代码。

  • 始终如一地使用适配器。

  • Use 初始线程正确。

  • 看到这个,它从多个角度审视了一个相关的例子。

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);
                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);
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有没有更好的方法来设置 JPanel 图形的初始位置?) 的相关文章

随机推荐

  • Javascript - 日期范围验证

    我有一个表单用户可以输入任何日期 但我想设置一个日期范围验证 例如 从2012年12月1日到2013年1月1日 系统无法接受不在该范围内的用户的任何日期 我已经尝试过这个javascript代码 但它甚至没有给我任何警报当日期不在范围内时
  • 访问 C#.net 中的 webbrowser 控件中呈现的框架

    我需要获取 C net 中的 webbrowser 控件呈现的页面中的链接 问题是我认为该页面使用框架 这就是为什么我无法从网络浏览器获取任何链接 我如何访问或查看网络浏览器控件中的那些框架 你可以使用Frames财产 webBrowser
  • 函数属性与泛型的 TypeScript 组合

    此类型的要点是允许用户传入数据 颜色 hasColor or 数据 信息 hasInfo 不是任何其他组合 type Props data string info string hasInfo boolean color never has
  • Python Plotly 图表更新有两个下拉菜单

    我正在尝试在 Jupyter Lab 中构建一个绘图散点图 以便能够查看 DataFrame 中各个列之间的依赖关系 我想要两个下拉菜单 对应于 X 轴和 Y 轴 每个菜单中都有 DF 列的完整列表 当我在任何菜单中选择一列时 相应轴上的数
  • iOS 基本 FTP 设置;读写流

    我正在尝试创建一个具有一些非常基本的 FTP 功能的 iOS 5 应用程序 并且需要一些指导 它将连接到本地网络上的设备并使用 dat txt 文件执行读 写操作 在过去的几天里 我进行了一些搜索 并看到了各种建议 但没有什么足够简单 我可
  • 如何实现“回收站”功能?

    我正在开发一个 Java 桌面应用程序 需要在其中实现回收站功能 现在 我使用桌面应用程序将文件复制到名为回收站的文件夹中 然后删除原始文件 我将目标路径存储在一个文本文件中 其中文件被删除 只是为了将文件恢复到原始位置 恢复文件时 我只是
  • 如何使用 mysql 创建每周队列分析表?

    假设您有一个用户表 其中至少包含用户注册的日期和 ID 现在 假设您有一个单独的表 用于跟踪可能在用户生命周期中的任何时刻发生的操作 例如付款 比如应用内购买 在该表中 我们跟踪用户 ID 付款日期和付款 ID 所以我们有类似这样的东西来设
  • 使用地理编码初始化 React Google Maps StandaloneSearchBox

    有人可以告诉我如何使用类型初始化React Google Maps的StandaloneSearchBox组件 geocode 就像原始的google maps places Autocomplete一样 这样我就可以限制自动完成的输入建议
  • 使用 Json.Net 在 C# 中解析 Json

    Posts id 1 title Bibidh prothom khondo content sjih sdkljjdsf kdjsfjks author last update 23 june 2013 Comments id 1 con
  • 复选框 + Jquery 隐藏/显示

    我有一系列的行和复选框来过滤它们 ul li li ul
  • 表中可编辑字段之间的 Tab 键切换

    我正在使用这里的代码http www korvus com blog geek making the tab key work with jeditable fields 在 jeditable 字段之间进行制表符工作 如果这些字段是独立的
  • INSERT 语句与 FOREIGN KEY 约束“FK_PostTag_Tag_TagId”冲突

    我在用实体框架 7 RC1我有实体 public class Post public Int32 Id get set public String Title get set public virtual IList
  • 最后进入异常处理

    到底是什么作用finally阻止异常处理执行 它保存应该始终执行的代码 无论是否发生异常 例如 如果您打开了一个文件 则应该在finally阻止以确保它始终处于关闭状态 如果您将其关闭try块 较早的异常将导致执行直接跳转到catch阻止并
  • Shunting-Yard VS 递归下降解析器

    我正在构建一个高级数学解析器 并且想知道 Shunting Yard 和其他可用解析器算法 例如 Descent Parser 之间的区别 因为我更喜欢以 RPN 表示法存储公式 提前致谢 我从来没有太多使用 调车场 算法 因为它似乎只关注
  • 如何为从 NIB 加载的 NSWindow 提供焦点?

    我在用着NSWindowController从 NIB 加载窗口 然而 当我打电话时showWindow 该窗口在视觉上位于最上面 但焦点仍保持在原来的位置 而不是将其移动到新窗口 It s easy to see this happeni
  • java中的日历日期为yyyy-MM-dd格式

    如何将日历日期转换为yyyy MM dd format Calendar cal Calendar getInstance cal add Calendar DATE 1 Date date cal getTime SimpleDateFo
  • 为什么 pytesseract 不能识别单个数字?

    I am performing ocr on a site and specifically on these two images 我对 OCR 相当陌生 我使用以下内容 from PIL import Image import pyte
  • 如何使用 jQuery 增加数量字段的值?

    我有一个带有一些数量字段的表格 每一侧都有一个加号和减号
  • .NET 中的网络文件复制

    我有一个运行 Samba 共享的 Ubuntu 盒子 向所有人开放 我可以通过 ip 地址访问它 所以我知道我可以完全访问它 在我的应用程序中 我正在尝试以下操作 但它无法通过 IP 地址 仅 DNS 名称 工作 val ip addres
  • 有没有更好的方法来设置 JPanel 图形的初始位置?)

    在梁的第15章中Java 编程简介 第七版 他介绍了一个程序 可以在 JPanel 上制作一个 2 D 球 并通过单击放大 缩小按钮来放大它 我修改了程序 以便它还可以 1 在用户单击 选项 单击时放大 缩小球 2 允许您通过按下按钮来选择