在 Java 中为新图形清除屏幕 (awt)

Posted

技术标签:

【中文标题】在 Java 中为新图形清除屏幕 (awt)【英文标题】:Clearing the screen for new graphics in Java (awt) 【发布时间】:2022-01-06 18:56:16 【问题描述】:

我有这段代码,它基本上是一个带有两个可点击矩形的主菜单。

开始游戏 信息

开始游戏工作正常。 信息是没有真正起作用的。按下时,会出现信息屏幕,但主菜单按钮仍然存在,虽然不可见(可以单击).. 似乎当信息菜单出现时,主菜单按钮没有被清除。 此外,信息菜单上的任何点都是可点击的,并将再次显示主菜单。 (不是预期的,只有后退按钮应该这样做)。

我该如何解决这些问题?

package test;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;



public class HomeMenu extends JComponent implements MouseListener, MouseMotionListener 

    private static final String GAME_TITLE = "BRICK DESTROY";
    private static final String START_TEXT = "START";
    private static final String INFO_TEXT = "INFO";
    private static final String howtoPlay = """
            1- Click Start\n
            2- Choose the mode\n
            3- Each mode has 3 levels\n
            4- To play/pause press space, use 'A' and 'D' to move\n
            5- To open pause menu press 'ESC'\n
            6- To open DebugPanel press 'ALT-SHIFT-F1'""";
    private static final String backText = "BACK";

    private static final Color BORDER_COLOR = new Color(200,8,21); //Venetian Red
    private static final Color DASH_BORDER_COLOR = new  Color(255, 216, 0);//school bus yellow
    private static final Color TEXT_COLOR = new Color(255, 255, 255);//white
    private static final Color CLICKED_BUTTON_COLOR = Color.ORANGE.darker();;
    private static final Color CLICKED_TEXT = Color.ORANGE.darker();
    private static final int BORDER_SIZE = 5;
    private static final float[] DASHES = 12,6;


    private Rectangle menuFace;
    private Rectangle infoFace;
    private Rectangle startButton;
    private Rectangle infoButton;
    private Rectangle backButton;


    private BasicStroke borderStoke;
    private BasicStroke borderStoke_noDashes;
    private Image img =  Toolkit.getDefaultToolkit().createImage("1.jpeg");
    private Font gameTitleFont;
    private Font infoFont;
    private Font buttonFont;
    private Font howtoPlayFont;

    private GameFrame owner;

    private boolean startClicked;
    private boolean infoClicked = false;
    private boolean backClicked = false;


    public HomeMenu(GameFrame owner,Dimension area)

        this.setFocusable(true);
        this.requestFocusInWindow();

        this.addMouseListener(this);
        this.addMouseMotionListener(this);

        this.owner = owner;


        menuFace = new Rectangle(new Point(0,0),area);
        infoFace = new Rectangle(new Point(0,0),area);
        this.setPreferredSize(area);

        Dimension btnDim = new Dimension(area.width / 3, area.height / 12);
        startButton = new Rectangle(btnDim);
        infoButton = new Rectangle(btnDim);
        backButton = new Rectangle(btnDim);

        borderStoke = new BasicStroke(BORDER_SIZE,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND,0,DASHES,0);
        borderStoke_noDashes = new BasicStroke(BORDER_SIZE,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);


        gameTitleFont = new Font("Calibri",Font.BOLD,28);
        infoFont = new Font("Calibri",Font.BOLD,24);
        buttonFont = new Font("Calibri",Font.BOLD,startButton.height-2);
        howtoPlayFont = new Font("Calibri",Font.PLAIN,14);




    


    public void paint(Graphics g)
        drawMenu((Graphics2D)g);

    



    public void drawMenu(Graphics2D g2d)

        if(infoClicked) 
            drawInfoMenu(g2d);
            return;
        else
            drawContainer(g2d);

            Color prevColor = g2d.getColor();
            Font prevFont = g2d.getFont();

            double x = menuFace.getX();
            double y = menuFace.getY();


            g2d.translate(x,y);

            //methods calls
            drawText(g2d);
            drawButton(g2d);

            //end of methods calls

            g2d.translate(-x,-y);
            g2d.setFont(prevFont);
            g2d.setColor(prevColor);
        


        Toolkit.getDefaultToolkit().sync();

    



    private void drawContainer(Graphics2D g2d)
        Color prev = g2d.getColor();

        //g2d.setColor(BG_COLOR);
        g2d.drawImage(img,0,0,menuFace.width,menuFace.height,this);
        //g2d.fill(menuFace);

        Stroke tmp = g2d.getStroke();

        g2d.setStroke(borderStoke_noDashes);
        g2d.setColor(DASH_BORDER_COLOR);
        g2d.draw(menuFace);

        g2d.setStroke(borderStoke);
        g2d.setColor(BORDER_COLOR);
        g2d.draw(menuFace);

        g2d.setStroke(tmp);

        g2d.setColor(prev);
    

    private void drawText(Graphics2D g2d)

        g2d.setColor(TEXT_COLOR);

        FontRenderContext frc = g2d.getFontRenderContext();

        Rectangle2D gameTitleRect = gameTitleFont.getStringBounds(GAME_TITLE,frc);

        int sX,sY;

        sY = (int)(menuFace.getHeight() / 4);

        sX = (int)(menuFace.getWidth() - gameTitleRect.getWidth()) / 2;
        sY += (int) gameTitleRect.getHeight() * 1.1;//add 10% of String height between the two strings

        g2d.setFont(gameTitleFont);
        g2d.drawString(GAME_TITLE,sX,sY);


    

    private void drawButton(Graphics2D g2d)

        FontRenderContext frc = g2d.getFontRenderContext();

        Rectangle2D txtRect = buttonFont.getStringBounds(START_TEXT,frc);
        Rectangle2D mTxtRect = buttonFont.getStringBounds(INFO_TEXT,frc);

        g2d.setFont(buttonFont);

        int x = (menuFace.width - startButton.width) / 2;
        int y =(int) ((menuFace.height - startButton.height) * 0.5);

        startButton.setLocation(x,y);

        x = (int)(startButton.getWidth() - txtRect.getWidth()) / 2;
        y = (int)(startButton.getHeight() - txtRect.getHeight()) / 2;

        x += startButton.x;
        y += startButton.y + (startButton.height * 0.9);


        if(startClicked)
            Color tmp = g2d.getColor();
            g2d.setColor(CLICKED_BUTTON_COLOR);
            g2d.draw(startButton);
            g2d.setColor(CLICKED_TEXT);
            g2d.drawString(START_TEXT,x,y);
            g2d.setColor(tmp);
        
        else
            g2d.draw(startButton);
            g2d.drawString(START_TEXT,x,y);
        

        x = startButton.x;
        y = startButton.y;

        y *= 1.3;

        infoButton.setLocation(x,y);


        x = (int)(infoButton.getWidth() - mTxtRect.getWidth()) / 2;
        y = (int)(infoButton.getHeight() - mTxtRect.getHeight()) / 2;

        x += infoButton.getX();
        y += infoButton.getY() + (startButton.height * 0.9);

        if(infoClicked)
            Color tmp = g2d.getColor();
            g2d.setColor(CLICKED_BUTTON_COLOR);
            g2d.draw(infoButton);
            g2d.setColor(CLICKED_TEXT);
            g2d.drawString(INFO_TEXT,x,y);
            g2d.setColor(tmp);
        
        else
            g2d.draw(infoButton);
            g2d.drawString(INFO_TEXT,x,y);
        

    


    private void drawInfoMenu(Graphics2D g2d)

        FontRenderContext frc = g2d.getFontRenderContext();

        Rectangle2D infoRec = infoFont.getStringBounds(INFO_TEXT,frc);

        Color prev = g2d.getColor();


        Stroke tmp = g2d.getStroke();


        g2d.setStroke(borderStoke_noDashes);
        g2d.setColor(DASH_BORDER_COLOR);
        g2d.draw(infoFace);

        g2d.setStroke(borderStoke);
        g2d.setColor(BORDER_COLOR);
        g2d.draw(infoFace);

        g2d.fillRect(0,0,infoFace.width,infoFace.height);

        g2d.setStroke(tmp);

        g2d.setColor(prev);

        g2d.setColor(TEXT_COLOR);


        int sX,sY;

        sY = (int)(infoFace.getHeight() / 15);

        sX = (int)(infoFace.getWidth() - infoRec.getWidth()) / 2;
        sY += (int) infoRec.getHeight() * 1.1;//add 10% of String height between the two strings

        g2d.setFont(infoFont);
        g2d.drawString(INFO_TEXT,sX,sY);

        TextLayout layout = new TextLayout(howtoPlay, howtoPlayFont, frc);
        String[] outputs = howtoPlay.split("\n");
        for(int i=0; i<outputs.length; i++) 
            g2d.setFont(howtoPlayFont);
            g2d.drawString(outputs[i], 40, (int) (80 + i * layout.getBounds().getHeight() + 0.5));
        

        backButton.setLocation(getWidth()/3,getHeight()-50);


        int x = (int)(backButton.getWidth() - infoRec.getWidth()) / 2;
        int y = (int)(backButton.getHeight() - infoRec.getHeight()) / 2;

        x += backButton.x+11;
        y += backButton.y + (layout.getBounds().getHeight() * 1.35);

        backButton.setLocation(getWidth()/3,getHeight()-50);

        if(backClicked)
            Color tmp1 = g2d.getColor();
            g2d.setColor(CLICKED_BUTTON_COLOR);
            g2d.draw(backButton);
            g2d.setColor(CLICKED_TEXT);
            g2d.drawString(backText,x,y);
            g2d.setColor(tmp1);
            infoClicked = false;
            repaint();
        
        else
            g2d.draw(backButton);
            g2d.drawString(backText,x,y);
        


    

    @Override
    public void mouseClicked(MouseEvent mouseEvent) 
        Point p = mouseEvent.getPoint();
        if(startButton.contains(p))
           owner.enableGameBoard();

        
        else if(infoButton.contains(p))
            infoClicked = true;
        
        else if(backButton.contains(p))
            infoClicked = false;

        
        repaint();

    

    @Override
    public void mousePressed(MouseEvent mouseEvent) 
        Point p = mouseEvent.getPoint();
        if(startButton.contains(p))
            startClicked = true;
            repaint(startButton.x,startButton.y,startButton.width+1,startButton.height+1);

        
        else if(infoButton.contains(p))
            infoClicked = true;

        
        else if(backButton.contains(p))
            infoClicked = false;
        
        repaint();

    

    @Override
    public void mouseReleased(MouseEvent mouseEvent) 
        if(startClicked)
            startClicked = false;
            repaint(startButton.x,startButton.y,startButton.width+1,startButton.height+1);
        
        else if(infoClicked)
            infoClicked = false;
        
        else if(backClicked)
            infoClicked = true;
        
        repaint();
    

    @Override
    public void mouseEntered(MouseEvent mouseEvent) 

    

    @Override
    public void mouseExited(MouseEvent mouseEvent) 

    


    @Override
    public void mouseDragged(MouseEvent mouseEvent) 

    

    @Override
    public void mouseMoved(MouseEvent mouseEvent) 
        Point p = mouseEvent.getPoint();
        if(startButton.contains(p) || infoButton.contains(p) || backButton.contains(p)) 
            this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        
        else 
            this.setCursor(Cursor.getDefaultCursor());
        
    


这是两个窗口的图像 main menu

info menu, pressing anywhere = back to home menu, pressing roughly in the middle = start game or back to main menu too

【问题讨论】:

1.阅读 Performing Custom Painting 和 [在 AWT 和 Swing 中绘画](oracle.com/java/technologies/painting.html) 以更好地了解绘画的工作原理以及您应该如何使用它; 2. 将您的需求分解为单独的类/面板,并专注于他们的个人需求(即解耦和单一职责) 【参考方案1】:

首先阅读Performing Custom Painting 和Painting in AWT and Swing,以更好地了解在 Swing 中绘画的工作原理以及您应该如何使用它。

但我已经有了……

public void paint(Graphics g)
    drawMenu((Graphics2D)g);


否则会建议。说真的,请阅读这些链接,以便了解上述决定将为您带来的所有问题。

您正在使用 OO 语言进行操作,您需要利用它并解耦您的代码并专注于“单一职责”原则。

我有点厌倦了谈论它,所以你可以阅读一下:

https://softwareengineering.stackexchange.com/questions/244476/what-is-decoupling-and-what-development-areas-can-it-apply-to Cohesion and Decoupling, what do they represent? Single Responsibility Principle Single Responsibility Principle in Java with Examples SOLID Design Principles Explained: The Single Responsibility Principle

这些是您真正需要了解的基本概念,因为它们将使您的 SOOO 生活变得更加轻松,并且可以应用于几乎任何语言。

例如,从您的代码中...

public HomeMenu(GameFrame owner,Dimension area)
    //...
    this.setPreferredSize(area);

没有充分的理由(除了懒惰(恕我直言))任何调用者都应该告诉组件它应该是什么大小,这不是他们的责任。组件有责任告诉父容器它希望有多大,而父组件则负责弄清楚它将如何实现(或视情况而定)。

您遇到的“基本”问题很简单。您的“上帝”课程只是试图做太多事情(即承担了太多责任)。现在我们“可以”在代码中添加十几个或更多标志来弥补这一点,这只会增加耦合和复杂性,使其更难理解和维护,或者我们可以退后一步,将其分解为各个责任领域并围绕这些领域构建解决方案,例如...

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Test 

    public static void main(String[] args) 
        new Test();
    

    public Test() 
        EventQueue.invokeLater(new Runnable() 
            @Override
            public void run() 
                JFrame frame = new JFrame();
                frame.add(new HomePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            
        );
    

    public class HomePane extends JPanel 

        public HomePane() 
            setLayout(new BorderLayout());
            navigateToMenu();
        

        @Override
        public Dimension getPreferredSize() 
            return new Dimension(400, 400);
        

        protected void navigateToMenu() 
            removeAll();
            HomeMenuPane pane = new HomeMenuPane(new HomeMenuPane.NavigationListener() 
                @Override
                public void navigateToInfo(HomeMenuPane source) 
                    HomePane.this.navigateToInfo();
                

                @Override
                public void navigateToStartGame(HomeMenuPane source) 
                    startGame();
                
            );
            add(pane);
            revalidate();
            repaint();
        

        protected void navigateToInfo() 
            removeAll();
            HowToPlayPane pane = new HowToPlayPane(new HowToPlayPane.NavigationListener() 
                @Override
                public void navigateBack(HowToPlayPane source) 
                    navigateToMenu();
                
            );
            add(pane);
            revalidate();
            repaint();
        

        protected void startGame() 
            removeAll();
            add(new JLabel("This is pretty awesome, isn't it!", JLabel.CENTER));
            revalidate();
            repaint();
        

    

    public abstract class AbstractBaseMenuPane extends JPanel 

        protected static final Color BORDER_COLOR = new Color(200, 8, 21); //Venetian Red
        protected static final Color DASH_BORDER_COLOR = new Color(255, 216, 0);//school bus yellow
        protected static final Color TEXT_COLOR = new Color(255, 255, 255);//white
        protected static final Color CLICKED_BUTTON_COLOR = Color.ORANGE.darker();
        protected static final Color CLICKED_TEXT = Color.ORANGE.darker();
        protected static final int BORDER_SIZE = 5;
        protected static final float[] DASHES = 12, 6;

        private Rectangle border;

        private BasicStroke borderStoke;
        private BasicStroke borderStoke_noDashes;

        private BufferedImage backgroundImage;

        public AbstractBaseMenuPane() 
            borderStoke = new BasicStroke(BORDER_SIZE, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0, DASHES, 0);
            borderStoke_noDashes = new BasicStroke(BORDER_SIZE, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
            border = new Rectangle(new Point(0, 0), getPreferredSize());
            // You are now responsible for filling the background
            setOpaque(false);
        

        @Override
        public Dimension getPreferredSize() 
            return new Dimension(400, 400);
        

        @Override
        protected void paintComponent(Graphics g) 
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            BufferedImage backgroundImage = getBackgroundImage();
            if (backgroundImage != null) 
                g2d.drawImage(backgroundImage, 0, 0, getWidth(), getHeight(), this);
            

            Color prev = g2d.getColor();
            Stroke tmp = g2d.getStroke();

            g2d.setStroke(borderStoke_noDashes);
            g2d.setColor(DASH_BORDER_COLOR);
            g2d.draw(border);

            g2d.setStroke(borderStoke);
            g2d.setColor(BORDER_COLOR);
            g2d.draw(border);

            g2d.dispose();
        

        public void setBackgroundImage(BufferedImage backgroundImage) 
            this.backgroundImage = backgroundImage;
            repaint();
        

        public BufferedImage getBackgroundImage() 
            return backgroundImage;
        

    

    public class HomeMenuPane extends AbstractBaseMenuPane 

        public static interface NavigationListener 

            public void navigateToInfo(HomeMenuPane source);

            public void navigateToStartGame(HomeMenuPane source);
        

        private static final String GAME_TITLE = "BRICK DESTROY";
        private static final String START_TEXT = "START";
        private static final String INFO_TEXT = "INFO";

        private Rectangle startButton;
        private Rectangle infoButton;

        private Font gameTitleFont;
        private Font buttonFont;

        // Don't do this, this just sucks (for so many reasons)
        // Use ImageIO.read instead and save yourself a load of frustration
        //private Image img =  Toolkit.getDefaultToolkit().createImage("1.jpeg");

        private Point lastClickPoint;

        private NavigationListener navigationListener;

        public HomeMenuPane(NavigationListener navigationListener) 
            this.navigationListener = navigationListener;

            try 
                setBackgroundImage(ImageIO.read(getClass().getResource("/images/BrickWall.jpg")));
             catch (IOException ex) 
                Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
            

            this.addMouseListener(new MouseAdapter() 

                @Override
                public void mousePressed(MouseEvent mouseEvent) 
                    Point p = mouseEvent.getPoint();
                    lastClickPoint = p;
                    if (startButton.contains(p)) 
                        peformStartGameAction();
                     else if (infoButton.contains(p)) 
                        performInfoAction();
                    
                    repaint();
                

                @Override
                public void mouseReleased(MouseEvent mouseEvent) 
                    lastClickPoint = null;
                    repaint();
                
            );
            this.addMouseMotionListener(new MouseAdapter() 
                @Override
                public void mouseMoved(MouseEvent mouseEvent) 
                    Point p = mouseEvent.getPoint();
                    if (startButton.contains(p) || infoButton.contains(p)) 
                        setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                     else 
                        setCursor(Cursor.getDefaultCursor());
                    
                
            );

            Dimension area = getPreferredSize();

            Dimension btnDim = new Dimension(area.width / 3, area.height / 12);
            startButton = new Rectangle(btnDim);
            infoButton = new Rectangle(btnDim);

            gameTitleFont = new Font("Calibri", Font.BOLD, 28);
            buttonFont = new Font("Calibri", Font.BOLD, startButton.height - 2);
        

        @Override
        protected void paintComponent(Graphics g) 
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            Color prevColor = g2d.getColor();
            Font prevFont = g2d.getFont();

            //methods calls
            drawText(g2d);
            drawButton(g2d);

            //end of methods calls
            g2d.setFont(prevFont);
            g2d.setColor(prevColor);
            g2d.dispose();
        

        private void drawText(Graphics2D g2d) 
            g2d.setColor(TEXT_COLOR);

            FontRenderContext frc = g2d.getFontRenderContext();

            Rectangle2D gameTitleRect = gameTitleFont.getStringBounds(GAME_TITLE, frc);

            int sX, sY;

            sY = (int) (getHeight() / 4);

            sX = (int) (getWidth() - gameTitleRect.getWidth()) / 2;
            sY += (int) gameTitleRect.getHeight() * 1.1;//add 10% of String height between the two strings

            g2d.setFont(gameTitleFont);
            g2d.drawString(GAME_TITLE, sX, sY);

        

        private void drawButton(Graphics2D g2d) 

            FontRenderContext frc = g2d.getFontRenderContext();

            Rectangle2D txtRect = buttonFont.getStringBounds(START_TEXT, frc);
            Rectangle2D mTxtRect = buttonFont.getStringBounds(INFO_TEXT, frc);

            g2d.setFont(buttonFont);

            int x = (getWidth() - startButton.width) / 2;
            int y = (int) ((getHeight() - startButton.height) * 0.5);

            startButton.setLocation(x, y);

            x = (int) (startButton.getWidth() - txtRect.getWidth()) / 2;
            y = (int) (startButton.getHeight() - txtRect.getHeight()) / 2;

            x += startButton.x;
            y += startButton.y + (startButton.height * 0.9);

            if (lastClickPoint != null && startButton.contains(lastClickPoint)) 
                Color tmp = g2d.getColor();
                g2d.setColor(CLICKED_BUTTON_COLOR);
                g2d.draw(startButton);
                g2d.setColor(CLICKED_TEXT);
                g2d.drawString(START_TEXT, x, y);
                g2d.setColor(tmp);
             else 
                g2d.draw(startButton);
                g2d.drawString(START_TEXT, x, y);
            

            x = startButton.x;
            y = startButton.y;

            y *= 1.3;

            infoButton.setLocation(x, y);

            x = (int) (infoButton.getWidth() - mTxtRect.getWidth()) / 2;
            y = (int) (infoButton.getHeight() - mTxtRect.getHeight()) / 2;

            x += infoButton.getX();
            y += infoButton.getY() + (startButton.height * 0.9);

            if (lastClickPoint != null && infoButton.contains(lastClickPoint)) 
                Color tmp = g2d.getColor();
                g2d.setColor(CLICKED_BUTTON_COLOR);
                g2d.draw(infoButton);
                g2d.setColor(CLICKED_TEXT);
                g2d.drawString(INFO_TEXT, x, y);
                g2d.setColor(tmp);
             else 
                g2d.draw(infoButton);
                g2d.drawString(INFO_TEXT, x, y);
            

        

        protected void peformStartGameAction() 
            navigationListener.navigateToStartGame(this);
        

        protected void performInfoAction() 
            navigationListener.navigateToInfo(this);
        
    

    public class HowToPlayPane extends AbstractBaseMenuPane 

        public static interface NavigationListener 

            public void navigateBack(HowToPlayPane source);
        

        private static final String HOW_TO_PLAY_TEXT = """
            1- Click Start\n
            2- Choose the mode\n
            3- Each mode has 3 levels\n
            4- To play/pause press space, use 'A' and 'D' to move\n
            5- To open pause menu press 'ESC'\n
            6- To open DebugPanel press 'ALT-SHIFT-F1'""";
        private static final String BACK_TEXT = "BACK";
        private static final String INFO_TEXT = "INFO";

        private Rectangle backButton;
        private boolean backClicked = false;

        private Font infoFont;
        private Font howtoPlayFont;

        private NavigationListener navigationListener;

        public HowToPlayPane(NavigationListener navigationListener) 
            this.navigationListener = navigationListener;
            this.addMouseListener(new MouseAdapter() 
                @Override
                public void mousePressed(MouseEvent mouseEvent) 
                    Point p = mouseEvent.getPoint();
                    if (backButton.contains(p)) 
                        backClicked = true;
                        repaint();
                        performBackAction();
                    
                

                @Override
                public void mouseReleased(MouseEvent e) 
                    backClicked = false;
                
            );

            this.addMouseMotionListener(new MouseAdapter() 
                @Override
                public void mouseMoved(MouseEvent mouseEvent) 
                    Point p = mouseEvent.getPoint();
                    if (backButton.contains(p)) 
                        setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                     else 
                        setCursor(Cursor.getDefaultCursor());
                    
                
            );

            Dimension btnDim = new Dimension(getPreferredSize().width / 3, getPreferredSize().height / 12);
            backButton = new Rectangle(btnDim);

            infoFont = new Font("Calibri", Font.BOLD, 24);
            howtoPlayFont = new Font("Calibri", Font.PLAIN, 14);
        

        @Override
        public Dimension getPreferredSize() 
            return new Dimension(400, 400);
        

        @Override
        protected void paintComponent(Graphics g) 
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            g2d.setColor(BORDER_COLOR);
            g2d.fillRect(0, 0, getWidth(), getHeight());

            FontRenderContext frc = g2d.getFontRenderContext();
            Rectangle2D infoRec = infoFont.getStringBounds(INFO_TEXT, frc);
//
//            Color prev = g2d.getColor();
//
//            Stroke tmp = g2d.getStroke();
//
//            g2d.setStroke(borderStoke_noDashes);
//            g2d.setColor(DASH_BORDER_COLOR);
//            g2d.draw(infoFace);
//
//            g2d.setStroke(borderStoke);
//            g2d.setColor(BORDER_COLOR);
//            g2d.draw(infoFace);
//
//            g2d.fillRect(0, 0, infoFace.width, infoFace.height);
//
//            g2d.setStroke(tmp);
//
//            g2d.setColor(prev);
//
            g2d.setColor(TEXT_COLOR);

            int sX, sY;

            sY = (int) (getHeight() / 15);

            sX = (int) (getWidth() - infoRec.getWidth()) / 2;
            sY += (int) infoRec.getHeight() * 1.1;//add 10% of String height between the two strings

            g2d.setFont(infoFont);
            g2d.drawString(INFO_TEXT, sX, sY);

            TextLayout layout = new TextLayout(HOW_TO_PLAY_TEXT, howtoPlayFont, frc);
            String[] outputs = HOW_TO_PLAY_TEXT.split("\n");
            for (int i = 0; i < outputs.length; i++) 
                g2d.setFont(howtoPlayFont);
                g2d.drawString(outputs[i], 40, (int) (80 + i * layout.getBounds().getHeight() + 0.5));
            

            backButton.setLocation(getWidth() / 3, getHeight() - 50);

            int x = (int) (backButton.getWidth() - infoRec.getWidth()) / 2;
            int y = (int) (backButton.getHeight() - infoRec.getHeight()) / 2;

            x += backButton.x + 11;
            y += backButton.y + (layout.getBounds().getHeight() * 1.35);

            backButton.setLocation(getWidth() / 3, getHeight() - 50);

            if (backClicked) 
                Color tmp1 = g2d.getColor();
                g2d.setColor(CLICKED_BUTTON_COLOR);
                g2d.draw(backButton);
                g2d.setColor(CLICKED_TEXT);
                g2d.drawString(BACK_TEXT, x, y);
                g2d.setColor(tmp1);
                repaint();
             else 
                g2d.draw(backButton);
                g2d.drawString(BACK_TEXT, x, y);
            
            g2d.dispose();
        

        protected void performBackAction() 
            navigationListener.navigateBack(this);
        
    


现在,这个例子利用组件来呈现不同的视图(它甚至有一个很好的抽象实现来允许代码重用?),但我突然想到,如果你“真的”想要,你可以有一系列“画家”类,可用于将当前状态的绘画委托给,鼠标点击/移动可以委托给,这意味着您可以有一个组件,它可以简单地委托绘画(通过paintComponent 方法),painter 对其处于活动状态。

而且,你不知道吗,他们有一个设计原则,Delegation Pattern

上面的例子也使用了observer pattern,所以你可能也想看看

【讨论】:

以上是关于在 Java 中为新图形清除屏幕 (awt)的主要内容,如果未能解决你的问题,请参考以下文章

第六周总结

vb 执行Cls语句,将清除窗体上用Print方法输出的内容、用图形方法绘制的图形以及窗体

如何清除 Java 中的 JList?

SDL2:如何在不清除屏幕的情况下进行渲染

java实现画图和清屏功能.

Java:清除控制台